aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bpkg/pkg-status.cli20
-rw-r--r--bpkg/pkg-status.cxx171
-rw-r--r--bpkg/rep-list.cxx4
3 files changed, 129 insertions, 66 deletions
diff --git a/bpkg/pkg-status.cli b/bpkg/pkg-status.cli
index 6aa971e..6157c4d 100644
--- a/bpkg/pkg-status.cli
+++ b/bpkg/pkg-status.cli
@@ -13,6 +13,9 @@ namespace bpkg
{
"<options> <pkg> <ver>",
+ // NOTE: remember to update <dep-spec> in bdep-status if changing the
+ // argument format.
+ //
"\h|SYNOPSIS|
\c{\b{bpkg pkg-status}|\b{status} [<options>] [<pkg>[\b{/}<ver>]...]}
@@ -23,8 +26,11 @@ namespace bpkg
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}.
+ \l{bpkg-pkg-build(1)}). Additionally, the status of immediate or all
+ dependencies of the above packages can be printed by specifying the
+ \c{\b{--immediate}|\b{-i}} or \c{\b{--recursive}|\b{-r}} options,
+ 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)
@@ -136,5 +142,15 @@ namespace bpkg
class pkg_status_options: configuration_options
{
"\h|PKG-STATUS OPTIONS|"
+
+ bool --immediate|-i
+ {
+ "Also print the status of immediate dependencies."
+ }
+
+ bool --recursive|-r
+ {
+ "Also print the status of all dependencies, recursively."
+ }
};
}
diff --git a/bpkg/pkg-status.cxx b/bpkg/pkg-status.cxx
index 35b3db0..b440ad9 100644
--- a/bpkg/pkg-status.cxx
+++ b/bpkg/pkg-status.cxx
@@ -25,69 +25,19 @@ namespace bpkg
};
using packages = vector<package>;
- int
- pkg_status (const pkg_status_options& o, cli::scanner& args)
+ // If single is true, then omit the package name. If recursive or immediate
+ // is true, then print status for dependencies indented by two spaces.
+ //
+ static void
+ pkg_status (database& db,
+ const packages& pkgs,
+ bool single,
+ string& indent,
+ bool recursive,
+ bool immediate)
{
tracer trace ("pkg_status");
- const dir_path& c (o.directory ());
- l4 ([&]{trace << "configuration: " << c;});
-
- database db (open (c, trace));
- transaction t (db.begin ());
- session s;
-
- packages pkgs;
- bool single (false); // True if single package specified by the user.
- {
- 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};
-
- // Search in the packages that already exist in this configuration.
- //
- {
- query q (query::name == p.name);
-
- if (!p.version.empty ())
- q = q && compare_version_eq (query::version,
- p.version,
- p.version.revision != 0);
-
- p.selected = db.query_one<selected_package> (q);
- }
-
- pkgs.push_back (move (p));
- }
-
- 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)});
- }
-
- if (pkgs.empty ())
- {
- info << "no held packages in the configuration";
- return 0;
- }
- }
- }
-
for (const package& p: pkgs)
{
l4 ([&]{trace << "package " << p.name << "; version " << p.version;});
@@ -135,10 +85,12 @@ namespace bpkg
}
}
+ cout << indent;
+
// Suppress printing the package name if there is only one and it was
// specified by the user.
//
- if (!single)
+ if (!single || immediate || recursive)
{
cout << p.name;
@@ -214,7 +166,104 @@ namespace bpkg
cout << "unknown";
cout << endl;
+
+ if (recursive || immediate)
+ {
+ // Collect and recurse.
+ //
+ packages dpkgs;
+ if (p.selected != nullptr)
+ {
+ for (const auto& pair: p.selected->prerequisites)
+ {
+ shared_ptr<selected_package> d (pair.first.load ());
+ dpkgs.push_back (package {d->name, version (), move (d)});
+ }
+ }
+
+ if (!dpkgs.empty ())
+ {
+ indent += " ";
+ pkg_status (db,
+ dpkgs,
+ false /* single */,
+ indent,
+ recursive,
+ false /* immediate */);
+ indent.resize (indent.size () - 2);
+ }
+ }
}
+ }
+
+ int
+ pkg_status (const pkg_status_options& o, cli::scanner& args)
+ {
+ tracer trace ("pkg_status");
+
+ if (o.immediate () && o.recursive ())
+ fail << "both --immediate|-i and --recursive|-r specified";
+
+ const dir_path& c (o.directory ());
+ l4 ([&]{trace << "configuration: " << c;});
+
+ database db (open (c, trace));
+ transaction t (db.begin ());
+ session s;
+
+ packages pkgs;
+ bool single (false); // True if single package specified by the user.
+ {
+ 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};
+
+ // Search in the packages that already exist in this configuration.
+ //
+ {
+ query q (query::name == p.name);
+
+ if (!p.version.empty ())
+ q = q && compare_version_eq (query::version,
+ p.version,
+ p.version.revision != 0);
+
+ p.selected = db.query_one<selected_package> (q);
+ }
+
+ pkgs.push_back (move (p));
+ }
+
+ 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)});
+ }
+
+ if (pkgs.empty ())
+ {
+ info << "no held packages in the configuration";
+ return 0;
+ }
+ }
+ }
+
+ string indent;
+ pkg_status (db, pkgs, single, indent, o.recursive (), o.immediate ());
t.commit ();
return 0;
diff --git a/bpkg/rep-list.cxx b/bpkg/rep-list.cxx
index f2aca2c..3ee52a9 100644
--- a/bpkg/rep-list.cxx
+++ b/bpkg/rep-list.cxx
@@ -75,9 +75,7 @@ namespace bpkg
}
}
- indent.pop_back ();
- indent.pop_back ();
-
+ indent.resize (indent.size () - 2);
chain.erase (r);
}