aboutsummaryrefslogtreecommitdiff
path: root/bpkg/pkg-drop.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-02-13 16:30:31 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-02-13 16:30:31 +0200
commit74bcab9dfa50647dd6615f261f2c2bc9f5a38951 (patch)
tree3cd60a784ff8a16b58ddd2ec4bb12003e9d11719 /bpkg/pkg-drop.cxx
parent4fd0df2573341824eea5edfaf45be33997ce56ce (diff)
Offer in pkg-build to drop prerequisite packages that are no longer necessary
This can happen if a package that is being upgraded/downgraded changes its dependencies.
Diffstat (limited to 'bpkg/pkg-drop.cxx')
-rw-r--r--bpkg/pkg-drop.cxx234
1 files changed, 165 insertions, 69 deletions
diff --git a/bpkg/pkg-drop.cxx b/bpkg/pkg-drop.cxx
index 8c979d2..66b9382 100644
--- a/bpkg/pkg-drop.cxx
+++ b/bpkg/pkg-drop.cxx
@@ -76,7 +76,7 @@ namespace bpkg
return map_.emplace (move (n), data_type {end (), {move (p), r}}).second;
}
- // Collect all the dependets of the user selection retutning the list
+ // Collect all the dependets of the user selection returning the list
// of their names. Dependents of dependents are collected recursively.
//
dependent_names
@@ -90,7 +90,7 @@ namespace bpkg
// Unconfigured package cannot have any dependents.
//
- if (dp.reason == drop_reason::user &&
+ if (dp.reason != drop_reason::dependent &&
dp.package->state == package_state::configured)
collect_dependents (db, dns, dp.package);
}
@@ -150,11 +150,11 @@ namespace bpkg
for (const auto& pair: p->prerequisites)
{
- const string& pn (pair.first.object_id ());
+ const lazy_shared_ptr<selected_package>& lpp (pair.first);
- if (map_.find (pn) == map_.end ())
+ if (map_.find (lpp.object_id ()) == map_.end ())
{
- shared_ptr<selected_package> pp (db.load<selected_package> (pn));
+ shared_ptr<selected_package> pp (lpp.load ());
if (!pp->hold_package) // Prune held packages.
{
@@ -288,6 +288,103 @@ namespace bpkg
map<string, data_type> map_;
};
+ // Drop ordered list of packages.
+ //
+ static int
+ pkg_drop (const dir_path& c,
+ const common_options& o,
+ database& db,
+ const drop_packages& pkgs,
+ bool drop_prq,
+ bool print_only,
+ bool disfigure_only,
+ bool yes,
+ bool no)
+ {
+ // Print what we are going to do, then ask for the user's confirmation.
+ //
+ if (print_only || !(yes || no))
+ {
+ for (const drop_package& dp: pkgs)
+ {
+ // Skip prerequisites if we weren't instructed to drop them.
+ //
+ if (dp.reason == drop_reason::prerequisite && !drop_prq)
+ continue;
+
+ const shared_ptr<selected_package>& p (dp.package);
+
+ if (print_only)
+ cout << "drop " << p->name << endl;
+ else if (verb)
+ text << "drop " << p->name;
+ }
+
+ if (print_only)
+ return 0;
+ }
+
+ // Ask the user if we should continue.
+ //
+ if (no || !(yes || yn_prompt ("continue? [Y/n]", 'y')))
+ return 1;
+
+ // All that's left to do is first disfigure configured packages and
+ // then purge all of them. We do both left to right (i.e., from more
+ // dependent to less dependent). For disfigure this order is required.
+ // For purge, it will be the order closest to the one specified by the
+ // user.
+ //
+ for (const drop_package& dp: pkgs)
+ {
+ // Skip prerequisites if we weren't instructed to drop them.
+ //
+ if (dp.reason == drop_reason::prerequisite && !drop_prq)
+ continue;
+
+ const shared_ptr<selected_package>& p (dp.package);
+
+ if (p->state != package_state::configured)
+ continue;
+
+ // Each package is disfigured in its own transaction, so that we always
+ // leave the configuration in a valid state.
+ //
+ transaction t (db.begin ());
+ pkg_disfigure (c, o, t, p); // Commits the transaction.
+ assert (p->state == package_state::unpacked);
+
+ if (verb)
+ text << "disfigured " << p->name;
+ }
+
+ if (disfigure_only)
+ return 0;
+
+ // Purge.
+ //
+ for (const drop_package& dp: pkgs)
+ {
+ // Skip prerequisites if we weren't instructed to drop them.
+ //
+ if (dp.reason == drop_reason::prerequisite && !drop_prq)
+ continue;
+
+ const shared_ptr<selected_package>& p (dp.package);
+
+ assert (p->state == package_state::fetched ||
+ p->state == package_state::unpacked);
+
+ transaction t (db.begin ());
+ pkg_purge (c, t, p); // Commits the transaction, p is now transient.
+
+ if (verb)
+ text << "purged " << p->name;
+ }
+
+ return 0;
+ }
+
int
pkg_drop (const pkg_drop_options& o, cli::scanner& args)
{
@@ -421,87 +518,86 @@ namespace bpkg
t.commit ();
}
- // Print what we are going to do, then ask for the user's confirmation.
- //
- if (o.print_only () || !(o.yes () || o.no ()))
- {
- for (const drop_package& dp: pkgs)
- {
- // Skip prerequisites if we weren't instructed to drop them.
- //
- if (dp.reason == drop_reason::prerequisite && !drop_prq)
- continue;
-
- const shared_ptr<selected_package>& p (dp.package);
-
- if (o.print_only ())
- cout << "drop " << p->name << endl;
- else if (verb)
- text << "drop " << p->name;
- }
-
- if (o.print_only ())
- return 0;
- }
+ return pkg_drop (c,
+ o,
+ db,
+ pkgs,
+ drop_prq,
+ o.print_only (),
+ o.disfigure_only (),
+ o.yes (),
+ o.no ());
+ }
- // Ask the user if we should continue.
- //
- if (o.no () || !(o.yes () || yn_prompt ("continue? [Y/n]", 'y')))
- return 1;
+ // Examine the list of prerequsite packages and drop those that don't
+ // have any dependents.
+ //
+ void
+ pkg_drop (const dir_path& c,
+ const common_options& o,
+ database& db,
+ const set<shared_ptr<selected_package>>& prqs,
+ bool prompt)
+ {
+ assert (session::has_current ());
- // All that's left to do is first disfigure configured packages and
- // then purge all of them. We do both left to right (i.e., from more
- // dependent to less dependent). For disfigure this order is required.
- // For purge, it will be the order closest to the one specified by the
- // user.
+ // Assemble the list of packages we will be dropping.
//
- for (const drop_package& dp: pkgs)
+ drop_packages pkgs;
{
- // Skip prerequisites if we weren't instructed to drop them.
+ transaction t (db.begin ());
+
+ // First add all the "caller selection" of packages to the list and
+ // collect their prerequisites (these will be the candidates to drop
+ // as well).
//
- if (dp.reason == drop_reason::prerequisite && !drop_prq)
- continue;
+ for (const shared_ptr<selected_package>& p: prqs)
+ {
+ assert (p->state != package_state::broken);
- const shared_ptr<selected_package>& p (dp.package);
+ if (pkgs.collect (p, drop_reason::prerequisite))
+ pkgs.collect_prerequisites (db, p);
+ }
- if (p->state != package_state::configured)
- continue;
+ // Now arrange them (and their prerequisites) in the dependency order.
+ //
+ for (const shared_ptr<selected_package>& p: prqs)
+ pkgs.order (p->name);
- // Each package is disfigured in its own transaction, so that we
- // always leave the configuration in a valid state.
+ // Finally filter out those that we cannot drop.
//
- transaction t (db.begin ());
- pkg_disfigure (c, o, t, p); // Commits the transaction.
- assert (p->state == package_state::unpacked);
+ bool r (pkgs.filter_prerequisites (db));
- if (verb)
- text << "disfigured " << p->name;
- }
+ t.commit ();
- if (o.disfigure_only ())
- return 0;
+ if (!r)
+ return; // Nothing can be dropped.
+ }
- // Purge.
- //
- for (const drop_package& dp: pkgs)
+ if (prompt)
{
- // Skip prerequisites if we weren't instructed to drop them.
- //
- if (dp.reason == drop_reason::prerequisite && !drop_prq)
- continue;
-
- const shared_ptr<selected_package>& p (dp.package);
+ {
+ diag_record dr (text);
- assert (p->state == package_state::fetched ||
- p->state == package_state::unpacked);
+ dr << "following prerequisite packages were automatically "
+ << "built and will no longer be necessary:";
- transaction t (db.begin ());
- pkg_purge (c, t, p); // Commits the transaction, p is now transient.
+ for (const drop_package& dp: pkgs)
+ dr << text << dp.package->name;
+ }
- if (verb)
- text << "purged " << p->name;
+ if (!yn_prompt ("drop prerequisite packages? [Y/n]", 'y'))
+ return;
}
- return 0;
+ pkg_drop (c,
+ o,
+ db,
+ pkgs,
+ true, // Drop prerequisites (that's what we are here for).
+ false, // Print-only (too late for that).
+ false, // Disfigure-only (could be an option).
+ true, // Yes (don't print the plan or prompt).
+ false); // No (we already said yes).
}
}