aboutsummaryrefslogtreecommitdiff
path: root/bpkg/utility.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bpkg/utility.cxx')
-rw-r--r--bpkg/utility.cxx164
1 files changed, 141 insertions, 23 deletions
diff --git a/bpkg/utility.cxx b/bpkg/utility.cxx
index ef61870..d084b76 100644
--- a/bpkg/utility.cxx
+++ b/bpkg/utility.cxx
@@ -3,8 +3,8 @@
#include <bpkg/utility.hxx>
-#include <libbutl/prompt.mxx>
-#include <libbutl/fdstream.mxx>
+#include <libbutl/prompt.hxx>
+#include <libbutl/fdstream.hxx>
#include <bpkg/diagnostics.hxx>
#include <bpkg/common-options.hxx>
@@ -26,22 +26,48 @@ namespace bpkg
const dir_path certs_dir (dir_path (bpkg_dir) /= "certs");
const dir_path repos_dir (dir_path (bpkg_dir) /= "repos");
+ // Standard and alternative build file/directory naming schemes.
+ //
+ // build:
+ //
+ const dir_path std_build_dir ("build");
+ const dir_path std_config_dir (dir_path (std_build_dir) /= "config");
+ const path std_bootstrap_file (dir_path (std_build_dir) /= "bootstrap.build");
+ const path std_root_file (dir_path (std_build_dir) /= "root.build");
+ const string std_build_ext ("build");
+
+ // build2:
+ //
+ const dir_path alt_build_dir ("build2");
+ const dir_path alt_config_dir (dir_path (alt_build_dir) /= "config");
+ const path alt_bootstrap_file (dir_path (alt_build_dir) /= "bootstrap.build2");
+ const path alt_root_file (dir_path (alt_build_dir) /= "root.build2");
+ const string alt_build_ext ("build2");
+
const dir_path current_dir (".");
- dir_path temp_dir;
+ const target_triplet host_triplet (BPKG_HOST_TRIPLET);
+
+ map<dir_path, dir_path> tmp_dirs;
+
+ bool keep_tmp;
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 (tmp_dirs.find (cfg));
+ assert (i != tmp_dirs.end ());
+ return auto_rmfile (i->second / path::traits_type::temp_name (p),
+ !keep_tmp);
}
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 (tmp_dirs.find (cfg));
+ assert (i != tmp_dirs.end ());
+ return auto_rmdir (i->second / dir_path (path::traits_type::temp_name (p)),
+ !keep_tmp);
}
void
@@ -62,21 +88,26 @@ namespace bpkg
mk (d); // We shouldn't need mk_p().
- temp_dir = move (d);
+ tmp_dirs[cfg] = move (d);
}
void
clean_tmp (bool ignore_error)
{
- if (!temp_dir.empty () && exists (temp_dir))
+ for (const auto& d: tmp_dirs)
{
- rm_r (temp_dir,
- true /* dir_itself */,
- 3,
- ignore_error ? rm_error_mode::ignore : rm_error_mode::fail);
-
- temp_dir.clear ();
+ const dir_path& td (d.second);
+
+ if (exists (td))
+ {
+ rm_r (td,
+ true /* dir_itself */,
+ 3,
+ ignore_error ? rm_error_mode::ignore : rm_error_mode::fail);
+ }
}
+
+ tmp_dirs.clear ();
}
path&
@@ -84,7 +115,8 @@ namespace bpkg
{
try
{
- f.complete ().normalize ();
+ if (!f.complete ().normalized ())
+ f.normalize ();
}
catch (const invalid_path& e)
{
@@ -103,7 +135,8 @@ namespace bpkg
{
try
{
- d.complete ().normalize ();
+ if (!d.complete ().normalized ())
+ d.normalize ();
}
catch (const invalid_path& e)
{
@@ -117,7 +150,21 @@ namespace bpkg
return d;
}
- bool stderr_term;
+ dir_path
+ current_directory ()
+ {
+ try
+ {
+ return dir_path::current_directory ();
+ }
+ catch (const system_error& e)
+ {
+ fail << "unable to obtain current directory: " << e << endf;
+ }
+ }
+
+ optional<const char*> stderr_term = nullopt;
+ bool stderr_term_color = false;
bool
yn_prompt (const string& p, char d)
@@ -242,8 +289,8 @@ namespace bpkg
}
}
- void
- mv (const dir_path& from, const dir_path& to)
+ bool
+ mv (const dir_path& from, const dir_path& to, bool ie)
{
if (verb >= 3)
text << "mv " << from << ' ' << to; // Prints trailing slashes.
@@ -254,8 +301,40 @@ namespace bpkg
}
catch (const system_error& e)
{
- fail << "unable to move directory " << from << " to " << to << ": " << e;
+ error << "unable to move directory " << from << " to " << to << ": "
+ << e;
+
+ if (ie)
+ return false;
+
+ throw failed ();
}
+
+ return true;
+ }
+
+ bool
+ mv (const path& from, const path& to, bool ie)
+ {
+ if (verb >= 3)
+ text << "mv " << from << ' ' << to;
+
+ try
+ {
+ mvfile (from, to,
+ cpflags::overwrite_content | cpflags::overwrite_permissions);
+ }
+ catch (const system_error& e)
+ {
+ error << "unable to move file " << from << " to " << to << ": " << e;
+
+ if (ie)
+ return false;
+
+ throw failed ();
+ }
+
+ return true;
}
dir_path
@@ -313,4 +392,43 @@ namespace bpkg
? co.build ().string ().c_str ()
: BPKG_EXE_PREFIX "b" BPKG_EXE_SUFFIX;
}
+
+ process_path
+ search_b (const common_options& co)
+ {
+ const char* b (name_b (co));
+
+ try
+ {
+ // Use our executable directory as a fallback search since normally the
+ // entire toolchain is installed into one directory. This way, for
+ // example, if we installed into /opt/build2 and run bpkg with absolute
+ // path (and without PATH), then bpkg will be able to find "its" b.
+ //
+ return process::path_search (b, true /* init */, exec_dir);
+ }
+ catch (const process_error& e)
+ {
+ fail << "unable to execute " << b << ": " << e << endf;
+ }
+ }
+
+ void
+ dump_stderr (auto_fd&& fd)
+ {
+ ifdstream is (move (fd), fdstream_mode::skip, ifdstream::badbit);
+
+ // We could probably write something like this, instead:
+ //
+ // *diag_stream << is.rdbuf () << flush;
+ //
+ // However, it would never throw and we could potentially miss the reading
+ // failure, unless we decide to additionally mess with the diagnostics
+ // stream exception mask.
+ //
+ for (string l; !eof (getline (is, l)); )
+ *diag_stream << l << endl;
+
+ is.close ();
+ }
}