aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bpkg/build-options.cli6
-rw-r--r--bpkg/build.cxx87
-rw-r--r--bpkg/package10
-rw-r--r--bpkg/package.xml2
-rw-r--r--bpkg/pkg-fetch.cxx2
-rw-r--r--bpkg/pkg-status.cxx6
-rw-r--r--bpkg/pkg-unpack.cxx2
-rwxr-xr-xtests/test.sh51
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 (<file>) or package source directory (<dir>). 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 (<ver>) 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_package> available; // Can be NULL, fake/transient.
shared_ptr<bpkg::repository> 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<selected_package>& 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 @@
<column name="version_revision" type="INTEGER" null="true"/>
<column name="version_upstream" type="TEXT" null="true"/>
<column name="state" type="TEXT" null="true"/>
+ <column name="hold_package" type="INTEGER" null="true"/>
+ <column name="hold_version" type="INTEGER" null="true"/>
<column name="repository" type="TEXT" null="true"/>
<column name="archive" type="TEXT" null="true"/>
<column name="purge_archive" type="INTEGER" null="true"/>
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 <<EOF
build libfoo 1.0.0
build libbaz 1.1.0
EOF
+
+# hold
+#
+test cfg-create --wipe
+test build -y repository/1/satisfy/libfoo-1.0.0.tar.gz
+stat libfoo "configured 1.0.0 hold_package hold_version"
+test build -y repository/1/satisfy/libfoo-1.1.0
+stat libfoo "configured 1.1.0 hold_package hold_version"
+
+test cfg-create --wipe
+test rep-add $rep/satisfy/t4c
+test rep-fetch
+test build -y libfoo
+stat libfoo "configured 1.0.0 hold_package"
+test build -y libfoo/1.0.0
+stat libfoo "configured 1.0.0 hold_package hold_version"
+
+test cfg-create --wipe
+test rep-add $rep/satisfy/t4c
+test rep-fetch
+test build -y libfoo/1.0.0
+stat libfoo "configured 1.0.0 hold_package hold_version"
+
+test cfg-create --wipe
+test pkg-fetch -e repository/1/satisfy/libfoo-1.0.0.tar.gz
+test pkg-unpack libfoo
+test pkg-configure libfoo
+stat libfoo "configured 1.0.0"
+test build -y libfoo
+stat libfoo "configured 1.0.0 hold_package"
+
+test cfg-create --wipe
+test rep-add $rep/satisfy/t4c
+test rep-fetch
+test build -y libfoo
+stat libfoo "configured 1.0.0 hold_package"
+test build -y libbaz
+stat libfoo "configured 1.1.0 hold_package"
+
+test cfg-create --wipe
+test rep-add $rep/satisfy/t4c
+test rep-fetch
+test build -y libfoo/1.0.0
+stat libfoo "configured 1.0.0 hold_package hold_version"
+fail build -y libbaz
+
+test cfg-create --wipe
+test rep-add $rep/satisfy/t4c
+test rep-fetch
+test build -y libbaz
+stat libfoo "configured 1.1.0"