From 31421516334f8e41a04c75a1fed86b4cecd11526 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 18 Jun 2016 20:44:17 +0200 Subject: Offer to update dependents in pkg-build, add options to pkg-{build,drop} --- bpkg/pkg-build.cli | 39 +++++++++++++++++++++++------- bpkg/pkg-build.cxx | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++---- bpkg/pkg-drop | 5 ++-- bpkg/pkg-drop.cli | 21 ++++++++++++++-- bpkg/pkg-drop.cxx | 41 ++++++++++++++++++++++++-------- 5 files changed, 150 insertions(+), 26 deletions(-) (limited to 'bpkg') diff --git a/bpkg/pkg-build.cli b/bpkg/pkg-build.cli index 9de38f2..e0ec9b1 100644 --- a/bpkg/pkg-build.cli +++ b/bpkg/pkg-build.cli @@ -20,11 +20,16 @@ namespace bpkg \h|DESCRIPTION| The \cb{pkg-build} command builds one or more packages including all their - prerequisites. Each package can be specified as just the name () with - optional package version () in which case the package will be - automatically fetched from one of the repositories. See the - \l{bpkg-cfg-add(1)} and \l{bpkg-cfg-fetch(1)} commands for more - information on package repositories. + prerequisites. Besides building new packages, this command is also used to + upgrade or downgrade packages that already exists in the configuration. + + Each package can be specified as just the name () with optional + package version () in which case the package will be automatically + fetched from one of the repositories. See the \l{bpkg-cfg-add(1)} and + \l{bpkg-cfg-fetch(1)} commands for more information on package + repositories. If is not specified, then the latest available + version will be built. To downgrade, the desired version must be + specified explicitly. Alternatively, the package can be specified as either the path to the package archive () or to the package directory (/; note that @@ -39,8 +44,8 @@ namespace bpkg addition, have their versions held, that is, they will not be automatically upgraded. - The \cb{pkg-build} command also supports several \cb{--*-only} options - that allow you to limit the amount of work that will be done." + The \cb{pkg-build} command also supports several options (described + below) that allow you to control the amount of work that will be done." } class pkg_build_options: configuration_options @@ -52,12 +57,30 @@ namespace bpkg "Assume the answer to all prompts is \cb{yes}." } - bool --keep-prerequisite + bool --drop-prerequisite|-D + { + "Drop without confirmation prerequsite packages that were automatically + built and will no longer be necessary." + } + + bool --keep-prerequisite|-K { "Don't offer to drop prerequsite packages that were automatically built and will no longer be necessary." } + bool --update-dependent|-U + { + "Update without confirmation dependent packages that are reconfigured + due to their prerequisites being upgraded or downgraded." + } + + bool --leave-dependent|-L + { + "Don't offer to update dependent packages that are reconfigured due to + their prerequisites being upgraded or downgraded." + } + bool --print-only|-p { "Print to \cb{STDOUT} what would be done without actually doing diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index 9dc58c4..efb708b 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -807,6 +807,16 @@ namespace bpkg const dir_path& c (o.directory ()); l4 ([&]{trace << "configuration: " << c;}); + if (o.drop_prerequisite () && o.keep_prerequisite ()) + fail << "both --drop-prerequisite|-D and --keep-prerequisite|-K " + << "specified" << + info << "run 'bpkg help pkg-build' for more information"; + + if (o.update_dependent () && o.leave_dependent ()) + fail << "both --update-dependent|-U and --leave-dependent|-L " + << "specified" << + info << "run 'bpkg help pkg-build' for more information"; + if (!args.more ()) fail << "package name argument expected" << info << "run 'bpkg help pkg-build' for more information"; @@ -1098,7 +1108,11 @@ namespace bpkg } // Print what we are going to do, then ask for the user's confirmation. + // While at it, detect if we have any dependents that the user may want to + // update. // + bool update_dependents (false); + if (o.print_only () || !o.yes ()) { for (const build_package& p: reverse_iterate (pkgs)) @@ -1107,12 +1121,15 @@ namespace bpkg const shared_ptr& ap (p.available); string act; + string cause; if (ap == nullptr) { // This is a dependent needing reconfiguration. // assert (sp != nullptr && p.reconfigure ()); + update_dependents = true; act = "reconfigure " + sp->name; + cause = "dependent of"; } else { @@ -1139,6 +1156,7 @@ namespace bpkg act = sp->version < ap->version ? "upgrade " : "downgrade "; act += ap->id.name + ' ' + ap->version.string (); + cause = "required by"; } string rb; @@ -1149,7 +1167,7 @@ namespace bpkg } if (!rb.empty ()) - act += " (required by" + rb + ')'; + act += " (" + cause + rb + ')'; if (o.print_only ()) cout << act << endl; @@ -1166,6 +1184,15 @@ namespace bpkg if (!(o.yes () || yn_prompt ("continue? [Y/n]", 'y'))) return 1; + // Figure out if we also should update dependents. + // + if (o.leave_dependent ()) + update_dependents = false; + else if (o.yes () || o.update_dependent ()) + update_dependents = true; + else if (update_dependents) // Don't prompt if there aren't any. + update_dependents = yn_prompt ("update dependent packages? [Y/n]", 'y'); + // Ok, we have "all systems go". The overall action plan is as follows. // // 1. disfigure up/down-graded, reconfigured [left to right] @@ -1197,6 +1224,11 @@ namespace bpkg // established, we will pass them to pkg_drop() whose job will be to // figure out which ones can be dropped, prompt the user, etc. // + // We also have the other side of this logic: dependent packages that we + // reconfigure because their prerequsites got upgraded/downgraded and that + // the user may want to in addition update (that update_dependents flag + // above). This case we handle in house. + // set> drop_pkgs; // disfigure @@ -1362,6 +1394,15 @@ namespace bpkg db.update (sp); t.commit (); + // Clean up if this package ended up in the potention drop set. + // + if (hp) + { + auto i (drop_pkgs.find (sp)); + if (i != drop_pkgs.end ()) + drop_pkgs.erase (i); + } + if (verb > 1) { if (hp) @@ -1377,7 +1418,8 @@ namespace bpkg // packages that are no longer necessary. // if (!drop_pkgs.empty ()) - pkg_drop (c, o, db, drop_pkgs, !o.yes ()); + drop_pkgs = pkg_drop ( + c, o, db, drop_pkgs, !(o.yes () || o.drop_prerequisite ())); if (o.configure_only ()) return 0; @@ -1389,16 +1431,36 @@ namespace bpkg // vector upkgs; + // First add the user selection. + // for (const build_package& p: reverse_iterate (pkgs)) { const shared_ptr& sp (p.selected); - // Update the user selection only. - // if (find (names.begin (), names.end (), sp->name) != names.end ()) upkgs.push_back (pkg_command_vars {sp, strings ()}); } + // Then add dependents. We do it as a separate step so that they are + // updated after the user selection. + // + if (update_dependents) + { + for (const build_package& p: reverse_iterate (pkgs)) + { + const shared_ptr& sp (p.selected); + + if (p.reconfigure () && p.available == nullptr) + { + // Note that it is entirely possible this package got dropped so + // we need to check for that. + // + if (drop_pkgs.find (sp) == drop_pkgs.end ()) + upkgs.push_back (pkg_command_vars {sp, strings ()}); + } + } + } + pkg_update (c, o, strings (), upkgs); if (verb) diff --git a/bpkg/pkg-drop b/bpkg/pkg-drop index 4b7931e..23974af 100644 --- a/bpkg/pkg-drop +++ b/bpkg/pkg-drop @@ -19,9 +19,10 @@ namespace bpkg pkg_drop (const pkg_drop_options&, cli::scanner& args); // Examine the list of prerequisite packages and drop those that don't - // have any dependents. Note that it should be called in session. + // have any dependents. Return the set of packages that were actually + // dropped. Note that it should be called in session. // - void + std::set> pkg_drop (const dir_path& configuration, const common_options&, database&, diff --git a/bpkg/pkg-drop.cli b/bpkg/pkg-drop.cli index 7737d15..49d4f98 100644 --- a/bpkg/pkg-drop.cli +++ b/bpkg/pkg-drop.cli @@ -26,8 +26,8 @@ namespace bpkg packages that would otherwise no longer be needed, you will be offered to drop those as well. - The \cb{pkg-drop} command also supports several \cb{--*-only} options that - allow you to limit the amount of work that will be done." + The \cb{pkg-drop} command also supports several options (described below) + that allow you to control the amount of work that will be done." } class pkg_drop_options: configuration_options @@ -53,6 +53,23 @@ namespace bpkg packages." } + bool --keep-dependent|-K + { + "Issue an error if attempting to drop dependent packages." + } + + bool --drop-prerequisite|-D + { + "Drop without confirmation prerequsite packages that were automatically + built and will no longer be necessary." + } + + bool --keep-prerequisite + { + "Don't offer to drop prerequsite packages that were automatically built + and will no longer be necessary." + } + bool --print-only|-p { "Print to \cb{STDOUT} what would be done without actually doing diff --git a/bpkg/pkg-drop.cxx b/bpkg/pkg-drop.cxx index 07717ed..79a4870 100644 --- a/bpkg/pkg-drop.cxx +++ b/bpkg/pkg-drop.cxx @@ -390,11 +390,21 @@ namespace bpkg { tracer trace ("pkg_drop"); + const dir_path& c (o.directory ()); + l4 ([&]{trace << "configuration: " << c;}); + if (o.yes () && o.no ()) fail << "both --yes|-y and --no|-n specified"; - const dir_path& c (o.directory ()); - l4 ([&]{trace << "configuration: " << c;}); + 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.drop_prerequisite () && o.keep_prerequisite ()) + fail << "both --drop-prerequisite|-D and --keep-prerequisite " + << "specified" << + info << "run 'bpkg help pkg-drop' for more information"; if (!args.more ()) fail << "package name argument expected" << @@ -447,7 +457,12 @@ namespace bpkg if (!dnames.empty () && !o.drop_dependent ()) { { - diag_record dr (text); + diag_record dr; + + if (o.keep_dependent ()) + dr << fail; + else + dr << text; dr << "following dependent packages will have to be dropped " << "as well:"; @@ -497,7 +512,10 @@ namespace bpkg // have dependents other than the ones we are dropping). If there are // some that we can drop, ask the user for confirmation. // - if (pkgs.filter_prerequisites (db) && !(drop_prq = o.yes ()) && !o.no ()) + if (pkgs.filter_prerequisites (db) && + !o.keep_prerequisite () && + !(drop_prq = o.drop_prerequisite ()) && + !(drop_prq = o.yes ()) && !o.no ()) { { diag_record dr (text); @@ -529,10 +547,7 @@ namespace bpkg o.no ()); } - // Examine the list of prerequsite packages and drop those that don't - // have any dependents. - // - void + set> pkg_drop (const dir_path& c, const common_options& o, database& db, @@ -571,7 +586,7 @@ namespace bpkg t.commit (); if (!r) - return; // Nothing can be dropped. + return {}; // Nothing can be dropped. } if (prompt) @@ -587,7 +602,7 @@ namespace bpkg } if (!yn_prompt ("drop prerequisite packages? [Y/n]", 'y')) - return; + return {}; } pkg_drop (c, @@ -599,5 +614,11 @@ namespace bpkg false, // Disfigure-only (could be an option). true, // Yes (don't print the plan or prompt). false); // No (we already said yes). + + set> r; + for (const drop_package& dp: pkgs) + r.insert (dp.package); + + return r; } } -- cgit v1.1