aboutsummaryrefslogtreecommitdiff
path: root/bpkg/pkg-status.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bpkg/pkg-status.cxx')
-rw-r--r--bpkg/pkg-status.cxx202
1 files changed, 123 insertions, 79 deletions
diff --git a/bpkg/pkg-status.cxx b/bpkg/pkg-status.cxx
index e5144ca..a93322e 100644
--- a/bpkg/pkg-status.cxx
+++ b/bpkg/pkg-status.cxx
@@ -19,19 +19,20 @@ namespace bpkg
{
struct package
{
- string name;
- bpkg::version version; // Empty if unspecified.
- shared_ptr<selected_package> selected; // NULL if none selected.
+ string name;
+ bpkg::version version; // Empty if unspecified.
+ shared_ptr<selected_package> selected; // NULL if none selected.
+ optional<dependency_constraint> constraint; // Version constraint, if any.
};
using packages = vector<package>;
- // If single is true, then omit the package name. If recursive or immediate
- // is true, then print status for dependencies indented by two spaces.
+ // If recursive or immediate is true, then print status for dependencies
+ // indented by two spaces.
//
static void
- pkg_status (database& db,
+ pkg_status (const pkg_status_options& o,
+ database& db,
const packages& pkgs,
- bool single,
string& indent,
bool recursive,
bool immediate)
@@ -42,21 +43,41 @@ namespace bpkg
{
l4 ([&]{trace << "package " << p.name << "; version " << p.version;});
+ // Can't be both.
+ //
+ assert (p.version.empty () || !p.constraint);
+
+ const shared_ptr<selected_package>& s (p.selected);
+
// Look for available packages.
//
- bool available; // At least one vailable package (stub or not).
- vector<shared_ptr<available_package>> apkgs;
+ // Some of them are only available to upgrade/downgrade as dependencies.
+ //
+ struct apkg
+ {
+ shared_ptr<available_package> package;
+ bool build;
+ };
+ vector<apkg> apkgs;
+
+ // A package with this name is known in available packages potentially
+ // for build.
+ //
+ bool known (false);
+ bool build (false);
{
shared_ptr<repository> rep (db.load<repository> ("")); // Root.
using query = query<available_package>;
query q (query::id.name == p.name);
+ {
+ auto r (db.query<available_package> (q));
+ known = !r.empty ();
+ build = filter_one (rep, move (r)).first != nullptr;
+ }
- available =
- filter_one (rep, db.query<available_package> (q)).first != nullptr;
-
- if (available)
+ if (known)
{
// If the user specified the version, then only look for that
// specific version (we still do it since there might be other
@@ -69,103 +90,127 @@ namespace bpkg
false);
// 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).
+ // greater than to what already exists. Note that for a system
+ // wildcard version we will always show all available versions
+ // (since it's 0).
//
- if (p.selected != nullptr)
- q = q && query::id.version > p.selected->version;
+ if (s != nullptr)
+ q = q && query::id.version > s->version;
q += order_by_version_desc (query::id.version);
- // Only consider packages that are in repositories that were
- // explicitly added to the configuration and their complements,
- // recursively.
+ // Packages that are in repositories that were explicitly added to
+ // the configuration and their complements, recursively, are also
+ // available to build.
//
- apkgs = filter (rep, db.query<available_package> (q));
+ for (shared_ptr<available_package> ap:
+ pointer_result (
+ db.query<available_package> (q)))
+ {
+ bool build (filter (rep, ap));
+ apkgs.push_back (apkg {move (ap), build});
+ }
}
}
cout << indent;
- // Suppress printing the package name if there is only one and it was
- // specified by the user.
+ // Selected.
+ //
+
+ // Hold package status.
//
- if (!single || immediate || recursive)
+ if (s != nullptr)
{
- cout << p.name;
+ if (s->hold_package && !o.no_hold () && !o.no_hold_package ())
+ cout << '!';
+ }
- if (!p.version.empty ())
- cout << '/' << p.version;
+ cout << p.name;
- cout << ": ";
- }
+ if (o.constraint () && p.constraint)
+ cout << ' ' << *p.constraint;
- bool found (false);
+ cout << ' ';
- if (const shared_ptr<selected_package>& s = p.selected)
+ if (s != nullptr)
{
cout << s->state;
if (s->substate != package_substate::none)
cout << ',' << s->substate;
- // Also print the version of the package unless the user specified it.
- //
- if (p.version != s->version)
- cout << ' ' << s->version_string ();
-
- if (s->hold_package)
- cout << " hold_package";
+ cout << ' ';
- if (s->hold_version)
- cout << " hold_version";
+ if (s->hold_version && !o.no_hold () && !o.no_hold_version ())
+ cout << '!';
- found = true;
+ cout << s->version_string ();
}
- if (available)
+ // Available.
+ //
+ bool available (false);
+ if (known)
{
- cout << (found ? "; " : "") << "available";
-
+ // Available from the system.
+ //
// The idea is that in the future we will try to auto-discover a
// system version and then print that. For now we just say "maybe
- // available from the system" but only if no version was specified by
+ // available from the system" even if the version was specified by
// the user. We will later compare it if the user did specify the
// version.
//
- bool sys (p.version.empty ());
+ string sys;
+ if (o.system ())
+ {
+ sys = "?";
+ available = true;
+ }
- if (!apkgs.empty ())
+ // Get rid of stubs.
+ //
+ for (auto i (apkgs.begin ()); i != apkgs.end (); ++i)
{
- // 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 ||
- p.version.empty () ||
- apkgs.size () > 1 ||
- p.version != apkgs[0]->version)
+ if (i->package->stub ())
{
- for (const shared_ptr<available_package>& a: apkgs)
- {
- if (a->stub ())
- break; // All the rest are stubs so bail out.
-
- cout << ' ' << a->version;
- }
+ // All the rest are stubs so bail out.
+ //
+ apkgs.erase (i, apkgs.end ());
+ break;
}
- }
- if (sys)
- cout << " sys:?";
+ available = true;
+ }
- found = true;
+ if (available)
+ {
+ cout << (s != nullptr ? " " : "") << "available";
+
+ for (const apkg& a: apkgs)
+ cout << ' '
+ << (a.build ? "" : "[")
+ << a.package->version
+ << (a.build ? "" : "]");
+
+ if (!sys.empty ())
+ cout << ' '
+ << (build ? "" : "[")
+ << "sys:" << sys
+ << (build ? "" : "]");
+ }
}
- if (!found)
+ if (s == nullptr && !available)
+ {
cout << "unknown";
+ // Print the user's version if specified.
+ //
+ if (!p.version.empty ())
+ cout << ' ' << p.version;
+ }
+
cout << endl;
if (recursive || immediate)
@@ -173,21 +218,22 @@ namespace bpkg
// Collect and recurse.
//
packages dpkgs;
- if (p.selected != nullptr)
+ if (s != nullptr)
{
- for (const auto& pair: p.selected->prerequisites)
+ for (const auto& pair: s->prerequisites)
{
shared_ptr<selected_package> d (pair.first.load ());
- dpkgs.push_back (package {d->name, version (), move (d)});
+ const optional<dependency_constraint>& c (pair.second);
+ dpkgs.push_back (package {d->name, version (), move (d), c});
}
}
if (!dpkgs.empty ())
{
indent += " ";
- pkg_status (db,
+ pkg_status (o,
+ db,
dpkgs,
- false /* single */,
indent,
recursive,
false /* immediate */);
@@ -213,7 +259,6 @@ namespace bpkg
session s;
packages pkgs;
- bool single (false); // True if single package specified by the user.
{
using query = query<selected_package>;
@@ -224,7 +269,8 @@ namespace bpkg
const char* arg (args.next ());
package p {parse_package_name (arg),
parse_package_version (arg),
- nullptr};
+ nullptr /* selected */,
+ nullopt /* constraint */};
// Search in the packages that already exist in this configuration.
//
@@ -242,8 +288,6 @@ namespace bpkg
pkgs.push_back (move (p));
}
-
- single = (pkgs.size () == 1);
}
else
{
@@ -253,7 +297,7 @@ namespace bpkg
pointer_result (
db.query<selected_package> (query::hold_package)))
{
- pkgs.push_back (package {s->name, version (), move (s)});
+ pkgs.push_back (package {s->name, version (), move (s), nullopt});
}
if (pkgs.empty ())
@@ -265,7 +309,7 @@ namespace bpkg
}
string indent;
- pkg_status (db, pkgs, single, indent, o.recursive (), o.immediate ());
+ pkg_status (o, db, pkgs, indent, o.recursive (), o.immediate ());
t.commit ();
return 0;