From 64654832a7bcd735f3581d254b18bf724a9cc0a7 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 25 Jan 2023 11:11:32 +0200 Subject: Start testing Debian implementation --- bpkg/system-package-manager-debian.cxx | 370 +++++++++++++-------- bpkg/system-package-manager-debian.hxx | 62 +++- bpkg/system-package-manager-debian.test.cxx | 111 +++++++ bpkg/system-package-manager-debian.test.testscript | 169 ++++++++++ bpkg/system-package-manager.cxx | 6 +- bpkg/system-package-manager.hxx | 8 +- 6 files changed, 574 insertions(+), 152 deletions(-) create mode 100644 bpkg/system-package-manager-debian.test.cxx create mode 100644 bpkg/system-package-manager-debian.test.testscript diff --git a/bpkg/system-package-manager-debian.cxx b/bpkg/system-package-manager-debian.cxx index f885e2d..a7da2c0 100644 --- a/bpkg/system-package-manager-debian.cxx +++ b/bpkg/system-package-manager-debian.cxx @@ -5,12 +5,11 @@ #include +using namespace butl; + namespace bpkg { - using package_status = system_package_status; - using package_status_debian = system_package_status_debian; - - using package_policy = package_status_debian::package_policy; + using package_status = system_package_status_debian; // Parse the debian-name (or alike) value. // @@ -45,7 +44,7 @@ namespace bpkg // main package) as well as -doc and -dbg unless requested (the // extra_{doc,dbg} arguments). // - static package_status_debian + static package_status parse_debian_name (const string& nv, bool extra_doc, bool extra_dbg) @@ -72,7 +71,7 @@ namespace bpkg if (ns.empty ()) fail << "empty package group"; - package_status_debian r; + package_status r; // Handle the dev instead of main special case for libraries. // @@ -87,10 +86,10 @@ namespace bpkg suffix (m, "-dev") && !(ns.size () > 1 && suffix (ns[1], "-dev"))) { - r = package_status_debian ("", move (m)); + r = package_status ("", move (m)); } else - r = package_status_debian (move (m)); + r = package_status (move (m)); } // Handle the rest. @@ -121,14 +120,14 @@ namespace bpkg strings gs (split (nv, ',')); assert (!gs.empty ()); // *-name value cannot be empty. - package_status_debian r; + package_status r; for (size_t i (0); i != gs.size (); ++i) { if (i == 0) // Main group. r = parse_group (gs[i]); else { - package_status_debian g (parse_group (gs[i])); + package_status g (parse_group (gs[i])); if (!g.main.empty ()) r.extras.push_back (move (g.main)); if (!g.dev.empty ()) r.extras.push_back (move (g.dev)); @@ -145,6 +144,60 @@ namespace bpkg return r; } + // Attempt to determine the main package name from its -dev package based on + // the extracted Depends value. Return empty string if unable to. + // + string system_package_manager_debian:: + main_from_dev (const string& dev_name, + const string& dev_ver, + const string& depends) + { + // The format of the Depends value is a comma-seperated list of dependency + // expressions. For example: + // + // Depends: libssl3 (= 3.0.7-1), libc6 (>= 2.34), libfoo | libbar + // + // For the main package we look for a dependency in the form: + // + // * (= ) + // + // Usually it is the first one. + // + string dev_stem (dev_name, 0, dev_name.rfind ("-dev")); + + string r; + for (size_t b (0), e (0); next_word (depends, b, e, ','); ) + { + string d (depends, b, e - b); + trim (d); + + size_t p (d.find (' ')); + if (p != string::npos) + { + if (d.compare (0, dev_stem.size (), dev_stem) == 0) // * + { + size_t q (d.find ('(', p + 1)); + if (q != string::npos && d.back () == ')') // (...) + { + if (d[q + 1] == '=' && d[q + 2] == ' ') // Equal. + { + string v (d, q + 3, d.size () - q - 3 - 1); + trim (v); + + if (v == dev_ver) + { + r.assign (d, 0, p); + break; + } + } + } + } + } + } + + return r; + } + // Do we use apt or apt-get? From apt(8): // // "The apt(8) commandline is designed as an end-user tool and it may change @@ -155,17 +208,20 @@ namespace bpkg // these commands (potentially with some additional options enabled) in // your scripts as they keep backward compatibility as much as possible." // + // Note also that for some reason both apt-cache and apt-get exit with 100 + // code on error. + // static process_path apt_cache_path; static process_path apt_get_path; static process_path sudo_path; - // Obtain the installed and candidate versions for the specified list - // of Debian packages by executing `apt-cache policy`. + // Obtain the installed and candidate versions for the specified list of + // Debian packages by executing `apt-cache policy`. // // If the n argument is not 0, then only query the first n packages. // - static void - apt_cache_policy (vector& pps, size_t n = 0) + void system_package_manager_debian:: + apt_cache_policy (vector& pps, size_t n) { if (n == 0) n = pps.size (); @@ -202,7 +258,7 @@ namespace bpkg try { - if (apt_cache_path.empty ()) + if (apt_cache_path.empty () && !simulate_) apt_cache_path = process::path_search (args[0]); process_env pe (apt_cache_path, evars); @@ -213,13 +269,51 @@ namespace bpkg // Redirect stdout to a pipe. For good measure also redirect stdin to // /dev/null to make sure there are no prompts of any kind. // - process pr (apt_cache_path, - args, - -2 /* stdin */, - -1 /* stdout */, - 2 /* stderr */, - nullptr /* cwd */, - evars); + process pr; + if (!simulate_) + pr = process (apt_cache_path, + args, + -2 /* stdin */, + -1 /* stdout */, + 2 /* stderr */, + nullptr /* cwd */, + evars); + else + { + print_process (pe, args); + + strings k; + for (size_t i (0); i != n; ++i) + k.push_back (pps[i].name); + + const path* f (nullptr); + if (installed_) + { + auto i (simulate_->apt_cache_policy_installed_.find (k)); + if (i != simulate_->apt_cache_policy_installed_.end ()) + f = &i->second; + } + if (f == nullptr && fetched_) + { + auto i (simulate_->apt_cache_policy_fetched_.find (k)); + if (i != simulate_->apt_cache_policy_fetched_.end ()) + f = &i->second; + } + if (f == nullptr) + { + auto i (simulate_->apt_cache_policy_.find (k)); + if (i != simulate_->apt_cache_policy_.end ()) + f = &i->second; + } + + pr = process (process_exit (0)); + pr.in_ofd = f == nullptr || f->empty () + ? fdopen_null () + : (f->string () == "-" + ? fddup (stdin_fd ()) + : fdopen (*f, fdopen_mode::in)); + } + try { ifdstream is (move (pr.in_ofd), fdstream_mode::skip, ifdstream::badbit); @@ -270,7 +364,7 @@ namespace bpkg // Skip until this package. // - for (; i != n && pps[i].name.get () != l; ++i) ; + for (; i != n && pps[i].name != l; ++i) ; if (i == n) fail << "unexpected package name '" << l << "'"; @@ -310,9 +404,14 @@ namespace bpkg pp.candidate_version = parse_version ("Candidate"); + // Candidate should fallback to Installed. + // + assert (pp.installed_version.empty () || + !pp.candidate_version.empty ()); + // Skip the rest of the indented lines (or blanks, just in case). // - while (!eof (getline (is, l)) && (l.empty () || l.front () != ' ')) ; + while (!eof (getline (is, l)) && (l.empty () || l.front () == ' ')) ; } } @@ -353,7 +452,7 @@ namespace bpkg // specified package and version. Fail if either package or version is // unknown. // - static string + string system_package_manager_debian:: apt_cache_show (const string& name, const string& ver) { assert (!name.empty () && !ver.empty ()); @@ -377,7 +476,7 @@ namespace bpkg string r; try { - if (apt_cache_path.empty ()) + if (apt_cache_path.empty () && !simulate_) apt_cache_path = process::path_search (args[0]); process_env pe (apt_cache_path, evars); @@ -388,13 +487,48 @@ namespace bpkg // Redirect stdout to a pipe. For good measure also redirect stdin to // /dev/null to make sure there are no prompts of any kind. // - process pr (apt_cache_path, - args, - -2 /* stdin */, - -1 /* stdout */, - 2 /* stderr */, - nullptr /* cwd */, - evars); + process pr; + if (!simulate_) + pr = process (apt_cache_path, + args, + -2 /* stdin */, + -1 /* stdout */, + 2 /* stderr */, + nullptr /* cwd */, + evars); + else + { + print_process (pe, args); + + pair k (name, ver); + + const path* f (nullptr); + if (fetched_) + { + auto i (simulate_->apt_cache_show_fetched_.find (k)); + if (i != simulate_->apt_cache_show_fetched_.end ()) + f = &i->second; + } + if (f == nullptr) + { + auto i (simulate_->apt_cache_show_.find (k)); + if (i != simulate_->apt_cache_show_.end ()) + f = &i->second; + } + + if (f == nullptr || f->empty ()) + { + text << "E: No packages found"; + pr = process (process_exit (100)); + } + else + { + pr = process (process_exit (0)); + pr.in_ofd = f->string () == "-" + ? fddup (stdin_fd ()) + : fdopen (*f, fdopen_mode::in); + } + } bool no_version (false); try @@ -435,10 +569,13 @@ namespace bpkg do { - // This line should be the start of a field unless it's a - // comment. According to deb822(5), there can be no leading - // whitespaces before `#`. + // This line should be the start of a field unless it's a comment + // or the terminating blank line. According to deb822(5), there + // can be no leading whitespaces before `#`. // + if (l.empty ()) + break; + if (l[0] == '#') { getline (is, l); @@ -533,75 +670,15 @@ namespace bpkg return r; } - // Attempt to determine the main package name from its -dev package. Return - // empty string if unable. Save the extracted Depends value to the depends - // argument for diagnostics. - // - static string - main_from_dev (const string& dev_name, - const string& dev_ver, - string& depends) - { - depends = apt_cache_show (dev_name, dev_ver); - - // The format of the Depends value is a comma-seperated list of dependency - // expressions. For example: - // - // Depends: libssl3 (= 3.0.7-1), libc6 (>= 2.34), libfoo | libbar - // - // For the main package we look for a dependency in the form: - // - // * (= ) - // - // Usually it is the first one. - // - string dev_stem (dev_name, 0, dev_name.rfind ("-dev")); - - string r; - for (size_t b (0), e (0); next_word (depends, b, e, ','); ) - { - string d (depends, b, e - b); - trim (d); - - size_t p (d.find (' ')); - if (p != string::npos) - { - if (d.compare (0, dev_stem.size (), dev_stem) == 0) // * - { - size_t q (d.find ('(', p + 1)); - if (q != string::npos && d.back () == ')') // (...) - { - if (d[q + 1] == '=' && d[q + 2] == ' ') // Equal. - { - string v (d, q + 3, d.size () - q - 3 - 1); - trim (v); - - if (v == dev_ver) - { - r.assign (d, 0, p); - break; - } - } - } - } - } - } - - return r; - } - // Prepare the common `apt-get ` options. // - static pair - apt_get_common (const char* command, - const string& sudo, - optional progress, - bool yes) + pair system_package_manager_debian:: + apt_get_common (const char* command) { cstrings args; - if (!sudo.empty ()) - args.push_back (sudo.c_str ()); + if (!sudo_.empty ()) + args.push_back (sudo_.c_str ()); args.push_back ("apt-get"); args.push_back (command); @@ -621,7 +698,7 @@ namespace bpkg // apt-get install it shows additionally progress during unpacking which // looks quite odd. // - if (progress && *progress) + if (progress_ && *progress_) { args.push_back ("--quiet=0"); } @@ -629,14 +706,14 @@ namespace bpkg { // Only use level 2 if assuming yes. // - args.push_back (yes ? "--quiet=2" : "--quiet"); + args.push_back (yes_ ? "--quiet=2" : "--quiet"); } - else if (progress && !*progress) + else if (progress_ && !*progress_) { args.push_back ("--quiet"); } - if (yes) + if (yes_) { args.push_back ("--assume-yes"); } @@ -651,16 +728,16 @@ namespace bpkg { const process_path* pp (nullptr); - if (!sudo.empty ()) + if (!sudo_.empty ()) { - if (sudo_path.empty ()) + if (sudo_path.empty () && !simulate_) sudo_path = process::path_search (args[0]); pp = &sudo_path; } else { - if (apt_get_path.empty ()) + if (apt_get_path.empty () && !simulate_) apt_get_path = process::path_search (args[0]); pp = &apt_get_path; @@ -681,11 +758,10 @@ namespace bpkg // Execute `apt-get update` to update the package index. // - static void - apt_get_update (const string& sudo, optional progress, bool yes) + void system_package_manager_debian:: + apt_get_update () { - pair args_pp ( - apt_get_common ("update", sudo, progress, yes)); + pair args_pp (apt_get_common ("update")); cstrings& args (args_pp.first); const process_path& pp (args_pp.second); @@ -699,16 +775,21 @@ namespace bpkg else if (verb) text << "updating Debian package index..."; - // We don't expect any prompts from apt-get update, but who knows. - // - process pr (pp, args); + process pr; + if (!simulate_) + pr = process (pp, args); + else + { + print_process (args); + pr = process (process_exit (simulate_->apt_get_update_fail_ ? 100 : 0)); + } if (!pr.wait ()) { diag_record dr (fail); dr << "apt-get update exited with non-zero code"; - if (verb < 3) + if (verb < 2) { dr << "command line: "; print_process (dr, args); @@ -726,19 +807,15 @@ namespace bpkg } } - // Execute `apt-get install` to install the specified packages/version + // Execute `apt-get install` to install the specified packages/versions // (e.g., libfoo or libfoo=1.2.3). // - static void - apt_get_install (const strings& pkgs, - const string& sudo, - optional progress, - bool yes) + void system_package_manager_debian:: + apt_get_install (const strings& pkgs) { assert (!pkgs.empty ()); - pair args_pp ( - apt_get_common ("install", sudo, progress, yes)); + pair args_pp (apt_get_common ("install")); cstrings& args (args_pp.first); const process_path& pp (args_pp.second); @@ -755,14 +832,21 @@ namespace bpkg else if (verb) text << "installing Debian packages..."; - process pr (pp, args); + process pr; + if (!simulate_) + pr = process (pp, args); + else + { + print_process (args); + pr = process (process_exit (simulate_->apt_get_install_fail_ ? 100 : 0)); + } if (!pr.wait ()) { diag_record dr (fail); dr << "apt-get install exited with non-zero code"; - if (verb < 3) + if (verb < 2) { dr << "command line: "; print_process (dr, args); @@ -783,8 +867,7 @@ namespace bpkg } } - optional - system_package_manager_debian:: + optional system_package_manager_debian:: pkg_status (const package_name& pn, const available_packages* aps) { // For now we ignore -doc and -dbg package components (but we may want to @@ -806,7 +889,7 @@ namespace bpkg return nullopt; } - vector candidates; + vector candidates; // Translate our package name to the Debian package names. // @@ -838,10 +921,10 @@ namespace bpkg // Keep the main package name empty as an indication that it is to // be discovered. // - candidates.push_back (package_status_debian ("", n + "-dev")); + candidates.push_back (package_status ("", n + "-dev")); } else - candidates.push_back (package_status_debian (n)); + candidates.push_back (package_status (n)); } else { @@ -849,13 +932,13 @@ namespace bpkg // for (const string& n: ns) { - package_status_debian s (parse_debian_name (n, need_doc, need_dbg)); + package_status s (parse_debian_name (n, need_doc, need_dbg)); // Suppress duplicates for good measure based on the main package // name (and falling back to -dev if empty). // auto i (find_if (candidates.begin (), candidates.end (), - [&s] (const package_status_debian& x) + [&s] (const package_status& x) { return s.main.empty () ? s.dev == x.dev @@ -873,9 +956,10 @@ namespace bpkg // Guess unknown main package given the dev package and its version. // - auto guess_main = [&pn] (package_status_debian& s, const string& ver) + auto guess_main = [this, &pn] (package_status& s, const string& ver) { - string depends; + string depends (apt_cache_show (s.dev, ver)); + s.main = main_from_dev (s.dev, ver, depends); if (s.main.empty ()) @@ -924,9 +1008,9 @@ namespace bpkg // First look for an already fully installed package. // - optional r; + optional r; - for (package_status_debian& ps: candidates) + for (package_status& ps: candidates) { vector& pps (ps.package_policies); @@ -993,11 +1077,11 @@ namespace bpkg bool requery; if ((requery = fetch_ && !fetched_)) { - apt_get_update (sudo_, progress_, yes_); + apt_get_update (); fetched_ = true; } - for (package_status_debian& ps: candidates) + for (package_status& ps: candidates) { vector& pps (ps.package_policies); @@ -1064,7 +1148,7 @@ namespace bpkg if (!r) { - for (package_status_debian& ps: candidates) + for (package_status& ps: candidates) { if (ps.main.empty ()) continue; @@ -1146,7 +1230,7 @@ namespace bpkg auto it (status_cache_.find (pn)); assert (it != status_cache_.end () && it->second); - const package_status_debian& ps (*it->second); + const package_status& ps (*it->second); // At first it may seem we don't need to do anything for already fully // installed packages. But it's possible some of them were automatically @@ -1208,7 +1292,7 @@ namespace bpkg specs.push_back (move (s)); } - apt_get_install (specs, sudo_, progress_, yes_); + apt_get_install (specs); } // Verify that versions we have promised in pkg_status() match what @@ -1219,7 +1303,7 @@ namespace bpkg for (const package_name& pn: pns) { - const package_status_debian& ps (*status_cache_.find (pn)->second); + const package_status& ps (*status_cache_.find (pn)->second); pps.push_back (package_policy (ps.system_name)); } @@ -1228,7 +1312,7 @@ namespace bpkg auto i (pps.begin ()); for (const package_name& pn: pns) { - const package_status_debian& ps (*status_cache_.find (pn)->second); + const package_status& ps (*status_cache_.find (pn)->second); const package_policy& pp (*i++); if (pp.installed_version != ps.system_version) diff --git a/bpkg/system-package-manager-debian.hxx b/bpkg/system-package-manager-debian.hxx index fc4aeb7..d3b9f02 100644 --- a/bpkg/system-package-manager-debian.hxx +++ b/bpkg/system-package-manager-debian.hxx @@ -59,13 +59,12 @@ namespace bpkg // struct package_policy { - reference_wrapper name; - + string name; string installed_version; // Empty if none. string candidate_version; // Empty if none and no installed_version. explicit - package_policy (const string& n): name (n) {} + package_policy (string n): name (move (n)) {} }; vector package_policies; @@ -96,6 +95,63 @@ namespace bpkg // using system_package_manager::system_package_manager; + // Implementation details exposed for testing (see definitions for + // documentation). + // + public: + using package_status = system_package_status_debian; + using package_policy = package_status::package_policy; + + void + apt_cache_policy (vector&, size_t = 0); + + string + apt_cache_show (const string&, const string&); + + void + apt_get_update (); + + void + apt_get_install (const strings&); + + pair + apt_get_common (const char*); + + static string + main_from_dev (const string&, const string&, const string&); + + // If simulate is not NULL, then instead of executing the actual apt-cache + // and apt-get commands simulate their execution: (1) for apt-cache by + // printing their command lines and reading the results from files + // specified in the below apt_cache_* maps and (2) for apt-get by printing + // their command lines and failing if requested. + // + // In the (1) case if the corresponding map entry does not exist or the + // path is empty, then act as if the specified package/version is + // unknown. If the path is special "-" then read from stdin. For apt-cache + // different post-fetch and (for policy) post-install results can be + // specified (if the result is not found in one of the later maps, the + // previous map is used as a fallback). Note that the keys in the + // apt_cache_policy_* maps are the package sets and the corresponding + // result file is expected to contain (or not) the results for all of + // them. See apt_cache_policy() and apt_cache_show() implementations for + // details on the expected results. + // + struct simulation + { + std::map apt_cache_policy_; + std::map apt_cache_policy_fetched_; + std::map apt_cache_policy_installed_; + + std::map, path> apt_cache_show_; + std::map, path> apt_cache_show_fetched_; + + bool apt_get_update_fail_ = false; + bool apt_get_install_fail_ = false; + }; + + const simulation* simulate_ = nullptr; + protected: bool fetched_ = false; // True if already fetched metadata. bool installed_ = false; // True if already installed. diff --git a/bpkg/system-package-manager-debian.test.cxx b/bpkg/system-package-manager-debian.test.cxx new file mode 100644 index 0000000..dc5f418 --- /dev/null +++ b/bpkg/system-package-manager-debian.test.cxx @@ -0,0 +1,111 @@ +// file : bpkg/system-package-manager-debian.test.cxx -*- C++ -*- +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include + +#include + +#undef NDEBUG +#include + +using namespace std; + +namespace bpkg +{ + using package_status = system_package_status_debian; + using package_policy = package_status::package_policy; + + // Usage: args[0] ... + // + // Where is one of: + // + // apt-cache-policy ... result comes from stdin + // + // apt-cache-show result comes from stdin + // + // main-from-dev depends comes from stdin + // + int + main (int argc, char* argv[]) + try + { + assert (argc >= 2); // + + string cmd (argv[1]); + + // @@ TODO: add option to customize. + // + os_release osr {"debian", {}, "10", "", "Debian", "", ""}; + + system_package_manager_debian::simulation s; + system_package_manager_debian m (move (osr), + false /* install */, + false /* fetch */, + nullopt /* progress */, + false /* yes */, + "sudo"); + m.simulate_ = &s; + + if (cmd == "apt-cache-policy") + { + assert (argc >= 3); // ... + + strings key; + vector pps; + for (int i (2); i != argc; ++i) + { + key.push_back (argv[i]); + pps.push_back (package_policy (argv[i])); + } + + s.apt_cache_policy_.emplace (move (key), path ("-")); + + m.apt_cache_policy (pps); + + for (const package_policy& pp: pps) + { + cout << pp.name << " '" + << pp.installed_version << "' '" + << pp.candidate_version << "'\n"; + } + } + else if (cmd == "apt-cache-show") + { + assert (argc == 4); // + + pair key (argv[2], argv[3]); + + s.apt_cache_show_.emplace (key, path ("-")); + + cout << m.apt_cache_show (key.first, key.second) << "\n"; + } + else if (cmd == "main-from-dev") + { + assert (argc == 4); // + + string n (argv[2]); + string v (argv[3]); + string d; + getline (cin, d, '\0'); + + cout << m.main_from_dev (n, v, d) << "\n"; + } + else + fail << "unknown command '" << cmd << "'"; + + return 0; + } + catch (const failed&) + { + return 1; + } +} + +int +main (int argc, char* argv[]) +{ + return bpkg::main (argc, argv); +} diff --git a/bpkg/system-package-manager-debian.test.testscript b/bpkg/system-package-manager-debian.test.testscript new file mode 100644 index 0000000..290919f --- /dev/null +++ b/bpkg/system-package-manager-debian.test.testscript @@ -0,0 +1,169 @@ +# file : bpkg/host-os-release.test.testscript +# license : MIT; see accompanying LICENSE file + +: apt-cache-policy +: +{ + test.arguments += apt-cache-policy + + : basics + : + $* libssl3 libssl1.1 libssl-dev libsqlite5 libxerces-c-dev <>EOE >>EOO + libssl3: + Installed: 3.0.7-1 + Candidate: 3.0.7-2 + Version table: + 3.0.7-2 500 + 500 http://deb.debian.org/debian bookworm/main amd64 Packages + *** 3.0.7-1 100 + 100 /var/lib/dpkg/status + libssl1.1: + Installed: 1.1.1n-0+deb11u3 + Candidate: 1.1.1n-0+deb11u3 + Version table: + *** 1.1.1n-0+deb11u3 100 + 100 /var/lib/dpkg/status + libssl-dev: + Installed: 3.0.7-1 + Candidate: 3.0.7-2 + Version table: + 3.0.7-2 500 + 500 http://deb.debian.org/debian bookworm/main amd64 Packages + *** 3.0.7-1 100 + 100 /var/lib/dpkg/status + libxerces-c-dev: + Installed: (none) + Candidate: 3.2.4+debian-1 + Version table: + 3.2.4+debian-1 500 + 500 http://deb.debian.org/debian bookworm/main amd64 Packages + EOI + LC_ALL=C apt-cache policy --quiet libssl3 libssl1.1 libssl-dev libsqlite5 libxerces-c-dev + EOE + libssl3 '3.0.7-1' '3.0.7-2' + libssl1.1 '1.1.1n-0+deb11u3' '1.1.1n-0+deb11u3' + libssl-dev '3.0.7-1' '3.0.7-2' + libsqlite5 '' '' + libxerces-c-dev '' '3.2.4+debian-1' + EOO + + : empty + : + $* libsqlite5 <:'' 2>>EOE >>EOO + LC_ALL=C apt-cache policy --quiet libsqlite5 + EOE + libsqlite5 '' '' + EOO + + : none-none + : + $* pulseaudio <>EOE >>EOO + pulseaudio: + Installed: (none) + Candidate: (none) + Version table: + 1:11.1-1ubuntu7.5 -1 + 500 http://au.archive.ubuntu.com/ubuntu bionic-updates/main amd64 Packages + 1:11.1-1ubuntu7 -1 + 500 http://au.archive.ubuntu.com/ubuntu bionic/main amd64 Packages + EOI + LC_ALL=C apt-cache policy --quiet pulseaudio + EOE + pulseaudio '' '' + EOO +} + +: apt-cache-show +: +{ + test.arguments += apt-cache-show + + # Note: put Depends last to test folded/multiline parsing. + # + : basics + : + $* libssl1.1 1.1.1n-0+deb11u3 <>EOE >>EOO + Package: libssl1.1 + Status: install ok installed + Priority: optional + Section: libs + Installed-Size: 4120 + Maintainer: Debian OpenSSL Team + Architecture: amd64 + Multi-Arch: same + Source: openssl + Version: 1.1.1n-0+deb11u3 + Breaks: isync (<< 1.3.0-2), lighttpd (<< 1.4.49-2), python-boto (<< 2.44.0-1.1), python-httplib2 (<< 0.11.3-1), python-imaplib2 (<< 2.57-5), python3-boto (<< 2.44.0-1.1), python3-imaplib2 (<< 2.57-5) + Description: Secure Sockets Layer toolkit - shared libraries + This package is part of the OpenSSL project's implementation of the SSL + and TLS cryptographic protocols for secure communication over the + Internet. + . + It provides the libssl and libcrypto shared libraries. + Description-md5: 88547c6206c7fbc4fcc7d09ce100d210 + Homepage: https://www.openssl.org/ + Depends: libc6 (>= 2.25), debconf (>= 0.5) | debconf-2.0 + + EOI + LC_ALL=C apt-cache show --quiet libssl1.1=1.1.1n-0+deb11u3 + EOE + libc6 (>= 2.25), debconf (>= 0.5) | debconf-2.0 + EOO + + : no-depends + : + $* libssl1.1 1.1.1n-0+deb11u3 <>EOE >'' + Package: libssl1.1 + Status: install ok installed + Priority: optional + Section: libs + Installed-Size: 4120 + Maintainer: Debian OpenSSL Team + Architecture: amd64 + Multi-Arch: same + Source: openssl + Version: 1.1.1n-0+deb11u3 + Breaks: isync (<< 1.3.0-2), lighttpd (<< 1.4.49-2), python-boto (<< 2.44.0-1.1), python-httplib2 (<< 0.11.3-1), python-imaplib2 (<< 2.57-5), python3-boto (<< 2.44.0-1.1), python3-imaplib2 (<< 2.57-5) + Description: Secure Sockets Layer toolkit - shared libraries + This package is part of the OpenSSL project's implementation of the SSL + and TLS cryptographic protocols for secure communication over the + Internet. + . + It provides the libssl and libcrypto shared libraries. + Description-md5: 88547c6206c7fbc4fcc7d09ce100d210 + Homepage: https://www.openssl.org/ + + EOI + LC_ALL=C apt-cache show --quiet libssl1.1=1.1.1n-0+deb11u3 + EOE +} + +: main-from-dev +: +{ + test.arguments += main-from-dev + + : first + : + $* libssl-dev 3.0.7-1 <'libssl3' + libssl3 (= 3.0.7-1), debconf (>= 0.5) | debconf-2.0 + EOI + + : not-first + : + $* libxerces-c-dev 3.2.4+debian-1 <'libxerces-c3.2' + libc6-dev | libc-dev, libicu-dev, libxerces-c3.2 (= 3.2.4+debian-1) + EOI + + : exact + : + $* libexpat1-dev 2.5.0-1 <'libexpat1' + libexpat1 (= 2.5.0-1), libc6-dev | libc-dev + EOI + + : not-stem + : + $* libcurl4-openssl-dev 7.87.0-2 <'' + libcurl4 (= 7.87.0-2) + EOI +} diff --git a/bpkg/system-package-manager.cxx b/bpkg/system-package-manager.cxx index aa71284..5e556f9 100644 --- a/bpkg/system-package-manager.cxx +++ b/bpkg/system-package-manager.cxx @@ -35,6 +35,10 @@ namespace bpkg const string& sudo, const string& name) { + optional progress (co.progress () ? true : + co.no_progress () ? false : + optional ()); + unique_ptr r; if (optional osr = host_os_release (host)) @@ -63,7 +67,7 @@ namespace bpkg // @@ TODO: verify name if specified. r.reset (new system_package_manager_debian ( - co, move (*osr), install, fetch, yes, sudo)); + move (*osr), install, fetch, progress, yes, sudo)); } } } diff --git a/bpkg/system-package-manager.hxx b/bpkg/system-package-manager.hxx index be55176..35b7439 100644 --- a/bpkg/system-package-manager.hxx +++ b/bpkg/system-package-manager.hxx @@ -159,16 +159,14 @@ namespace bpkg // available version of the not yet installed or partially installed // packages. // - system_package_manager (const common_options& co, - os_release&& osr, + system_package_manager (os_release&& osr, bool install, bool fetch, + optional progress, bool yes, string sudo) : os_release_ (osr), - progress_ (co.progress () ? true : - co.no_progress () ? false : - optional ()), + progress_ (progress), install_ (install), fetch_ (fetch), yes_ (yes), -- cgit v1.1