From 9ffd711094b68d8ce5bb464621020ccc993d787c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 15 Mar 2018 13:08:45 +0200 Subject: Add --immediate|-i and --recursive|-r to pkg-status for dependencies --- bpkg/pkg-status.cli | 20 +++++- bpkg/pkg-status.cxx | 171 +++++++++++++++++++++++++++++++++------------------- bpkg/rep-list.cxx | 4 +- 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 { " ", + // NOTE: remember to update in bdep-status if changing the + // argument format. + // "\h|SYNOPSIS| \c{\b{bpkg pkg-status}|\b{status} [] [[\b{/}]...]} @@ -23,8 +26,11 @@ namespace bpkg 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}. + \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; - 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; - - 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 (q); - } - - pkgs.push_back (move (p)); - } - - 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)}); - } - - 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 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; + + 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 (q); + } + + pkgs.push_back (move (p)); + } + + 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)}); + } + + 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); } -- cgit v1.1