aboutsummaryrefslogtreecommitdiff
path: root/build2/test
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2016-10-28 21:19:36 +0300
committerBoris Kolpackov <boris@codesynthesis.com>2016-11-04 09:26:36 +0200
commit134b6691cb57bb0089889faea2e4788bd450941e (patch)
tree4cf89997580054c9b13677689501a5f47b74e833 /build2/test
parentbd6ebe8c2ca359fb201b84d9004b650d943b4d51 (diff)
Add support for &dir/*** test path cleanup syntax
Diffstat (limited to 'build2/test')
-rw-r--r--build2/test/script/runner.cxx47
-rw-r--r--build2/test/script/script24
-rw-r--r--build2/test/script/script.cxx11
3 files changed, 65 insertions, 17 deletions
diff --git a/build2/test/script/runner.cxx b/build2/test/script/runner.cxx
index 22ce67d..2174286 100644
--- a/build2/test/script/runner.cxx
+++ b/build2/test/script/runner.cxx
@@ -203,9 +203,22 @@ namespace build2
//
for (const auto& p: reverse_iterate (sp.cleanups))
{
+ // @@ Should we forbid removal of files and directories not inside
+ // the scope working directory? Inventing recursive removal makes
+ // cleanup a bit unsafe.
+ //
+
+ // Remove directory if exists and empty. Fail otherwise.
+ //
if (p.to_directory ())
{
dir_path d (path_cast<dir_path> (p));
+
+ // @@ If 'd' is a file then will fail with a diagnostics having no
+ // location info. Probably need to add an optional location
+ // parameter to rmdir() function. The same problem exists for a
+ // file cleanup when try to rmfile() directory instead of file.
+ //
rmdir_status r (rmdir (d, 2));
if (r != rmdir_status::success)
@@ -213,8 +226,40 @@ namespace build2
<< (r == rmdir_status::not_empty
? " is not empty"
: " does not exist");
+
+ continue;
}
- else if (rmfile (p, 2) == rmfile_status::not_exist)
+
+ // Remove directory recursively if not current. Fail otherwise.
+ // Recursive removal of non-existing directory is not an error.
+ //
+ // Note that if some file system entry of non-directory type exists
+ // with such a name it is not removed but the operation still
+ // succeeds. The removal of this entry can be handled at the time of
+ // the containing directory removed.
+ //
+ const string& s (p.string ());
+ size_t n (s.size ());
+
+ if (n >= 4 &&
+ string::traits_type::compare (
+ s.c_str () + n - 4, "/***", 4) == 0)
+ {
+ // Cast to uint16_t to avoid ambiguity with libbutl::rmdir_r().
+ //
+ rmdir_status r (
+ rmdir_r (p.directory (), true, static_cast<uint16_t> (2)));
+
+ if (r == rmdir_status::not_empty) // Directory is current.
+ fail (cl) << "registered for cleanup wildcard " << p
+ << " matches the current directory";
+
+ continue;
+ }
+
+ // Remove file if exists. Fail otherwise.
+ //
+ if (rmfile (p, 2) == rmfile_status::not_exist)
fail (cl) << "registered for cleanup file " << p
<< " does not exist";
}
diff --git a/build2/test/script/script b/build2/test/script/script
index 362f0df..c3b717f 100644
--- a/build2/test/script/script
+++ b/build2/test/script/script
@@ -171,8 +171,23 @@ namespace build2
optional<description> desc;
// Files and directories that must be automatically cleaned up when
- // the scope is left. If the path ends with a trailing slash, then it
- // is assumed to be to a directory, otherwise -- to a file.
+ // the scope is left. If the path contains '*' it is a wildcard. If the
+ // path is not a wildcard and ends with a trailing slash, then it is
+ // assumed to be to a directory, otherwise -- to a file. A directory
+ // must be empty by the time of removal,
+ //
+ // The supported wildcards:
+ //
+ // dir/*** - remove directory 'dir' with all files and sub-directories
+ // recursively. Removing non-existing 'dir' is not an error.
+ //
+ // The not yet supported wildcards:
+ //
+ // &dir/* - remove all immediate files of directory 'dir';
+ // &dir/*/ - remove all immediate sub-directories (must be empty);
+ // &dir/** - remove all files recursively;
+ // &dir/**/ - remove all sub-directories recursively (must be empty by
+ // the time of removal).
//
paths cleanups;
@@ -206,10 +221,7 @@ namespace build2
// Register path for cleanup. Suppress duplicates.
//
void
- clean (const path& p);
-
- void
- clean (path&& p);
+ clean (path p);
public:
virtual
diff --git a/build2/test/script/script.cxx b/build2/test/script/script.cxx
index f1dab63..058720a 100644
--- a/build2/test/script/script.cxx
+++ b/build2/test/script/script.cxx
@@ -291,16 +291,7 @@ namespace build2
// command
//
void scope::
- clean (const path& p)
- {
- using std::find; // Hidden by scope::find().
-
- if (find (cleanups.begin (), cleanups.end (), p) == cleanups.end ())
- cleanups.emplace_back (p);
- }
-
- void scope::
- clean (path&& p)
+ clean (path p)
{
using std::find; // Hidden by scope::find().