From 134b6691cb57bb0089889faea2e4788bd450941e Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 28 Oct 2016 21:19:36 +0300 Subject: Add support for &dir/*** test path cleanup syntax --- build2/test/script/runner.cxx | 47 ++++++++++++++++++++++++++++++++++++++++++- build2/test/script/script | 24 ++++++++++++++++------ build2/test/script/script.cxx | 11 +--------- 3 files changed, 65 insertions(+), 17 deletions(-) (limited to 'build2/test') 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 (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 (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 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(). -- cgit v1.1