From f95f24412ea85149556b34abb91f06e247d6db6d Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 19 Jun 2023 18:45:26 +0300 Subject: Fix deinit command to try bpkg-pkg-build --deorphan if bpkg-pkg drop fails --- bdep/deinit.cli | 6 +++ bdep/deinit.cxx | 50 ++++++++++++++----- bdep/sync.cxx | 148 ++++++++++++++++++++++++++++++++++++++++++++------------ bdep/sync.hxx | 13 +++++ 4 files changed, 174 insertions(+), 43 deletions(-) (limited to 'bdep') diff --git a/bdep/deinit.cli b/bdep/deinit.cli index e78cdbe..3ec0e72 100644 --- a/bdep/deinit.cli +++ b/bdep/deinit.cli @@ -47,6 +47,12 @@ namespace bdep configuration. This mode is primarily useful when the configuration directory has been removed or is otherwise unusable." } + + bool --no-fetch + { + "Do not re-fetch the repository information before attempting to replace + packages being deinitialized with versions from repositories." + } }; " diff --git a/bdep/deinit.cxx b/bdep/deinit.cxx index 45fab57..30152a4 100644 --- a/bdep/deinit.cxx +++ b/bdep/deinit.cxx @@ -8,7 +8,8 @@ #include #include -#include // configuration_projects(), hook_file +#include +#include using namespace std; @@ -77,19 +78,44 @@ namespace bdep } } - // Note that --keep-dependent is important: if we drop dependent packages - // that are managed by bdep, then its view of what has been initialized - // in the configuration will become invalid. + // Try to drop the packages watching out for their potential dependents. + // If there are any dependents, then sync in the deinit mode. This way we + // handle the plausible scenario when a dependency is pushed/submitted to + // a git/pkg repository after being developed and now we switch (back) to + // tracking it from that repository. // if (!force) - run_bpkg (2, - o, - "drop", - "-d", cfg, - "--keep-dependent", - "--plan", "synchronizing:", - "--yes", - pkgs); + { + process pr (start_bpkg (2, + o, + 1 /* stdout */, + 2 /* stderr */, + "drop", + "-d", cfg, + "--dependent-exit", 125, + "--plan", "synchronizing:", + "--yes", + pkgs)); + + if (pr.wait ()) + return; + + const process_exit& e (*pr.exit); + if (e.normal ()) + { + if (e.code () != 125) + throw failed (); // Assume the child issued diagnostics. + + // Fall through. + } + else + fail << "process " << name_bpkg (o) << " " << e; + + if (!o.no_fetch ()) + cmd_fetch (o, prj, c, true /* fetch_full */); + + cmd_sync_deinit (o, prj, c, pkgs); + } } int diff --git a/bdep/sync.cxx b/bdep/sync.cxx index 0cda5af..602c9aa 100644 --- a/bdep/sync.cxx +++ b/bdep/sync.cxx @@ -820,6 +820,8 @@ namespace bdep // If upgrade is not nullopt, then: If there are dep_pkgs, then we are // upgrading specific dependency packages. Otherwise -- project packages. // + // If deinit_pkgs is not empty, then sync in the deinit mode. + // // Note that if origin_prj is not empty, then origin_cfgs are specified as // configurations (as opposed to paths). Also upgrade can only be specified // with origin_prj. @@ -847,6 +849,7 @@ namespace bdep bool disfigure, const package_locations& prj_pkgs, const strings& dep_pkgs, + const strings& deinit_pkgs, bool create_host_config, bool create_build2_config, transaction* origin_tr = nullptr, @@ -858,7 +861,11 @@ namespace bdep // bool origin (!origin_prj.empty ()); - assert (prj_pkgs.empty () || dep_pkgs.empty ()); // Can't have both. + // Cannot have more than one package list specified. + // + assert ((prj_pkgs.empty () ? 0 : 1) + + (dep_pkgs.empty () ? 0 : 1) + + (deinit_pkgs.empty () ? 0 : 1) <= 1); // If a transaction is specified, then it must be started on the origin // project's database (which therefore must be specified) and it must be @@ -1076,6 +1083,14 @@ namespace bdep for (const package_state& pkg: cfg->packages) { + // In the deinit mode skip the being deinitialized packages to add + // them to the command line differently (see below). + // + if (find (deinit_pkgs.begin (), deinit_pkgs.end (), pkg.name) != + deinit_pkgs.end () && + prj.path == origin_prj) + continue; + // Return true if this package is part of the list specified // explicitly or, if none are specified, init'ed in the origin // project. @@ -1525,6 +1540,42 @@ namespace bdep args.push_back (move (a)); } + // Add the being deinitialized packages. + // + if (!deinit_pkgs.empty ()) + { + assert (!origin_prj.empty ()); // Project the packages belong to. + + // Must contain the configuration where the packages are being + // deinitialized. + // + assert (origin_cfgs.size () == 1); + + string config_uuid ( + linked_cfgs.find (origin_cfgs.front ().path ())->uuid.string ()); + + args.push_back ("--mask-repository-uuid"); + args.push_back (config_uuid + '=' + repository_name (origin_prj)); + + args.push_back ("{"); + + if (multi_cfg) + args.push_back ("--config-uuid=" + config_uuid); + + args.push_back ("--deorphan"); + args.push_back ("--dependency"); + args.push_back ("}+"); + + if (deinit_pkgs.size () > 1) + args.push_back ("{"); + + for (const string& p: deinit_pkgs) + args.push_back (p); + + if (deinit_pkgs.size () > 1) + args.push_back ("}"); + } + // We do a separate fetch instead of letting pkg-build do it. This way we // get better control of the diagnostics (no "fetching ..." for the // project itself). We also make sure that if the user specifies a @@ -2105,11 +2156,12 @@ namespace bdep fetch, yes, name_cfg, - nullopt /* upgrade */, - nullopt /* recursive */, - false /* disfigure */, - package_locations () /* prj_pkgs */, - strings () /* dep_pkgs */, + nullopt /* upgrade */, + nullopt /* recursive */, + false /* disfigure */, + package_locations () /* prj_pkgs */, + strings () /* dep_pkgs */, + strings () /* deinit_pkgs */, create_host_config, create_build2_config, t, @@ -2180,11 +2232,12 @@ namespace bdep fetch, yes, name_cfg, - nullopt /* upgrade */, - nullopt /* recursive */, - false /* disfigure */, - package_locations () /* prj_pkgs */, - strings () /* dep_pkgs */, + nullopt /* upgrade */, + nullopt /* recursive */, + false /* disfigure */, + package_locations () /* prj_pkgs */, + strings () /* dep_pkgs */, + strings () /* deinit_pkgs */, create_host_config, create_build2_config, nullptr, @@ -2220,16 +2273,17 @@ namespace bdep dir_path () /* prj */, {sync_config (cfg)}, move (lcfgs), - strings () /* pkg_args */, - true /* implicit */, + strings () /* pkg_args */, + true /* implicit */, fetch, yes, name_cfg, - nullopt /* upgrade */, - nullopt /* recursive */, - false /* disfigure */, - package_locations () /* prj_pkgs */, - strings () /* dep_pkgs */, + nullopt /* upgrade */, + nullopt /* recursive */, + false /* disfigure */, + package_locations () /* prj_pkgs */, + strings () /* dep_pkgs */, + strings () /* deinit_pkgs */, create_host_config, create_build2_config); @@ -2286,21 +2340,50 @@ namespace bdep dir_path () /* prj */, move (ocfgs), move (lcfgs), - strings () /* pkg_args */, - true /* implicit */, + strings () /* pkg_args */, + true /* implicit */, fetch, yes, name_cfg, - nullopt /* upgrade */, - nullopt /* recursive */, - false /* disfigure */, - package_locations () /* prj_pkgs */, - strings () /* dep_pkgs */, + nullopt /* upgrade */, + nullopt /* recursive */, + false /* disfigure */, + package_locations () /* prj_pkgs */, + strings () /* dep_pkgs */, + strings () /* deinit_pkgs */, create_host_config, create_build2_config); } } + void + cmd_sync_deinit (const common_options& co, + const dir_path& prj, + const shared_ptr& cfg, + const strings& pkgs) + { + sync_configs ocfgs {cfg}; + linked_configs lcfgs (find_config_cluster (co, cfg->path)); + + cmd_sync (co, + prj, + move (ocfgs), + move (lcfgs), + strings () /* pkg_args */, + true /* implicit */, + true /* fetch */, + true /* yes */, + false /* name_cfg */, + nullopt /* upgrade */, + nullopt /* recursive */, + false /* disfigure */, + package_locations () /* prj_pkgs */, + strings () /* dep_pkgs */, + pkgs, + false /* create_host_config */, + false /* create_build2_config */); + } + int cmd_sync (cmd_sync_options&& o, cli::group_scanner& args) { @@ -2643,6 +2726,7 @@ namespace bdep o.disfigure (), package_locations () /* prj_pkgs */, dep_pkgs, + strings () /* deinit_pkgs */, o.create_host_config (), o.create_build2_config ()); } @@ -2665,6 +2749,7 @@ namespace bdep o.disfigure (), prj_pkgs, strings () /* dep_pkgs */, + strings () /* deinit_pkgs */, o.create_host_config (), o.create_build2_config ()); } @@ -2682,13 +2767,14 @@ namespace bdep pkg_args, o.implicit (), !fetch, - true /* yes */, - o.implicit () /* name_cfg */, - nullopt /* upgrade */, - nullopt /* recursive */, + true /* yes */, + o.implicit () /* name_cfg */, + nullopt /* upgrade */, + nullopt /* recursive */, o.disfigure (), - package_locations () /* prj_pkgs */, - strings () /* dep_pkgs */, + package_locations () /* prj_pkgs */, + strings () /* dep_pkgs */, + strings () /* deinit_pkgs */, o.create_host_config (), o.create_build2_config ()); } diff --git a/bdep/sync.hxx b/bdep/sync.hxx index b025e40..fdd6d0b 100644 --- a/bdep/sync.hxx +++ b/bdep/sync.hxx @@ -112,6 +112,19 @@ namespace bdep bool create_host_config = false, bool create_build2_config = false); + // As above but deinitialize the specified project packages in the specified + // configuration instead of upgrading them. + // + // Specifically, in bpkg terms, unhold and deorphan these packages in the + // specified configuration with their project directory repository being + // masked. + // + void + cmd_sync_deinit (const common_options&, + const dir_path& prj, + const shared_ptr&, + const strings& pkgs); + int cmd_sync (cmd_sync_options&&, cli::group_scanner& args); -- cgit v1.1