aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bpkg/manifest-utility.hxx2
-rw-r--r--bpkg/pkg-status.cli9
-rw-r--r--bpkg/pkg-status.cxx135
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} [<options>] <pkg>[\b{/}<ver>]...}
+ \c{\b{bpkg pkg-status}|\b{status} [<options>] [<pkg>[\b{/}<ver>]...]}
\h|DESCRIPTION|
The \cb{pkg-status} command prints the status of the specified packages
- or, if <ver> is specified, package versions. Note that the status is
- written to \cb{STDOUT}, not \cb{STDERR}.
+ or, if <ver> 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_package> selected; // NULL if none selected.
+ };
+ using packages = vector<package>;
+
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<selected_package>;
+
+ 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<selected_package> p;
- {
- using query = query<selected_package>;
- query q (query::name == n);
+ p.selected = db.query_one<selected_package> (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<selected_package> s:
+ pointer_result (
+ db.query<selected_package> (query::hold_package)))
+ {
+ pkgs.push_back (package {s->name, version (), move (s)});
+ }
- p = db.query_one<selected_package> (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<shared_ptr<available_package>> aps;
+ vector<shared_ptr<available_package>> apkgs;
{
shared_ptr<repository> rep (db.load<repository> ("")); // Root.
using query = query<available_package>;
- query q (query::id.name == n);
+ query q (query::id.name == p.name);
available =
filter_one (rep, db.query<available_package> (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<available_package> (q));
+ apkgs = filter (rep, db.query<available_package> (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<selected_package>& 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<available_package> ap: aps)
+ for (const shared_ptr<available_package>& a: apkgs)
{
- if (ap->stub ())
+ if (a->stub ())
break; // All the rest are stubs so bail out.
- cout << ' ' << ap->version;
+ cout << ' ' << a->version;
}
}
}