From 86576cdd3c8d959ffe93f49b7744a99164f172ee Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 8 Jul 2016 16:13:58 +0200 Subject: Move filesystem-related functions from context to new filesystem files --- build2/algorithm.cxx | 3 +- build2/b.cxx | 2 +- build2/buildfile | 1 + build2/cli/rule.cxx | 3 ++ build2/cli/target.cxx | 2 +- build2/config/module.cxx | 3 +- build2/config/operation.cxx | 3 +- build2/context | 71 ----------------------------- build2/context.cxx | 86 ----------------------------------- build2/context.txx | 101 ----------------------------------------- build2/cxx/link.cxx | 4 +- build2/dist/operation.cxx | 1 + build2/file.cxx | 2 +- build2/filesystem | 89 ++++++++++++++++++++++++++++++++++++ build2/filesystem.cxx | 99 ++++++++++++++++++++++++++++++++++++++++ build2/filesystem.txx | 108 ++++++++++++++++++++++++++++++++++++++++++++ build2/install/rule.cxx | 3 +- build2/rule.cxx | 5 +- build2/search.cxx | 2 +- build2/target.cxx | 2 +- 20 files changed, 315 insertions(+), 275 deletions(-) create mode 100644 build2/filesystem create mode 100644 build2/filesystem.cxx create mode 100644 build2/filesystem.txx diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx index 5aca7ee..51d2725 100644 --- a/build2/algorithm.cxx +++ b/build2/algorithm.cxx @@ -6,12 +6,13 @@ #include #include -#include #include #include // import() #include #include +#include #include +#include using namespace std; using namespace butl; diff --git a/build2/b.cxx b/build2/b.cxx index 3be9f95..8b3c693 100644 --- a/build2/b.cxx +++ b/build2/b.cxx @@ -11,7 +11,6 @@ #include #include -#include #include #include @@ -26,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/build2/buildfile b/build2/buildfile index e1b0b39..d754db2 100644 --- a/build2/buildfile +++ b/build2/buildfile @@ -13,6 +13,7 @@ exe{b}: \ {hxx cxx}{ diagnostics } \ {hxx cxx}{ dump } \ {hxx ixx cxx}{ file } \ + {hxx txx cxx}{ filesystem } \ {hxx cxx}{ lexer } \ {hxx cxx}{ module } \ {hxx ixx cxx}{ name } \ diff --git a/build2/cli/rule.cxx b/build2/cli/rule.cxx index d986eca..139abc6 100644 --- a/build2/cli/rule.cxx +++ b/build2/cli/rule.cxx @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -319,6 +320,8 @@ namespace build2 // prerequisites. Also update timestamp in case there are operations // after us that could use the information. // + // @@ Can't we use clean_extra() for this? + // bool r (false); if (t.i != nullptr) diff --git a/build2/cli/target.cxx b/build2/cli/target.cxx index e3d1526..7432bef 100644 --- a/build2/cli/target.cxx +++ b/build2/cli/target.cxx @@ -4,7 +4,7 @@ #include -#include +#include // file_mtime() using namespace std; using namespace butl; diff --git a/build2/config/module.cxx b/build2/config/module.cxx index 4f4064f..9113166 100644 --- a/build2/config/module.cxx +++ b/build2/config/module.cxx @@ -4,12 +4,11 @@ #include -#include - #include #include #include #include +#include // file_exists() #include #include diff --git a/build2/config/operation.cxx b/build2/config/operation.cxx index 1a207ca..4a5b39c 100644 --- a/build2/config/operation.cxx +++ b/build2/config/operation.cxx @@ -7,13 +7,12 @@ #include #include -#include - #include #include #include #include #include +#include #include #include diff --git a/build2/context b/build2/context index 3f47af6..dc7d0c0 100644 --- a/build2/context +++ b/build2/context @@ -5,10 +5,6 @@ #ifndef BUILD2_CONTEXT #define BUILD2_CONTEXT -#include // enable_if - -#include - #include #include @@ -62,73 +58,6 @@ namespace build2 variable_overrides reset (const strings& cmd_vars); - // The dual interface wrapper for the {mk,rm}{file,dir}() functions - // below that allows you to use it as a true/false return or a more - // detailed enum from - // - template - struct fs_status - { - T v; - fs_status (T v): v (v) {}; - operator T () const {return v;} - explicit operator bool () const {return v == T::success;} - }; - - // Create the directory and print the standard diagnostics starting from - // the specified verbosity level. - // - // Note that this implementation is not suitable if it is expected that the - // directory will exist in the majority of cases and performance is - // important. See the fsdir{} rule for details. - // - using mkdir_status = butl::mkdir_status; - - fs_status - mkdir (const dir_path&, uint16_t verbosity = 1); - - fs_status - mkdir_p (const dir_path&, uint16_t verbosity = 1); - - // Remove the file and print the standard diagnostics starting from the - // specified verbosity level. The second argument is only used in - // diagnostics, to print the target name. Passing the path for target will - // result in the relative path being printed. - // - using rmfile_status = butl::rmfile_status; - - template - fs_status - rmfile (const path&, const T& target, uint16_t verbosity = 1); - - inline fs_status - rmfile (const path& f, int verbosity = 1) // Literal overload (int). - { - return rmfile (f, f, static_cast (verbosity)); - } - - // Similar to rmfile() but for directories (note: not -r). - // - using rmdir_status = butl::rmdir_status; - - template - fs_status - rmdir (const dir_path&, const T& target, uint16_t verbosity = 1); - - inline fs_status - rmdir (const dir_path& d, int verbosity = 1) // Literal overload (int). - { - return rmdir (d, d, static_cast (verbosity)); - } - - // Remove the directory recursively and print the standard diagnostics - // starting from the specified verbosity level. Note that this function - // returns not_empty if we try to remove a working directory. If the dir - // argument is false, then the directory itself is not removed. - // - fs_status - rmdir_r (const dir_path&, bool dir = true, uint16_t verbosity = 1); - // Return the src/out directory corresponding to the given out/src. The // passed directory should be a sub-directory of out/src_root. // diff --git a/build2/context.cxx b/build2/context.cxx index 5530ce3..60e55bd 100644 --- a/build2/context.cxx +++ b/build2/context.cxx @@ -325,92 +325,6 @@ namespace build2 return vos; } - fs_status - mkdir (const dir_path& d, uint16_t v) - { - // We don't want to print the command if the directory already exists. - // This makes the below code a bit ugly. - // - mkdir_status ms; - - try - { - ms = try_mkdir (d); - } - catch (const system_error& e) - { - if (verb >= v) - text << "mkdir " << d; - - error << "unable to create directory " << d << ": " << e.what (); - throw failed (); - } - - if (ms == mkdir_status::success) - { - if (verb >= v) - text << "mkdir " << d; - } - - return ms; - } - - fs_status - mkdir_p (const dir_path& d, uint16_t v) - { - // We don't want to print the command if the directory already exists. - // This makes the below code a bit ugly. - // - mkdir_status ms; - - try - { - ms = try_mkdir_p (d); - } - catch (const system_error& e) - { - if (verb >= v) - text << "mkdir -p " << d; - - error << "unable to create directory " << d << ": " << e.what (); - throw failed (); - } - - if (ms == mkdir_status::success) - { - if (verb >= v) - text << "mkdir -p " << d; - } - - return ms; - } - - fs_status - rmdir_r (const dir_path& d, bool dir, uint16_t v) - { - using namespace butl; - - if (work.sub (d)) // Don't try to remove working directory. - return rmdir_status::not_empty; - - if (!dir_exists (d)) - return rmdir_status::not_exist; - - if (verb >= v) - text << "rmdir -r " << d; - - try - { - butl::rmdir_r (d, dir); - } - catch (const system_error& e) - { - fail << "unable to remove directory " << d << ": " << e.what (); - } - - return rmdir_status::success; - } - dir_path src_out (const dir_path& out, scope& r) { diff --git a/build2/context.txx b/build2/context.txx index 9223681..6ff61c9 100644 --- a/build2/context.txx +++ b/build2/context.txx @@ -2,109 +2,8 @@ // copyright : Copyright (c) 2014-2016 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -#include - namespace build2 { - template - fs_status - rmfile (const path& f, const T& t, uint16_t v) - { - using namespace butl; - - // We don't want to print the command if we couldn't remove the file - // because it does not exist (just like we don't print the update command - // if the file is up to date). This makes the below code a bit ugly. - // - auto print = [&f, &t, v] () - { - if (verb >= v) - { - if (verb >= 2) - text << "rm " << f; - else if (verb) - text << "rm " << t; - } - }; - - rmfile_status rs; - - try - { - rs = try_rmfile (f); - } - catch (const system_error& e) - { - print (); - error << "unable to remove file " << f << ": " << e.what (); - throw failed (); - } - - if (rs == rmfile_status::success) - print (); - - return rs; - } - - template - fs_status - rmdir (const dir_path& d, const T& t, uint16_t v) - { - using namespace butl; - - bool w (work.sub (d)); // Don't try to remove working directory. - rmdir_status rs; - - // We don't want to print the command if we couldn't remove the directory - // because it does not exist (just like we don't print mkdir if it already - // exists) or if it is not empty. This makes the below code a bit ugly. - // - auto print = [&d, &t, v] () - { - if (verb >= v) - { - if (verb >= 2) - text << "rm " << d; - else if (verb) - text << "rm " << t; - } - }; - - try - { - rs = !w ? try_rmdir (d) : rmdir_status::not_empty; - } - catch (const system_error& e) - { - print (); - error << "unable to remove directory " << d << ": " << e.what (); - throw failed (); - } - - switch (rs) - { - case rmdir_status::success: - { - print (); - break; - } - case rmdir_status::not_empty: - { - if (verb >= v && verb >= 2) - { - text << d << " is " - << (w ? "current working directory" : "not empty") - << ", not removing"; - } - break; - } - case rmdir_status::not_exist: - break; - } - - return rs; - } - template basic_path relative (const basic_path& p) diff --git a/build2/cxx/link.cxx b/build2/cxx/link.cxx index 4de3194..1818be6 100644 --- a/build2/cxx/link.cxx +++ b/build2/cxx/link.cxx @@ -10,14 +10,14 @@ #include // exit() #include -#include #include #include +#include #include #include +#include #include -#include #include #include diff --git a/build2/dist/operation.cxx b/build2/dist/operation.cxx index aea957a..4697c6c 100644 --- a/build2/dist/operation.cxx +++ b/build2/dist/operation.cxx @@ -10,6 +10,7 @@ #include #include #include +#include #include using namespace std; diff --git a/build2/file.cxx b/build2/file.cxx index 3195af7..9b3be0c 100644 --- a/build2/file.cxx +++ b/build2/file.cxx @@ -7,7 +7,7 @@ #include #include // cin -#include +#include // file_exists() #include #include diff --git a/build2/filesystem b/build2/filesystem new file mode 100644 index 0000000..1dcf8bd --- /dev/null +++ b/build2/filesystem @@ -0,0 +1,89 @@ +// file : build2/filesystem -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_FILESYSTEM +#define BUILD2_FILESYSTEM + +#include + +#include +#include + +// Higher-level filesystem utilities built on top of . +// +namespace build2 +{ + // The dual interface wrapper for the {mk,rm}{file,dir}() functions + // below that allows you to use it as a true/false return or a more + // detailed enum from + // + template + struct fs_status + { + T v; + fs_status (T v): v (v) {}; + operator T () const {return v;} + explicit operator bool () const {return v == T::success;} + }; + + // Create the directory and print the standard diagnostics starting from + // the specified verbosity level. + // + // Note that this implementation is not suitable if it is expected that the + // directory will exist in the majority of cases and performance is + // important. See the fsdir{} rule for details. + // + using mkdir_status = butl::mkdir_status; + + fs_status + mkdir (const dir_path&, uint16_t verbosity = 1); + + fs_status + mkdir_p (const dir_path&, uint16_t verbosity = 1); + + // Remove the file and print the standard diagnostics starting from the + // specified verbosity level. The second argument is only used in + // diagnostics, to print the target name. Passing the path for target will + // result in the relative path being printed. + // + using rmfile_status = butl::rmfile_status; + + template + fs_status + rmfile (const path&, const T& target, uint16_t verbosity = 1); + + inline fs_status + rmfile (const path& f, int verbosity = 1) // Literal overload (int). + { + return rmfile (f, f, static_cast (verbosity)); + } + + // Similar to rmfile() but for directories (note: not -r). + // + using rmdir_status = butl::rmdir_status; + + template + fs_status + rmdir (const dir_path&, const T& target, uint16_t verbosity = 1); + + inline fs_status + rmdir (const dir_path& d, int verbosity = 1) // Literal overload (int). + { + return rmdir (d, d, static_cast (verbosity)); + } + + // Remove the directory recursively and print the standard diagnostics + // starting from the specified verbosity level. Note that this function + // returns not_empty if we try to remove a working directory. If the dir + // argument is false, then the directory itself is not removed. + // + // @@ Collides (via ADL) with butl::rmdir_r(), which sucks. + // + fs_status + rmdir_r (const dir_path&, bool dir = true, uint16_t verbosity = 1); +} + +#include + +#endif // BUILD2_FILESYSTEM diff --git a/build2/filesystem.cxx b/build2/filesystem.cxx new file mode 100644 index 0000000..44b0ba4 --- /dev/null +++ b/build2/filesystem.cxx @@ -0,0 +1,99 @@ +// file : build2/filesystem.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include + +using namespace std; +using namespace butl; + +namespace build2 +{ + fs_status + mkdir (const dir_path& d, uint16_t v) + { + // We don't want to print the command if the directory already exists. + // This makes the below code a bit ugly. + // + mkdir_status ms; + + try + { + ms = try_mkdir (d); + } + catch (const system_error& e) + { + if (verb >= v) + text << "mkdir " << d; + + error << "unable to create directory " << d << ": " << e.what (); + throw failed (); + } + + if (ms == mkdir_status::success) + { + if (verb >= v) + text << "mkdir " << d; + } + + return ms; + } + + fs_status + mkdir_p (const dir_path& d, uint16_t v) + { + // We don't want to print the command if the directory already exists. + // This makes the below code a bit ugly. + // + mkdir_status ms; + + try + { + ms = try_mkdir_p (d); + } + catch (const system_error& e) + { + if (verb >= v) + text << "mkdir -p " << d; + + error << "unable to create directory " << d << ": " << e.what (); + throw failed (); + } + + if (ms == mkdir_status::success) + { + if (verb >= v) + text << "mkdir -p " << d; + } + + return ms; + } + + fs_status + rmdir_r (const dir_path& d, bool dir, uint16_t v) + { + using namespace butl; + + if (work.sub (d)) // Don't try to remove working directory. + return rmdir_status::not_empty; + + if (!dir_exists (d)) + return rmdir_status::not_exist; + + if (verb >= v) + text << "rmdir -r " << d; + + try + { + butl::rmdir_r (d, dir); + } + catch (const system_error& e) + { + fail << "unable to remove directory " << d << ": " << e.what (); + } + + return rmdir_status::success; + } +} diff --git a/build2/filesystem.txx b/build2/filesystem.txx new file mode 100644 index 0000000..a3366ba --- /dev/null +++ b/build2/filesystem.txx @@ -0,0 +1,108 @@ +// file : build2/filesystem.txx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include // work +#include + +namespace build2 +{ + template + fs_status + rmfile (const path& f, const T& t, uint16_t v) + { + using namespace butl; + + // We don't want to print the command if we couldn't remove the file + // because it does not exist (just like we don't print the update command + // if the file is up to date). This makes the below code a bit ugly. + // + auto print = [&f, &t, v] () + { + if (verb >= v) + { + if (verb >= 2) + text << "rm " << f; + else if (verb) + text << "rm " << t; + } + }; + + rmfile_status rs; + + try + { + rs = try_rmfile (f); + } + catch (const system_error& e) + { + print (); + error << "unable to remove file " << f << ": " << e.what (); + throw failed (); + } + + if (rs == rmfile_status::success) + print (); + + return rs; + } + + template + fs_status + rmdir (const dir_path& d, const T& t, uint16_t v) + { + using namespace butl; + + bool w (work.sub (d)); // Don't try to remove working directory. + rmdir_status rs; + + // We don't want to print the command if we couldn't remove the directory + // because it does not exist (just like we don't print mkdir if it already + // exists) or if it is not empty. This makes the below code a bit ugly. + // + auto print = [&d, &t, v] () + { + if (verb >= v) + { + if (verb >= 2) + text << "rm " << d; + else if (verb) + text << "rm " << t; + } + }; + + try + { + rs = !w ? try_rmdir (d) : rmdir_status::not_empty; + } + catch (const system_error& e) + { + print (); + error << "unable to remove directory " << d << ": " << e.what (); + throw failed (); + } + + switch (rs) + { + case rmdir_status::success: + { + print (); + break; + } + case rmdir_status::not_empty: + { + if (verb >= v && verb >= 2) + { + text << d << " is " + << (w ? "current working directory" : "not empty") + << ", not removing"; + } + break; + } + case rmdir_status::not_exist: + break; + } + + return rs; + } +} diff --git a/build2/install/rule.cxx b/build2/install/rule.cxx index cbfb105..9157413 100644 --- a/build2/install/rule.cxx +++ b/build2/install/rule.cxx @@ -4,11 +4,10 @@ #include -#include - #include #include #include +#include #include using namespace std; diff --git a/build2/rule.cxx b/build2/rule.cxx index 55a35b9..b010ae2 100644 --- a/build2/rule.cxx +++ b/build2/rule.cxx @@ -4,13 +4,12 @@ #include -#include - #include #include +#include #include +#include #include -#include using namespace std; using namespace butl; diff --git a/build2/search.cxx b/build2/search.cxx index 384bd55..6d0a5e9 100644 --- a/build2/search.cxx +++ b/build2/search.cxx @@ -4,7 +4,7 @@ #include -#include +#include // file_mtime() #include #include diff --git a/build2/target.cxx b/build2/target.cxx index 12bbfd1..deeee4f 100644 --- a/build2/target.cxx +++ b/build2/target.cxx @@ -4,7 +4,7 @@ #include -#include +#include // file_mtime() #include #include -- cgit v1.1