From 6fed384f9bdc86fa9bb13d87753d14a886f4f87e Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 21 Oct 2015 09:28:52 +0200 Subject: Add support for held packages, package versions --- bpkg/build-options.cli | 6 ++++ bpkg/build.cxx | 87 ++++++++++++++++++++++++++++++++++++++++++++------ bpkg/package | 10 ++++++ bpkg/package.xml | 2 ++ bpkg/pkg-fetch.cxx | 2 ++ bpkg/pkg-status.cxx | 6 ++++ bpkg/pkg-unpack.cxx | 2 ++ tests/test.sh | 51 +++++++++++++++++++++++++++++ 8 files changed, 156 insertions(+), 10 deletions(-) diff --git a/bpkg/build-options.cli b/bpkg/build-options.cli index f2c9e23..b03f1ee 100644 --- a/bpkg/build-options.cli +++ b/bpkg/build-options.cli @@ -24,6 +24,12 @@ source archive () or package source directory (). See \cb{pkg-fetch} and \cb{pkg-unpack} for more information on the semantics of specifying the package as an archive or directory. +Packages that are specified explicitly on the command line will be \i{held}, +that is, they will not be considered for automatic removal if they no longer +have any dependents. Packages that are specified with the explicit package +version () as well as an archive or directory, will, in addition, have +their versions \i{held}, that is, they will not be automatically upgraded. + The \cb{build} command also supports several \cb{--*-only} options that allow you to limit the amount of work that will be done. */ diff --git a/bpkg/build.cxx b/bpkg/build.cxx index 07d1cf0..a6c966a 100644 --- a/bpkg/build.cxx +++ b/bpkg/build.cxx @@ -160,6 +160,12 @@ namespace bpkg shared_ptr available; // Can be NULL, fake/transient. shared_ptr repository; // Can be NULL (orphan) or root. + // Hold flags. Note that we can only "increase" the values that are + // already in the selected package. + // + bool hold_package; + bool hold_version; + // Constraint value plus, normally, the dependent package name that // placed this constraint but can also be some other name for the // initial selection (e.g., package version specified by the user @@ -460,7 +466,14 @@ namespace bpkg force = true; } - satisfied_package dp {dsp, rp.first, rp.second, {}, false}; + satisfied_package dp { + dsp, + rp.first, + rp.second, + false, // Hold package. + false, // Hold version. + {}, // Constraints. + false}; // Reconfigure. // Add our constraint, if we have one. // @@ -468,9 +481,9 @@ namespace bpkg dp.constraints.emplace_back (name, *d.constraint); // Now collect this prerequisite. If it was actually collected - // (i.e., it wasn't already there) and we are forcing an upgrade, - // then warn, unless we are running quiet. Downgrade -- outright - // refuse. + // (i.e., it wasn't already there) and we are forcing an upgrade + // and the version is not held, then warn, unless we are running + // quiet. Downgrade or upgrade of a held version -- refuse. // if (collect (options, cd, db, move (dp)) && force) { @@ -478,20 +491,26 @@ namespace bpkg const version& av (rp.first->version); bool u (av > sv); + bool f (dsp->hold_version || !u); // Fail if downgrade or held. - if (verb || !u) + if (verb || f) { bool c (d.constraint); diag_record dr; - (u ? dr << warn : dr << fail) + (f ? dr << fail : dr << warn) << "package " << name << " dependency on " << (c ? "(" : "") << d << (c ? ")" : "") << " is forcing " << (u ? "up" : "down") << "grade of " << d.name << " " << sv << " to " << av; - if (!u) - dr << info << "explicitly specify version downgrade to continue"; + if (dsp->hold_version) + dr << info << "package version " << d.name << " " << sv + << " is held"; + + if (f) + dr << info << "explicitly request version " + << (u ? "up" : "down") << "grade to continue"; } } } @@ -680,7 +699,14 @@ namespace bpkg data_type { list_.end (), - satisfied_package {move (dsp), nullptr, nullptr, {}, true} + satisfied_package { + move (dsp), + nullptr, + nullptr, + false, // Hold package. + false, // Hold version. + {}, // Constraints. + true} // Reconfigure. }).first; i->second.position = list_.insert (pos, i->second.package); @@ -921,7 +947,14 @@ namespace bpkg level4 ([&]{trace << "collect " << ap->id.name << " " << ap->version;}); - satisfied_package p {move (sp), move (ap), move (ar), {}, false}; + satisfied_package p { + move (sp), + move (ap), + move (ar), + true, // Hold package. + !v.empty (), // Hold version. + {}, // Constraints. + false}; // Reconfigure. // "Fix" the version the user asked for by adding the '==' constraint. // @@ -1144,6 +1177,40 @@ namespace bpkg text << "configured " << sp->name << " " << sp->version; } + // Small detour: update the hold state. While we could have tried + // to "weave" it into one of the previous actions, things there + // are already convoluted enough. + // + for (const satisfied_package& p: reverse_iterate (pkgs)) + { + const shared_ptr& sp (p.selected); + assert (sp != nullptr); + + // Note that we should only "increase" the hold state. + // + bool hp (p.hold_package && sp->hold_package != p.hold_package); + bool hv (p.hold_version && sp->hold_version != p.hold_version); + + if (hp || hv) + { + if (hp) sp->hold_package = true; + if (hv) sp->hold_version = true; + + transaction t (db.begin ()); + db.update (sp); + t.commit (); + + if (verb > 1) + { + if (hp) + text << "hold package " << sp->name; + + if (hv) + text << "hold version " << sp->name << " " << sp->version; + } + } + } + // update // if (!o.configure_only ()) diff --git a/bpkg/package b/bpkg/package index 12079f6..a17a860 100644 --- a/bpkg/package +++ b/bpkg/package @@ -348,6 +348,16 @@ namespace bpkg version_type version; package_state state; + // The hold flags indicate whether this package and/or version + // should be retained in the configuration. A held package will + // not be automatically removed. A held version will not be + // automatically upgraded. Note also that the two flags are + // orthogonal: we may want to keep a specific version of the + // package as long as it has dependents. + // + bool hold_package; + bool hold_version; + // Repository from which this package came. Note that it is not // a pointer to the repository object because it could be wiped // out (e.g., as a result of rep-fetch). We call such packages diff --git a/bpkg/package.xml b/bpkg/package.xml index 79d7ac7..9ac6a3a 100644 --- a/bpkg/package.xml +++ b/bpkg/package.xml @@ -159,6 +159,8 @@ + + diff --git a/bpkg/pkg-fetch.cxx b/bpkg/pkg-fetch.cxx index d2b0674..9a2e84c 100644 --- a/bpkg/pkg-fetch.cxx +++ b/bpkg/pkg-fetch.cxx @@ -73,6 +73,8 @@ namespace bpkg move (n), move (v), package_state::fetched, + false, // hold package + false, // hold version move (rl), move (a), purge, diff --git a/bpkg/pkg-status.cxx b/bpkg/pkg-status.cxx index 7894c49..2f0bf7f 100644 --- a/bpkg/pkg-status.cxx +++ b/bpkg/pkg-status.cxx @@ -100,6 +100,12 @@ namespace bpkg if (v.empty ()) cout << " " << p->version; + if (p->hold_package) + cout << " hold_package"; + + if (p->hold_version) + cout << " hold_version"; + found = true; } diff --git a/bpkg/pkg-unpack.cxx b/bpkg/pkg-unpack.cxx index d6613b5..c224350 100644 --- a/bpkg/pkg-unpack.cxx +++ b/bpkg/pkg-unpack.cxx @@ -97,6 +97,8 @@ namespace bpkg move (m.name), move (m.version), package_state::unpacked, + false, // hold package + false, // hold version repository_location (), // Root repository. nullopt, // No archive false, // Don't purge archive. diff --git a/tests/test.sh b/tests/test.sh index 08ba9d7..c6c8a79 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -1078,3 +1078,54 @@ test build -p libbaz libfoo/1.0.0 <