aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-04-09 09:00:29 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-04-09 09:00:29 +0200
commit79a760af92146a63e337c4399ec57134f56d8886 (patch)
tree1f576594fcfc987a6874533815cc6a20c60cd78d
parentd2951ce7344dade96f78286cc311ed86c46d086e (diff)
Add dry-run support to install/uninstall rules
-rw-r--r--build2/filesystem.hxx2
-rw-r--r--build2/install/rule.cxx51
-rw-r--r--build2/install/rule.hxx2
-rw-r--r--build2/version/utility.cxx91
4 files changed, 82 insertions, 64 deletions
diff --git a/build2/filesystem.hxx b/build2/filesystem.hxx
index 2044141..91ee418 100644
--- a/build2/filesystem.hxx
+++ b/build2/filesystem.hxx
@@ -15,7 +15,7 @@
// Compared to the libbutl's versions, these handle errors and issue
// diagnostics. Some of them also print the corresponding command line
// equivalent at the specified verbosity level. Note that most of such
-// functions also handle the dry_run flag.
+// functions also respect the dry_run flag.
//
namespace build2
{
diff --git a/build2/install/rule.cxx b/build2/install/rule.cxx
index a30cbd3..85bd501 100644
--- a/build2/install/rule.cxx
+++ b/build2/install/rule.cxx
@@ -690,15 +690,25 @@ namespace build2
// install -d <dir>
//
- // If verbose is false, then only print the command at verbosity level 2
- // or higher.
- //
static void
install_d (const scope& rs,
const install_dir& base,
const dir_path& d,
bool verbose = true)
{
+ // Here is the problem: if this is a dry-run, then we will keep showing
+ // the same directory creation commands over and over again (because we
+ // don't actually create them). There are two alternative ways to solve
+ // this: actually create the directories or simply don't show anything.
+ // While we use the former approach during update (see mkdir() in
+ // filesystem), here it feels like we really shouldn't be touching the
+ // destination filesystem. Plus, not showing anything will be symmetric
+ // with uninstall since the directories won't be empty (because we don't
+ // actually uninstall any files).
+ //
+ if (dry_run)
+ return;
+
dir_path chd (chroot_path (rs, d));
try
@@ -760,9 +770,6 @@ namespace build2
// install <file> <dir>/
// install <file> <file>
//
- // If verbose is false, then only print the command at verbosity level 2
- // or higher.
- //
static void
install_f (const scope& rs,
const install_dir& base,
@@ -809,7 +816,8 @@ namespace build2
else if (verb && verbose)
text << "install " << t;
- run (pp, args);
+ if (!dry_run)
+ run (pp, args);
}
void file_rule::
@@ -844,7 +852,8 @@ namespace build2
else if (verb && verbose)
text << "install " << rell << " -> " << target;
- run (pp, args);
+ if (!dry_run)
+ run (pp, args);
}
target_state file_rule::
@@ -952,15 +961,17 @@ namespace build2
// itself unless base == dir. Return false if nothing has been removed
// (i.e., the directories do not exist or are not empty).
//
- // If verbose is false, then only print the command at verbosity level 2
- // or higher.
- //
static bool
uninstall_d (const scope& rs,
const install_dir& base,
const dir_path& d,
bool verbose)
{
+ // See install_d() for the rationale.
+ //
+ if (dry_run)
+ return false;
+
dir_path chd (chroot_path (rs, d));
// Figure out if we should try to remove this directory. Note that if
@@ -1086,13 +1097,16 @@ namespace build2
if (verb >= 2)
text << "rm " << relf;
- try
+ if (!dry_run)
{
- try_rmfile (f);
- }
- catch (const system_error& e)
- {
- fail << "unable to remove file " << f << ": " << e;
+ try
+ {
+ try_rmfile (f);
+ }
+ catch (const system_error& e)
+ {
+ fail << "unable to remove file " << f << ": " << e;
+ }
}
}
else
@@ -1112,7 +1126,8 @@ namespace build2
if (verb >= 2)
print_process (args);
- run (pp, args);
+ if (!dry_run)
+ run (pp, args);
}
return true;
diff --git a/build2/install/rule.hxx b/build2/install/rule.hxx
index ec4b9bf..526683d 100644
--- a/build2/install/rule.hxx
+++ b/build2/install/rule.hxx
@@ -154,7 +154,7 @@ namespace build2
// Installation/uninstallation "commands".
//
// If verbose is false, then only print the command at verbosity level 2
- // or higher.
+ // or higher. Note that these functions respect the dry_run flag.
// Install a symlink: base/link -> target.
//
diff --git a/build2/version/utility.cxx b/build2/version/utility.cxx
index 4222fff..6c4d43e 100644
--- a/build2/version/utility.cxx
+++ b/build2/version/utility.cxx
@@ -18,61 +18,64 @@ namespace build2
auto_rmfile
fixup_manifest (const path& in, path out, const standard_version& v)
{
- auto_rmfile r (move (out));
+ auto_rmfile r (move (out), !dry_run /* active */);
- try
+ if (!dry_run)
{
- permissions perm (path_permissions (in));
-
- ifdstream ifs (in);
- manifest_parser p (ifs, in.string ());
+ try
+ {
+ permissions perm (path_permissions (in));
- auto_fd ofd (fdopen (r.path,
- fdopen_mode::out |
- fdopen_mode::create |
- fdopen_mode::exclusive |
- fdopen_mode::binary,
- perm));
+ ifdstream ifs (in);
+ manifest_parser p (ifs, in.string ());
- ofdstream ofs (move (ofd));
- manifest_serializer s (ofs, r.path.string ());
+ auto_fd ofd (fdopen (r.path,
+ fdopen_mode::out |
+ fdopen_mode::create |
+ fdopen_mode::exclusive |
+ fdopen_mode::binary,
+ perm));
- manifest_name_value nv (p.next ());
- assert (nv.name.empty () && nv.value == "1"); // We just loaded it.
- s.next (nv.name, nv.value);
-
- for (nv = p.next (); !nv.empty (); nv = p.next ())
- {
- if (nv.name == "version")
- nv.value = v.string ();
+ ofdstream ofs (move (ofd));
+ manifest_serializer s (ofs, r.path.string ());
+ manifest_name_value nv (p.next ());
+ assert (nv.name.empty () && nv.value == "1"); // We just loaded it.
s.next (nv.name, nv.value);
- }
- s.next (nv.name, nv.value); // End of manifest.
- s.next (nv.name, nv.value); // End of stream.
+ for (nv = p.next (); !nv.empty (); nv = p.next ())
+ {
+ if (nv.name == "version")
+ nv.value = v.string ();
- ofs.close ();
- ifs.close ();
+ s.next (nv.name, nv.value);
+ }
- return r;
- }
- catch (const manifest_parsing& e)
- {
- location l (&in, e.line, e.column);
- fail (l) << e.description << endf;
- }
- catch (const manifest_serialization& e)
- {
- location l (&r.path);
- fail (l) << e.description << endf;
- }
- catch (const io_error& e)
- {
- fail << "io error: " << e <<
- info << "while reading " << in <<
- info << "while writing " << r.path << endf;
+ s.next (nv.name, nv.value); // End of manifest.
+ s.next (nv.name, nv.value); // End of stream.
+
+ ofs.close ();
+ ifs.close ();
+ }
+ catch (const manifest_parsing& e)
+ {
+ location l (&in, e.line, e.column);
+ fail (l) << e.description;
+ }
+ catch (const manifest_serialization& e)
+ {
+ location l (&r.path);
+ fail (l) << e.description;
+ }
+ catch (const io_error& e)
+ {
+ fail << "io error: " << e <<
+ info << "while reading " << in <<
+ info << "while writing " << r.path;
+ }
}
+
+ return r;
}
}
}