diff options
Diffstat (limited to 'bpkg/utility.cxx')
-rw-r--r-- | bpkg/utility.cxx | 164 |
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 (); + } } |