aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/algorithm.cxx3
-rw-r--r--build2/b.cxx2
-rw-r--r--build2/buildfile1
-rw-r--r--build2/cli/rule.cxx3
-rw-r--r--build2/cli/target.cxx2
-rw-r--r--build2/config/module.cxx3
-rw-r--r--build2/config/operation.cxx3
-rw-r--r--build2/context71
-rw-r--r--build2/context.cxx86
-rw-r--r--build2/context.txx101
-rw-r--r--build2/cxx/link.cxx4
-rw-r--r--build2/dist/operation.cxx1
-rw-r--r--build2/file.cxx2
-rw-r--r--build2/filesystem89
-rw-r--r--build2/filesystem.cxx99
-rw-r--r--build2/filesystem.txx108
-rw-r--r--build2/install/rule.cxx3
-rw-r--r--build2/rule.cxx5
-rw-r--r--build2/search.cxx2
-rw-r--r--build2/target.cxx2
20 files changed, 315 insertions, 275 deletions
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 <build2/scope>
#include <build2/target>
-#include <build2/prerequisite>
#include <build2/rule>
#include <build2/file> // import()
#include <build2/search>
#include <build2/context>
+#include <build2/filesystem>
#include <build2/diagnostics>
+#include <build2/prerequisite>
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 <iostream>
#include <butl/pager>
-#include <butl/filesystem>
#include <build2/types>
#include <build2/utility>
@@ -26,6 +25,7 @@
#include <build2/file>
#include <build2/module>
#include <build2/algorithm>
+#include <build2/filesystem>
#include <build2/diagnostics>
#include <build2/context>
#include <build2/variable>
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 <build2/target>
#include <build2/context>
#include <build2/algorithm>
+#include <build2/filesystem>
#include <build2/diagnostics>
#include <build2/cli/target>
@@ -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 <build2/cli/target>
-#include <butl/filesystem>
+#include <build2/filesystem> // 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 <build2/config/module>
-#include <butl/filesystem>
-
#include <build2/file>
#include <build2/rule>
#include <build2/scope>
#include <build2/context>
+#include <build2/filesystem> // file_exists()
#include <build2/diagnostics>
#include <build2/config/operation>
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 <set>
#include <fstream>
-#include <butl/filesystem>
-
#include <build2/file>
#include <build2/scope>
#include <build2/target>
#include <build2/context>
#include <build2/algorithm>
+#include <build2/filesystem>
#include <build2/diagnostics>
#include <build2/config/module>
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 <type_traits> // enable_if
-
-#include <butl/filesystem>
-
#include <build2/types>
#include <build2/utility>
@@ -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 <butl/filesystem>
- //
- template <typename T>
- 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_status>
- mkdir (const dir_path&, uint16_t verbosity = 1);
-
- fs_status<mkdir_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 <typename T>
- fs_status<rmfile_status>
- rmfile (const path&, const T& target, uint16_t verbosity = 1);
-
- inline fs_status<rmfile_status>
- rmfile (const path& f, int verbosity = 1) // Literal overload (int).
- {
- return rmfile (f, f, static_cast<uint16_t> (verbosity));
- }
-
- // Similar to rmfile() but for directories (note: not -r).
- //
- using rmdir_status = butl::rmdir_status;
-
- template <typename T>
- fs_status<rmdir_status>
- rmdir (const dir_path&, const T& target, uint16_t verbosity = 1);
-
- inline fs_status<rmdir_status>
- rmdir (const dir_path& d, int verbosity = 1) // Literal overload (int).
- {
- return rmdir (d, d, static_cast<uint16_t> (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_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_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_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<butl::rmdir_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 <build2/diagnostics>
-
namespace build2
{
- template <typename T>
- fs_status<butl::rmfile_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 <typename T>
- fs_status<butl::rmdir_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 <typename K>
basic_path<char, K>
relative (const basic_path<char, K>& 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 <cstdlib> // exit()
#include <butl/path-map>
-#include <butl/filesystem>
#include <build2/depdb>
#include <build2/scope>
+#include <build2/context>
#include <build2/variable>
#include <build2/algorithm>
+#include <build2/filesystem>
#include <build2/diagnostics>
-#include <build2/context>
#include <build2/bin/target>
#include <build2/cxx/target>
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 <build2/target>
#include <build2/context>
#include <build2/algorithm>
+#include <build2/filesystem>
#include <build2/diagnostics>
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 <fstream>
#include <iostream> // cin
-#include <butl/filesystem>
+#include <butl/filesystem> // file_exists()
#include <build2/scope>
#include <build2/context>
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 <butl/filesystem>
+
+#include <build2/types>
+#include <build2/utility>
+
+// Higher-level filesystem utilities built on top of <butl/filesystem>.
+//
+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 <butl/filesystem>
+ //
+ template <typename T>
+ 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_status>
+ mkdir (const dir_path&, uint16_t verbosity = 1);
+
+ fs_status<mkdir_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 <typename T>
+ fs_status<rmfile_status>
+ rmfile (const path&, const T& target, uint16_t verbosity = 1);
+
+ inline fs_status<rmfile_status>
+ rmfile (const path& f, int verbosity = 1) // Literal overload (int).
+ {
+ return rmfile (f, f, static_cast<uint16_t> (verbosity));
+ }
+
+ // Similar to rmfile() but for directories (note: not -r).
+ //
+ using rmdir_status = butl::rmdir_status;
+
+ template <typename T>
+ fs_status<rmdir_status>
+ rmdir (const dir_path&, const T& target, uint16_t verbosity = 1);
+
+ inline fs_status<rmdir_status>
+ rmdir (const dir_path& d, int verbosity = 1) // Literal overload (int).
+ {
+ return rmdir (d, d, static_cast<uint16_t> (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_status>
+ rmdir_r (const dir_path&, bool dir = true, uint16_t verbosity = 1);
+}
+
+#include <build2/filesystem.txx>
+
+#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 <build2/filesystem>
+
+#include <build2/diagnostics>
+
+using namespace std;
+using namespace butl;
+
+namespace build2
+{
+ fs_status<mkdir_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_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<butl::rmdir_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 <build2/context> // work
+#include <build2/diagnostics>
+
+namespace build2
+{
+ template <typename T>
+ fs_status<butl::rmfile_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 <typename T>
+ fs_status<butl::rmdir_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 <build2/install/rule>
-#include <butl/filesystem>
-
#include <build2/scope>
#include <build2/target>
#include <build2/algorithm>
+#include <build2/filesystem>
#include <build2/diagnostics>
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 <build2/rule>
-#include <butl/filesystem>
-
#include <build2/scope>
#include <build2/target>
+#include <build2/context>
#include <build2/algorithm>
+#include <build2/filesystem>
#include <build2/diagnostics>
-#include <build2/context>
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 <build2/search>
-#include <butl/filesystem>
+#include <butl/filesystem> // file_mtime()
#include <build2/scope>
#include <build2/target>
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 <build2/target>
-#include <butl/filesystem>
+#include <butl/filesystem> // file_mtime()
#include <build2/scope>
#include <build2/search>