diff options
Diffstat (limited to 'bpkg/pkg-drop.cxx')
-rw-r--r-- | bpkg/pkg-drop.cxx | 171 |
1 files changed, 127 insertions, 44 deletions
diff --git a/bpkg/pkg-drop.cxx b/bpkg/pkg-drop.cxx index 2e9969c..d8fa4ea 100644 --- a/bpkg/pkg-drop.cxx +++ b/bpkg/pkg-drop.cxx @@ -7,6 +7,8 @@ #include <list> #include <iostream> // cout +#include <libbutl/path-pattern.hxx> + #include <bpkg/package.hxx> #include <bpkg/package-odb.hxx> #include <bpkg/database.hxx> @@ -49,23 +51,23 @@ namespace bpkg }; using dependent_names = vector<dependent_name>; - // A "dependency-ordered" list of packages and their prerequisites. - // That is, every package on the list only possibly depending on the - // ones after it. In a nutshell, the usage is as follows: we first add - // the packages specified by the user (the "user selection"). We then - // collect all the dependent packages of the user selection, if any. - // These will either have to be dropped as well or we cannot continue. - // If the user gave the go ahead to drop the dependents, then, for our - // purposes, this list of dependents can from now own be treated as if - // it was a part of the user selection. The next step is to collect all - // the non-held prerequisites of the user selection with the goal of - // figuring out which ones will no longer be needed and offering to - // drop them as well. This part is a bit tricky and has to be done in - // three steps: We first collect all the prerequisites that we could - // possibly be dropping. We then order all the packages. And, finally, - // we filter out prerequisites that we cannot drop. See the comment to - // the call to collect_prerequisites() for details on why it has to be - // done this way. + // A "dependency-ordered" list of packages and their prerequisites. That is, + // every package on the list only possibly depending on the ones after it. + // In a nutshell, the usage is as follows: we first add the packages + // specified by the user (the "user selection"). We then collect all the + // dependent packages of the user selection, if any. These will either have + // to be dropped as well or we cannot continue and need to either issue + // diagnostics and fail or exit with the specified (via --dependent-exit) + // code. If the user gave the go ahead to drop the dependents, then, for our + // purposes, this list of dependents can from now own be treated as if it + // was a part of the user selection. The next step is to collect all the + // non-held prerequisites of the user selection with the goal of figuring + // out which ones will no longer be needed and offering to drop them as + // well. This part is a bit tricky and has to be done in three steps: We + // first collect all the prerequisites that we could possibly be dropping. + // We then order all the packages. And, finally, we filter out prerequisites + // that we cannot drop. See the comment to the call to + // collect_prerequisites() for details on why it has to be done this way. // struct drop_packages: list<reference_wrapper<drop_package>> { @@ -77,7 +79,7 @@ namespace bpkg drop_reason r = drop_reason::user) { package_name n (p->name); // Because of move(p) below. - return map_.emplace (config_package {db, move (n)}, + return map_.emplace (package_key {db, move (n)}, data_type {end (), {db, move (p), r}}).second; } @@ -278,7 +280,7 @@ namespace bpkg if (!keep) { i = erase (i); - map_.erase (config_package {db, p->name}); + map_.erase (package_key {db, p->name}); continue; } @@ -298,18 +300,18 @@ namespace bpkg drop_package package; }; - class config_package_map: public map<config_package, data_type> + class package_map: public map<package_key, data_type> { public: - using base_type = map<config_package, data_type>; + using base_type = map<package_key, data_type>; iterator find (database& db, const package_name& pn) { - return base_type::find (config_package {db, pn}); + return base_type::find (package_key {db, pn}); } }; - config_package_map map_; + package_map map_; }; // Drop ordered list of packages. @@ -371,7 +373,9 @@ namespace bpkg return 1; bool result (verb && !o.no_result ()); - bool progress (!result && verb == 1 && !o.no_progress () && stderr_term); + bool progress (!result && + ((verb == 1 && !o.no_progress () && stderr_term) || + o.progress ())); size_t prog_i, prog_n, prog_percent; @@ -504,17 +508,50 @@ namespace bpkg const dir_path& c (o.directory ()); l4 ([&]{trace << "configuration: " << c;}); - if (o.yes () && o.no ()) - fail << "both --yes|-y and --no|-n specified"; + { + diag_record dr; - if (o.drop_dependent () && o.keep_dependent ()) - fail << "both --drop-dependent and --keep-dependent|-K " - << "specified" << - info << "run 'bpkg help pkg-drop' for more information"; + if (o.yes () && o.no ()) + { + dr << fail << "both --yes|-y and --no|-n specified"; + } + else if (o.drop_dependent () && o.keep_dependent ()) + { + dr << fail << "both --drop-dependent and --keep-dependent|-K " + << "specified"; + } + else if (o.drop_dependent () && o.dependent_exit_specified ()) + { + dr << fail << "both --drop-dependent and --dependent-exit " + << "specified"; + } + else if (o.keep_dependent () && o.dependent_exit_specified ()) + { + dr << fail << "both --keep-dependent|-K and --dependent-exit " + << "specified"; + } + else if (o.all ()) + { + if (o.all_pattern_specified ()) + dr << fail << "both --all|-a and --all-pattern specified"; + + if (args.more ()) + dr << fail << "both --all|-a and package argument specified"; + } + else if (o.all_pattern_specified ()) + { + if (args.more ()) + dr << fail << "both --all-pattern and package argument specified"; + } + else if (!args.more ()) + { + dr << fail << "package name argument expected"; + } + + if (!dr.empty ()) + dr << info << "run 'bpkg help pkg-drop' for more information"; + } - if (!args.more ()) - fail << "package name argument expected" << - info << "run 'bpkg help pkg-drop' for more information"; database db (c, trace, true /* pre_attach */); @@ -544,17 +581,10 @@ namespace bpkg // by the user. // vector<package_name> names; - while (args.more ()) - { - package_name n (parse_package_name (args.next (), - false /* allow_version */)); - - l4 ([&]{trace << "package " << n;}); - - shared_ptr<selected_package> p (db.find<selected_package> (n)); - if (p == nullptr) - fail << "package " << n << " does not exist in configuration " << c; + auto add = [&names, &pkgs, &db] (shared_ptr<selected_package>&& p) + { + package_name n (p->name); if (p->state == package_state::broken) fail << "unable to drop broken package " << n << @@ -562,15 +592,68 @@ namespace bpkg if (pkgs.collect (db, move (p))) names.push_back (move (n)); + }; + + if (o.all () || o.all_pattern_specified ()) + { + using query = query<selected_package>; + + for (shared_ptr<selected_package> p: + pointer_result ( + db.query<selected_package> (query::hold_package))) + { + l4 ([&]{trace << *p;}); + + if (o.all_pattern_specified ()) + { + for (const string& pat: o.all_pattern ()) + { + if (path_match (p->name.string (), pat)) + { + add (move (p)); + break; + } + } + } + else // --all + add (move (p)); + } + + if (names.empty ()) + info << "nothing to drop"; + } + else + { + while (args.more ()) + { + package_name n (parse_package_name (args.next (), + false /* allow_version */)); + + l4 ([&]{trace << "package " << n;}); + + shared_ptr<selected_package> p (db.find<selected_package> (n)); + + if (p == nullptr) + fail << "package " << n << " does not exist in configuration " << c; + + add (move (p)); + } } // The next step is to see if there are any dependents that are not // already on the list. We will either have to drop those as well or - // abort. + // issue diagnostics and fail or silently indicate that with an exit + // code. // dependent_names dnames (pkgs.collect_dependents ()); if (!dnames.empty () && !o.drop_dependent ()) { + if (o.dependent_exit_specified ()) + { + t.commit (); + return o.dependent_exit (); + } + { diag_record dr; |