aboutsummaryrefslogtreecommitdiff
path: root/bpkg
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-03-16 14:25:17 +0200
committerKaren Arutyunov <karen@codesynthesis.com>2018-03-16 19:03:39 +0300
commit36026ec0a05d74776114ddf5aee096fbda9bc7ee (patch)
tree069ae3f92988641749b3b77865c2b9a12e74e8bb /bpkg
parentbe961c92f1306ad16392eb90dbaa579353c9033e (diff)
Redo pkg-status output
Diffstat (limited to 'bpkg')
-rw-r--r--bpkg/package.cxx12
-rw-r--r--bpkg/package.hxx5
-rw-r--r--bpkg/pkg-status.cli97
-rw-r--r--bpkg/pkg-status.cxx202
4 files changed, 198 insertions, 118 deletions
diff --git a/bpkg/package.cxx b/bpkg/package.cxx
index 966be72..da862ef 100644
--- a/bpkg/package.cxx
+++ b/bpkg/package.cxx
@@ -104,10 +104,10 @@ namespace bpkg
return nullptr;
}
- static inline shared_ptr<repository>
- find (const shared_ptr<repository>& r,
- const shared_ptr<available_package>& ap,
- bool prereq)
+ shared_ptr<repository>
+ filter (const shared_ptr<repository>& r,
+ const shared_ptr<available_package>& ap,
+ bool prereq)
{
repositories chain;
return find (r, ap, chain, prereq);
@@ -122,7 +122,7 @@ namespace bpkg
for (shared_ptr<available_package> ap: pointer_result (apr))
{
- if (find (r, ap, prereq) != nullptr)
+ if (filter (r, ap, prereq) != nullptr)
aps.push_back (move (ap));
}
@@ -138,7 +138,7 @@ namespace bpkg
for (shared_ptr<available_package> ap: pointer_result (apr))
{
- if (shared_ptr<repository> pr = find (r, ap, prereq))
+ if (shared_ptr<repository> pr = filter (r, ap, prereq))
return result (move (ap), move (pr));
}
diff --git a/bpkg/package.hxx b/bpkg/package.hxx
index 8c714c4..58338bd 100644
--- a/bpkg/package.hxx
+++ b/bpkg/package.hxx
@@ -499,6 +499,11 @@ namespace bpkg
odb::result<available_package>&&,
bool prereq = true);
+ shared_ptr<repository>
+ filter (const shared_ptr<repository>&,
+ const shared_ptr<available_package>&,
+ bool prereq = true);
+
// package_state
//
enum class package_state
diff --git a/bpkg/pkg-status.cli b/bpkg/pkg-status.cli
index 6157c4d..09c6b2c 100644
--- a/bpkg/pkg-status.cli
+++ b/bpkg/pkg-status.cli
@@ -32,11 +32,11 @@ namespace bpkg
respectively. 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)
- followed by '\cb{:}'. Then comes one of the status words listed below.
- Some of them can be optionally followed by '\cb{,}' (no spaces) and a
- sub-status word.
+ The status output format is regular with components separated with
+ spaces. Each line starts with the package name (and version, if
+ specified) followed by one of the status words listed below. Some of
+ them can be optionally followed by '\cb{,}' (no spaces) and a sub-status
+ word.
\dl|
@@ -73,58 +73,65 @@ namespace bpkg
If only the package name was specified without the package version, then
the \cb{available} status word is followed by the list of available
- versions. The last version on this list may have the \cb{sys:} prefix
- indicating an available system version. Such a system version may be
- the special '\cb{?}' value indicating that a package may or may not
- be available from the system and its version is unknown.
+ versions. If the \cb{--system} option is specified, then the last version
+ in this list may have the \cb{sys:} prefix indicating an available system
+ version. Such a system version may be the special '\cb{?}' value
+ indicating that a package may or may not be available from the system and
+ that its version is unknown.
Similarly, if only the package name was specified, then the \cb{fetched},
\cb{unpacked}, \cb{configured}, and \cb{broken} status words are followed
- by the version of the package. After the package version, these status
- words may be followed by one or more sub-status words. Currently, these
- can be \cb{hold_package} (package should not be automatically dropped) and
- \cb{hold_version} (package should not be automatically upgraded). Finally,
- if only the package name was specified and newer versions are available
- from some of the repositories, then the sub-status word is followed
- by '\cb{;}', the \cb{available} status word, and the list of newer
- versions.
+ by the version of the package. If newer versions are available, then the
+ package version is followed by the \cb{available} status word and the
+ list of newer versions.
+
+ If the package name was specified with the version, then only the status
+ (such as, \cb{configured}, \cb{available}, etc.) of this version is
+ printed.
+
+ If a package is being held, then its name is printed prefixed with
+ '\cb{!}'. Similarly, if a package version is being held, then the version
+ is printed prefixed with '\cb{!}'. Held packages and held versions were
+ selected by the user and are not automatically dropped and upgraded,
+ respectively.
Below are some examples, assuming the configuration has \cb{libfoo}
- \cb{1.0.0} configured and held as well as \cb{libfoo} \cb{1.1.0} and
- \cb{1.1.1} available from source and \cb{1.1.0} from the system.
+ \cb{1.0.0} configured and held (both package and version) as well as
+ \cb{libfoo} \cb{1.1.0} and \cb{1.1.1} available from source and
+ \cb{1.1.0} from the system.
\
bpkg status libbar
- unknown
+ libbar unknown
bpkg status libbar/1.0.0
- unknown
+ libbar/1.0.0 unknown
bpkg status libfoo/1.0.0
- configured hold_package
+ !libfoo/1.0.0 configured !1.0.0
bpkg status libfoo/1.1.0
- available 1.1.0 sys:1.1.0
+ libfoo/1.1.0 available 1.1.0
- bpkg status libfoo/1.1.1
- available
+ bpkg status --system libfoo/1.1.0
+ libfoo/1.1.0 available 1.1.0 sys:1.1.0
bpkg status libfoo
- configured 1.0.0 hold_package; available 1.1.0 1.1.1 sys:1.1.0
+ !libfoo configured !1.0.0 available 1.1.0 1.1.1
- bpkg status libfoo/1.0.0 libbar
- libfoo/1.0.0: configured hold_package
- libbar: unknown
+ bpkg status libfoo/1.1.1 libbar
+ libfoo/1.1.1 available 1.1.1
+ libbar unknown
\
Assuming now that we dropped \cb{libfoo} from the configuration:
\
bpkg status libfoo/1.0.0
- unknown
+ libfoo/1.0.0 unknown
bpkg status libfoo
- available 1.1.0 1.1.1 sys:1.1.0
+ libfoo available 1.1.0 1.1.1
\
And assuming now that we built \cb{libfoo} as a system package with
@@ -132,8 +139,7 @@ namespace bpkg
\
bpkg status libfoo
- configured,system * hold_package; available 1.1.0 1.1.1 sys:1.1.0
- unknown
+ !libfoo configured,system * available 1.1.0 1.1.1
\
"
@@ -152,5 +158,30 @@ namespace bpkg
{
"Also print the status of all dependencies, recursively."
}
+
+ bool --constraint
+ {
+ "Print version constraints for dependencies."
+ }
+
+ bool --system
+ {
+ "Check the availability of packages from the system."
+ }
+
+ bool --no-hold
+ {
+ "Don't print the package or version hold status."
+ }
+
+ bool --no-hold-package
+ {
+ "Don't print the package hold status."
+ }
+
+ bool --no-hold-version
+ {
+ "Don't print the version hold status."
+ }
};
}
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;