From 937aaf25741fb2ed5ae1bb7841c11702c5a51ded Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 15 Mar 2018 11:20:17 +0200 Subject: Print status of all held packages in pkg-status if no packages were specified --- bpkg/manifest-utility.hxx | 2 + bpkg/pkg-status.cli | 9 ++-- bpkg/pkg-status.cxx | 135 ++++++++++++++++++++++++++++++---------------- 3 files changed, 97 insertions(+), 49 deletions(-) diff --git a/bpkg/manifest-utility.hxx b/bpkg/manifest-utility.hxx index ee73c4a..e7bc149 100644 --- a/bpkg/manifest-utility.hxx +++ b/bpkg/manifest-utility.hxx @@ -41,6 +41,8 @@ namespace bpkg return parse_package_name (s.c_str ()); } + // Return empty version if none is specified. + // version parse_package_version (const char*); diff --git a/bpkg/pkg-status.cli b/bpkg/pkg-status.cli index 3a346a6..6aa971e 100644 --- a/bpkg/pkg-status.cli +++ b/bpkg/pkg-status.cli @@ -15,13 +15,16 @@ namespace bpkg "\h|SYNOPSIS| - \c{\b{bpkg pkg-status}|\b{status} [] [\b{/}]...} + \c{\b{bpkg pkg-status}|\b{status} [] [[\b{/}]...]} \h|DESCRIPTION| The \cb{pkg-status} command prints the status of the specified packages - or, if is specified, package versions. Note that the status is - written to \cb{STDOUT}, not \cb{STDERR}. + or, if is specified, package versions. If no packages were + specified, then \cb{pkg-status} prints the status of all the held + packages (which are the packages that were explicitly built; see + \l{bpkg-pkg-build(1)}). Note that the status is written to \cb{STDOUT}, + not \cb{STDERR}. The status output format is regular. If several packages were specified, then each line starts with the package name (and version, if specified) diff --git a/bpkg/pkg-status.cxx b/bpkg/pkg-status.cxx index 84f7ce8..35b3db0 100644 --- a/bpkg/pkg-status.cxx +++ b/bpkg/pkg-status.cxx @@ -17,6 +17,14 @@ using namespace butl; namespace bpkg { + struct package + { + string name; + bpkg::version version; // Empty if unspecified. + shared_ptr selected; // NULL if none selected. + }; + using packages = vector; + int pkg_status (const pkg_status_options& o, cli::scanner& args) { @@ -25,47 +33,75 @@ namespace bpkg const dir_path& c (o.directory ()); l4 ([&]{trace << "configuration: " << c;}); - if (!args.more ()) - fail << "package name argument expected" << - info << "run 'bpkg help pkg-status' for more information"; - database db (open (c, trace)); transaction t (db.begin ()); session s; - for (bool multi (false); args.more (); ) + packages pkgs; + bool single (false); // True if single package specified by the user. { - const char* arg (args.next ()); - multi = multi || args.more (); + using query = query; + + if (args.more ()) + { + while (args.more ()) + { + const char* arg (args.next ()); + package p {parse_package_name (arg), + parse_package_version (arg), + nullptr}; - string n (parse_package_name (arg)); - version v (parse_package_version (arg)); + // Search in the packages that already exist in this configuration. + // + { + query q (query::name == p.name); - l4 ([&]{trace << "package " << n << "; version " << v;}); + if (!p.version.empty ()) + q = q && compare_version_eq (query::version, + p.version, + p.version.revision != 0); - // First search in the packages that already exist in this configuration. - // - shared_ptr p; - { - using query = query; - query q (query::name == n); + p.selected = db.query_one (q); + } + + pkgs.push_back (move (p)); + } - if (!v.empty ()) - q = q && compare_version_eq (query::version, v, v.revision != 0); + single = (pkgs.size () == 1); + } + else + { + // Find all held packages. + // + for (shared_ptr s: + pointer_result ( + db.query (query::hold_package))) + { + pkgs.push_back (package {s->name, version (), move (s)}); + } - p = db.query_one (q); + if (pkgs.empty ()) + { + info << "no held packages in the configuration"; + return 0; + } } + } - // Now look for available packages. + for (const package& p: pkgs) + { + l4 ([&]{trace << "package " << p.name << "; version " << p.version;}); + + // Look for available packages. // bool available; // At least one vailable package (stub or not). - vector> aps; + vector> apkgs; { shared_ptr rep (db.load ("")); // Root. using query = query; - query q (query::id.name == n); + query q (query::id.name == p.name); available = filter_one (rep, db.query (q)).first != nullptr; @@ -76,17 +112,18 @@ namespace bpkg // specific version (we still do it since there might be other // revisions). // - if (!v.empty ()) - q = q && - compare_version_eq (query::id.version, v, v.revision != 0); + if (!p.version.empty ()) + q = q && compare_version_eq (query::id.version, + p.version, + p.version.revision != 0); // And if we found an existing package, then only look for versions // greater than what already exists. Note that for a system wildcard // version we will always show all available versions (since it's // 0). // - if (p != nullptr) - q = q && query::id.version > p->version; + if (p.selected != nullptr) + q = q && query::id.version > p.selected->version; q += order_by_version_desc (query::id.version); @@ -94,38 +131,41 @@ namespace bpkg // explicitly added to the configuration and their complements, // recursively. // - aps = filter (rep, db.query (q)); + apkgs = filter (rep, db.query (q)); } } - if (multi) + // Suppress printing the package name if there is only one and it was + // specified by the user. + // + if (!single) { - cout << n; + cout << p.name; - if (!v.empty ()) - cout << '/' << v; + if (!p.version.empty ()) + cout << '/' << p.version; cout << ": "; } bool found (false); - if (p != nullptr) + if (const shared_ptr& s = p.selected) { - cout << p->state; + cout << s->state; - if (p->substate != package_substate::none) - cout << ',' << p->substate; + if (s->substate != package_substate::none) + cout << ',' << s->substate; // Also print the version of the package unless the user specified it. // - if (v != p->version) - cout << ' ' << p->version_string (); + if (p.version != s->version) + cout << ' ' << s->version_string (); - if (p->hold_package) + if (s->hold_package) cout << " hold_package"; - if (p->hold_version) + if (s->hold_version) cout << " hold_version"; found = true; @@ -141,22 +181,25 @@ namespace bpkg // the user. We will later compare it if the user did specify the // version. // - bool sys (v.empty ()); + bool sys (p.version.empty ()); - if (!aps.empty ()) + if (!apkgs.empty ()) { // If the user specified the version, then there might only be one // entry in which case it is useless to repeat it. But we do want // to print it if there is also a system one. // - if (sys || v.empty () || aps.size () > 1 || aps[0]->version != v) + if (sys || + p.version.empty () || + apkgs.size () > 1 || + p.version != apkgs[0]->version) { - for (shared_ptr ap: aps) + for (const shared_ptr& a: apkgs) { - if (ap->stub ()) + if (a->stub ()) break; // All the rest are stubs so bail out. - cout << ' ' << ap->version; + cout << ' ' << a->version; } } } -- cgit v1.1