From 7bb44980ced46506c10bad333f526b7bc62ea1db Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 3 Sep 2021 18:24:08 +0300 Subject: Add support for multiple temporary directories --- bpkg/auth.cxx | 2 +- bpkg/bpkg.cxx | 50 +++++++++++++++++++++++++------------------------- bpkg/cfg-create.cxx | 5 ++--- bpkg/pkg-checkout.cxx | 13 +++++++++++-- bpkg/rep-fetch.cxx | 5 ++++- bpkg/rep-info.cxx | 17 ++++++++++++++++- bpkg/rep-remove.cxx | 11 +++++++---- bpkg/utility.cxx | 35 +++++++++++++++++++++-------------- bpkg/utility.hxx | 18 ++++++++++-------- 9 files changed, 97 insertions(+), 59 deletions(-) diff --git a/bpkg/auth.cxx b/bpkg/auth.cxx index 8698445..08f6b11 100644 --- a/bpkg/auth.cxx +++ b/bpkg/auth.cxx @@ -713,7 +713,7 @@ namespace bpkg try { - rm = tmp_file ("cert"); + rm = tmp_file (conf != nullptr ? *conf : empty_dir_path, "cert"); f = rm.path; ofdstream ofs (f); diff --git a/bpkg/bpkg.cxx b/bpkg/bpkg.cxx index 04aa798..49f4055 100644 --- a/bpkg/bpkg.cxx +++ b/bpkg/bpkg.cxx @@ -535,37 +535,37 @@ try // pkg-* commands // -#define PKG_COMMAND(CMD, SEP) COMMAND_IMPL(pkg_, "pkg-", CMD, SEP, true) +#define PKG_COMMAND(CMD, SEP, TMP) COMMAND_IMPL(pkg_, "pkg-", CMD, SEP, TMP) // These commands need the '--' separator to be kept in args. // - PKG_COMMAND (build, true); - PKG_COMMAND (clean, true); - PKG_COMMAND (configure, true); - PKG_COMMAND (install, true); - PKG_COMMAND (test, true); - PKG_COMMAND (uninstall, true); - PKG_COMMAND (update, true); - - PKG_COMMAND (checkout, false); - PKG_COMMAND (disfigure, false); - PKG_COMMAND (drop, false); - PKG_COMMAND (fetch, false); - PKG_COMMAND (purge, false); - PKG_COMMAND (status, false); - PKG_COMMAND (unpack, false); - PKG_COMMAND (verify, false); + PKG_COMMAND (build, true, false); + PKG_COMMAND (clean, true, true); + PKG_COMMAND (configure, true, true); + PKG_COMMAND (install, true, true); + PKG_COMMAND (test, true, true); + PKG_COMMAND (uninstall, true, true); + PKG_COMMAND (update, true, true); + + PKG_COMMAND (checkout, false, true); + PKG_COMMAND (disfigure, false, true); + PKG_COMMAND (drop, false, true); + PKG_COMMAND (fetch, false, true); + PKG_COMMAND (purge, false, true); + PKG_COMMAND (status, false, true); + PKG_COMMAND (unpack, false, true); + PKG_COMMAND (verify, false, true); // rep-* commands // -#define REP_COMMAND(CMD) COMMAND_IMPL(rep_, "rep-", CMD, false, true) - - REP_COMMAND (add); - REP_COMMAND (create); - REP_COMMAND (fetch); - REP_COMMAND (info); - REP_COMMAND (list); - REP_COMMAND (remove); +#define REP_COMMAND(CMD, TMP) COMMAND_IMPL(rep_, "rep-", CMD, false, TMP) + + REP_COMMAND (add, true); + REP_COMMAND (create, true); + REP_COMMAND (fetch, true); + REP_COMMAND (info, false); + REP_COMMAND (list, true); + REP_COMMAND (remove, true); assert (false); fail << "unhandled command"; diff --git a/bpkg/cfg-create.cxx b/bpkg/cfg-create.cxx index 8101dc0..29de01c 100644 --- a/bpkg/cfg-create.cxx +++ b/bpkg/cfg-create.cxx @@ -165,10 +165,9 @@ namespace bpkg } } - // Initialize tmp directory, unless it is already initialized. + // Initialize tmp directory. // - if (temp_dir.empty ()) - init_tmp (c); + init_tmp (c); // Create the database. // diff --git a/bpkg/pkg-checkout.cxx b/bpkg/pkg-checkout.cxx index d8c6819..49fc89f 100644 --- a/bpkg/pkg-checkout.cxx +++ b/bpkg/pkg-checkout.cxx @@ -191,6 +191,15 @@ namespace bpkg dir_path sd (repository_state (rl)); dir_path rd (rdb.config_orig / repos_dir / sd); + // Use the temporary directory from the repository information source + // configuration, so that we can always move the repository into and out + // of it (note that if they appear on different filesystems that won't + // be possible). + // + auto ti (temp_dir.find (rdb.config_orig)); + assert (ti != temp_dir.end ()); + const dir_path& tdir (ti->second); + // Try to reuse the cached repository (moved to the temporary directory // with some fragment checked out and fixed up). // @@ -214,7 +223,7 @@ namespace bpkg // The repository temporary directory. // - auto_rmdir rmt (temp_dir / sd); + auto_rmdir rmt (tdir / sd); // Move the repository to the temporary directory. // @@ -248,7 +257,7 @@ namespace bpkg // The temporary out of source directory that is required for the dist // meta-operation. // - auto_rmdir rmo (temp_dir / dir_path (n.string ())); + auto_rmdir rmo (tdir / dir_path (n.string ())); const dir_path& od (rmo.path); if (exists (od)) diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx index 7e0d3da..c000f05 100644 --- a/bpkg/rep-fetch.cxx +++ b/bpkg/rep-fetch.cxx @@ -408,9 +408,12 @@ namespace bpkg assert (conf == nullptr || !conf->empty ()); + auto i (temp_dir.find (conf != nullptr ? *conf : empty_dir_path)); + assert (i != temp_dir.end ()); + dir_path sd (repository_state (rl)); - auto_rmdir rm (temp_dir / sd); + auto_rmdir rm (i->second / sd); const dir_path& td (rm.path); if (exists (td)) diff --git a/bpkg/rep-info.cxx b/bpkg/rep-info.cxx index c935114..4e3315b 100644 --- a/bpkg/rep-info.cxx +++ b/bpkg/rep-info.cxx @@ -49,9 +49,24 @@ namespace bpkg // unknown manifest entries unless we are dumping them. // dir_path d (o.directory ()); + + const dir_path* conf (o.directory_specified () && d.empty () + ? nullptr + : &d); + + // If --directory|-d is not specified and the current working directory is + // a configuration directory, then initialize the temporary directory + // inside it, so that we can always move a version control-based + // repository into and out of it (see pkg_checkout() for details). + // + if (conf != nullptr && conf->empty ()) + conf = exists (bpkg_dir) ? ¤t_dir : nullptr; + + init_tmp (conf != nullptr ? *conf : empty_dir_path); + rep_fetch_data rfd ( rep_fetch (o, - o.directory_specified () && d.empty () ? nullptr : &d, + conf, rl, !o.manifest () /* ignore_unknow */, o.deep () /* expand_values */)); diff --git a/bpkg/rep-remove.cxx b/bpkg/rep-remove.cxx index 266d70c..5dab94b 100644 --- a/bpkg/rep-remove.cxx +++ b/bpkg/rep-remove.cxx @@ -129,9 +129,12 @@ namespace bpkg // the chances for the operation to succeed. // static void - rmdir (const dir_path& d) + rmdir (const dir_path& cfg, const dir_path& d) { - dir_path td (temp_dir / d.leaf ()); + auto i (temp_dir.find (cfg)); + assert (i != temp_dir.end ()); + + dir_path td (i->second / d.leaf ()); if (exists (td)) rm_r (td); @@ -210,7 +213,7 @@ namespace bpkg } if (rm) - rmdir (sd); + rmdir (db.config_orig, sd); } } } @@ -336,7 +339,7 @@ namespace bpkg for (const dir_entry& de: dir_iterator (rd, false /* ignore_dangling */)) { if (de.ltype () == entry_type::directory) - rmdir (rd / path_cast (de.path ())); + rmdir (db.config_orig, rd / path_cast (de.path ())); } } catch (const system_error& e) diff --git a/bpkg/utility.cxx b/bpkg/utility.cxx index b179f63..39dea81 100644 --- a/bpkg/utility.cxx +++ b/bpkg/utility.cxx @@ -28,20 +28,22 @@ namespace bpkg const dir_path current_dir ("."); - dir_path temp_dir; + map temp_dir; auto_rmfile - tmp_file (const string& p) + tmp_file (const dir_path& cfg, const string& p) { - assert (!temp_dir.empty ()); - return auto_rmfile (temp_dir / path::traits_type::temp_name (p)); + auto i (temp_dir.find (cfg)); + assert (i != temp_dir.end ()); + return auto_rmfile (i->second / path::traits_type::temp_name (p)); } auto_rmdir - tmp_dir (const string& p) + tmp_dir (const dir_path& cfg, const string& p) { - assert (!temp_dir.empty ()); - return auto_rmdir (temp_dir / dir_path (path::traits_type::temp_name (p))); + auto i (temp_dir.find (cfg)); + assert (i != temp_dir.end ()); + return auto_rmdir (i->second / dir_path (path::traits_type::temp_name (p))); } void @@ -62,21 +64,26 @@ namespace bpkg mk (d); // We shouldn't need mk_p(). - temp_dir = move (d); + temp_dir[cfg] = move (d); } void clean_tmp (bool ignore_error) { - if (!temp_dir.empty () && exists (temp_dir)) + for (const auto& d: temp_dir) { - rm_r (temp_dir, - true /* dir_itself */, - 3, - ignore_error ? rm_error_mode::ignore : rm_error_mode::fail); + const dir_path& td (d.second); - temp_dir.clear (); + if (exists (td)) + { + rm_r (td, + true /* dir_itself */, + 3, + ignore_error ? rm_error_mode::ignore : rm_error_mode::fail); + } } + + temp_dir.clear (); } path& diff --git a/bpkg/utility.hxx b/bpkg/utility.hxx index ce6120f..dabffbe 100644 --- a/bpkg/utility.hxx +++ b/bpkg/utility.hxx @@ -4,6 +4,7 @@ #ifndef BPKG_UTILITY_HXX #define BPKG_UTILITY_HXX +#include #include // make_shared() #include // to_string() #include // strcmp(), strchr() @@ -83,19 +84,20 @@ namespace bpkg // Temporary directory facility. // - // This is normally .bpkg/tmp/ but can also be some system-wide directory - // (e.g., /tmp/bpkg-XXX/) if there is no bpkg configuration. This directory - // is automatically created and cleaned up for most commands in main() so - // you don't need to call init_tmp() explicitly except for certain special - // commands (like cfg-create). + // An entry normally maps to /.bpkg/tmp/ but can also map + // an empty directory to some system-wide directory (e.g., /tmp/bpkg-XXX/) + // if there is no bpkg configuration. The temporary directory for the + // current configuration is automatically created and cleaned up for most + // commands in main(), so you don't need to call init_tmp() explicitly + // except for certain special commands (like cfg-create). // - extern dir_path temp_dir; + extern std::map temp_dir; auto_rmfile - tmp_file (const string& prefix); + tmp_file (const dir_path& cfg, const string& prefix); auto_rmdir - tmp_dir (const string& prefix); + tmp_dir (const dir_path& cfg, const string& prefix); void init_tmp (const dir_path& cfg); -- cgit v1.1