aboutsummaryrefslogtreecommitdiff
path: root/bpkg/pkg-drop.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bpkg/pkg-drop.cxx')
-rw-r--r--bpkg/pkg-drop.cxx171
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;