aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2019-08-30 17:56:26 (GMT)
committerKaren Arutyunov <karen@codesynthesis.com>2019-09-05 13:55:45 (GMT)
commit1ad6dad8da0d51e9522f9d27cf48531fa23b24ba (patch)
tree4f53f85678348e605d282bad20b327653faa0729
parent7b5a0b55569331560f9cb6439ee818c3ce5d8428 (diff)
Adapt to optional package revision
-rw-r--r--bpkg/database.cxx28
-rw-r--r--bpkg/manifest-utility.cxx6
-rw-r--r--bpkg/manifest-utility.hxx12
-rw-r--r--bpkg/package.cxx12
-rw-r--r--bpkg/package.hxx83
-rw-r--r--bpkg/package.ixx6
-rw-r--r--bpkg/package.xml2
-rw-r--r--bpkg/pkg-build.cxx72
-rw-r--r--bpkg/pkg-status.cxx18
-rw-r--r--bpkg/rep-fetch.cxx5
-rw-r--r--bpkg/satisfaction.cxx43
-rw-r--r--bpkg/satisfaction.test.cxx58
-rw-r--r--tests/common/satisfy/libbar-1.1.1.tar.gzbin0 -> 367 bytes
-rw-r--r--tests/common/satisfy/libfoo-1.1.0+1.tar.gzbin0 -> 353 bytes
l---------tests/common/satisfy/t4e/libbar-1.1.0.tar.gz1
l---------tests/common/satisfy/t4e/libbar-1.1.1.tar.gz1
l---------tests/common/satisfy/t4e/libfoo-1.1.0+1.tar.gz1
-rw-r--r--tests/common/satisfy/t4e/repositories.manifest4
-rw-r--r--tests/pkg-build.testscript64
l---------tests/pkg-build/t4e1
-rw-r--r--tests/pkg-status.testscript30
21 files changed, 360 insertions, 87 deletions
diff --git a/bpkg/database.cxx b/bpkg/database.cxx
index a66b3a3..68a2a34 100644
--- a/bpkg/database.cxx
+++ b/bpkg/database.cxx
@@ -42,15 +42,39 @@ namespace bpkg
// Register the data migration functions.
//
-#if 0
template <odb::schema_version v>
using migration_entry = odb::data_migration_entry<v, DB_SCHEMA_VERSION_BASE>;
static const migration_entry<6>
migrate_v6 ([] (odb::database& db)
{
+ // Set the zero version revision to NULL.
+ //
+ auto migrate_rev = [&db] (const char* table, const char* column)
+ {
+ db.execute (string ("UPDATE ") + table + " SET " + column + " = NULL " +
+ "WHERE " + column + " = 0");
+ };
+
+ // The version package manifest value. Note: is not part of a primary key.
+ //
+ migrate_rev ("selected_package", "version_revision");
+
+ // The depends package manifest value endpoint versions.
+ //
+ // Note that previously the zero and absent revisions had the same
+ // semantics. Now the semantics differs and the zero revision is preserved
+ // (see libbpkg/manifest.hxx for details).
+ //
+ migrate_rev ("selected_package_prerequisites", "min_version_revision");
+ migrate_rev ("selected_package_prerequisites", "max_version_revision");
+
+ migrate_rev ("available_package_dependency_alternatives",
+ "dep_min_version_revision");
+
+ migrate_rev ("available_package_dependency_alternatives",
+ "dep_max_version_revision");
});
-#endif
database
open (const dir_path& d, tracer& tr, bool create)
diff --git a/bpkg/manifest-utility.cxx b/bpkg/manifest-utility.cxx
index 74daf6b..bf4956b 100644
--- a/bpkg/manifest-utility.cxx
+++ b/bpkg/manifest-utility.cxx
@@ -68,7 +68,9 @@ namespace bpkg
}
version
- parse_package_version (const char* s, bool allow_wildcard)
+ parse_package_version (const char* s,
+ bool allow_wildcard,
+ bool fold_zero_revision)
{
using traits = string::traits_type;
@@ -82,7 +84,7 @@ namespace bpkg
try
{
- version r (p);
+ version r (p, fold_zero_revision);
if (r.release && r.release->empty ())
throw invalid_argument ("earliest version");
diff --git a/bpkg/manifest-utility.hxx b/bpkg/manifest-utility.hxx
index 6c88f1f..9f690b4 100644
--- a/bpkg/manifest-utility.hxx
+++ b/bpkg/manifest-utility.hxx
@@ -47,12 +47,18 @@ namespace bpkg
// Return empty version if none is specified.
//
version
- parse_package_version (const char*, bool allow_wildcard = false);
+ parse_package_version (const char*,
+ bool allow_wildcard = false,
+ bool fold_zero_revision = true);
inline version
- parse_package_version (const string& s, bool allow_wildcard = false)
+ parse_package_version (const string& s,
+ bool allow_wildcard = false,
+ bool fold_zero_revision = true)
{
- return parse_package_version (s.c_str (), allow_wildcard);
+ return parse_package_version (s.c_str (),
+ allow_wildcard,
+ fold_zero_revision);
}
// If the passed location is a relative local path, then assume this is a
diff --git a/bpkg/package.cxx b/bpkg/package.cxx
index 0ac2577..563fc93 100644
--- a/bpkg/package.cxx
+++ b/bpkg/package.cxx
@@ -16,7 +16,7 @@ using namespace std;
namespace bpkg
{
- const version wildcard_version (0, "0", nullopt, 0, 0);
+ const version wildcard_version (0, "0", nullopt, nullopt, 0);
// available_package_id
//
@@ -290,7 +290,10 @@ namespace bpkg
query q (
query::package::id.name == n &&
- compare_version_eq (query::package::id.version, v, true, false));
+ compare_version_eq (query::package::id.version,
+ canonical_version (v),
+ true /* revision */,
+ false /* iteration */));
for (const auto& prf: db.query<package_repository_fragment> (q))
{
@@ -306,7 +309,10 @@ namespace bpkg
shared_ptr<selected_package> p (db.find<selected_package> (n));
if (p == nullptr || !p->src_root ||
- compare_version_ne (v, p->version, true, false))
+ compare_version_ne (v,
+ p->version,
+ true /* revision */,
+ false /* iteration */))
return nullopt;
string mc (sha256 (o, d / manifest_file));
diff --git a/bpkg/package.hxx b/bpkg/package.hxx
index 74021c7..4f40939 100644
--- a/bpkg/package.hxx
+++ b/bpkg/package.hxx
@@ -28,7 +28,7 @@
//
#define DB_SCHEMA_VERSION_BASE 5
-#pragma db model version(DB_SCHEMA_VERSION_BASE, 5, closed)
+#pragma db model version(DB_SCHEMA_VERSION_BASE, 6, closed)
namespace bpkg
{
@@ -102,7 +102,7 @@ namespace bpkg
uint16_t epoch;
string canonical_upstream;
string canonical_release;
- uint16_t revision;
+ optional<uint16_t> revision;
uint32_t iteration;
string upstream;
optional<string> release;
@@ -112,10 +112,12 @@ namespace bpkg
_version () = default;
_version (uint16_t e,
string cu, string cr,
- uint16_t rv, uint32_t i, string u, optional<string> rl)
+ optional<uint16_t> rv, uint32_t i,
+ string u, optional<string> rl)
: epoch (e),
- canonical_upstream (cu), canonical_release (cr),
- revision (rv), iteration (i), upstream (u), release (rl) {}
+ canonical_upstream (move (cu)), canonical_release (move (cr)),
+ revision (rv), iteration (i),
+ upstream (move (u)), release (move (rl)) {}
};
}
@@ -147,6 +149,11 @@ namespace bpkg
// strange contraption is for. See available_package for an example
// on how everything fits together.
//
+ // Note that the object id cannot contain an optional member which is why we
+ // make the revision type uint16_t and represent nullopt as zero. This
+ // should be ok for package object ids referencing the package manifest
+ // version values because an absent revision and zero revision mean the
+ // same thing.
//
#pragma db value
struct canonical_version
@@ -157,6 +164,16 @@ namespace bpkg
uint16_t revision;
uint32_t iteration;
+ canonical_version () = default;
+
+ explicit
+ canonical_version (const version& v)
+ : epoch (v.epoch),
+ canonical_upstream (v.canonical_upstream),
+ canonical_release (v.canonical_release),
+ revision (v.effective_revision ()),
+ iteration (v.iteration) {}
+
// By default SQLite3 uses BINARY collation for TEXT columns. So while this
// means we don't need to do anything special to make "absent" (~) and
// specified canonical releases compare properly, better make it explicit
@@ -169,14 +186,15 @@ namespace bpkg
#pragma db value transient
struct upstream_version: version
{
- #pragma db member(upstream_) virtual(string) \
- get(this.upstream) \
- set(this = bpkg::version (0, std::move (?), std::string (), 0, 0))
+ #pragma db member(upstream_) virtual(string) \
+ get(this.upstream) \
+ set(this = bpkg::version ( \
+ 0, std::move (?), std::string (), bpkg::nullopt, 0))
- #pragma db member(release_) virtual(optional_string) \
- get(this.release) \
- set(this = bpkg::version ( \
- 0, std::move (this.upstream), std::move (?), 0, 0))
+ #pragma db member(release_) virtual(optional_string) \
+ get(this.release) \
+ set(this = bpkg::version ( \
+ 0, std::move (this.upstream), std::move (?), bpkg::nullopt, 0))
upstream_version () = default;
upstream_version (version v): version (move (v)) {}
@@ -186,10 +204,14 @@ namespace bpkg
void
init (const canonical_version& cv, const upstream_version& uv)
{
+ // Note: revert the zero revision mapping (see above).
+ //
*this = version (cv.epoch,
uv.upstream,
uv.release,
- cv.revision,
+ (cv.revision != 0
+ ? optional<uint16_t> (cv.revision)
+ : nullopt),
cv.iteration);
assert (cv.canonical_upstream == canonical_upstream &&
@@ -1147,17 +1169,20 @@ namespace bpkg
//
// They allow comparing objects that have epoch, canonical_upstream,
// canonical_release, revision, and iteration data members. The idea is that
- // this works for both query members of types version and canonical_version
- // as well as for comparing canonical_version to version.
+ // this works for both query members of types version and canonical_version.
+ // Note, though, that the object revisions should be comparable (both
+ // optional, numeric, etc), so to compare version to query member or
+ // canonical_version you may need to explicitly convert the version object
+ // to canonical_version.
//
- // Note that if the comparison operation ignores the revision, then it also
- // unconditionally ignores the iteration (that semantically extends the
+ // Also note that if the comparison operation ignores the revision, then it
+ // also unconditionally ignores the iteration (that semantically extends the
// revision).
//
template <typename T1, typename T2>
inline auto
compare_version_eq (const T1& x, const T2& y, bool revision, bool iteration)
- -> decltype (x.epoch == y.epoch)
+ -> decltype (x.revision == y.revision)
{
assert (revision || !iteration); // !revision && iteration is meaningless.
@@ -1181,7 +1206,7 @@ namespace bpkg
template <typename T1, typename T2>
inline auto
- operator== (const T1& x, const T2& y) -> decltype (x.epoch == y.epoch)
+ operator== (const T1& x, const T2& y) -> decltype (x.revision == y.revision)
{
return compare_version_eq (x, y, true);
}
@@ -1190,7 +1215,7 @@ namespace bpkg
template <typename T1, typename T2>
inline auto
compare_version_ne (const T1& x, const T2& y, bool revision, bool iteration)
- -> decltype (x.epoch == y.epoch)
+ -> decltype (x.revision == y.revision)
{
assert (revision || !iteration); // !revision && iteration is meaningless.
@@ -1207,7 +1232,7 @@ namespace bpkg
template <typename T1, typename T2>
inline auto
- operator!= (const T1& x, const T2& y) -> decltype (x.epoch != y.epoch)
+ operator!= (const T1& x, const T2& y) -> decltype (x.revision != y.revision)
{
return compare_version_ne (x, y, true, true);
}
@@ -1215,7 +1240,7 @@ namespace bpkg
template <typename T1, typename T2>
inline auto
compare_version_lt (const T1& x, const T2& y, bool revision, bool iteration)
- -> decltype (x.epoch == y.epoch)
+ -> decltype (x.revision == y.revision)
{
assert (revision || !iteration); // !revision && iteration is meaningless.
@@ -1245,7 +1270,7 @@ namespace bpkg
template <typename T1, typename T2>
inline auto
- operator< (const T1& x, const T2& y) -> decltype (x.epoch < y.epoch)
+ operator< (const T1& x, const T2& y) -> decltype (x.revision < y.revision)
{
return compare_version_lt (x, y, true, true);
}
@@ -1253,7 +1278,7 @@ namespace bpkg
template <typename T1, typename T2>
inline auto
compare_version_le (const T1& x, const T2& y, bool revision, bool iteration)
- -> decltype (x.epoch == y.epoch)
+ -> decltype (x.revision == y.revision)
{
assert (revision || !iteration); // !revision && iteration is meaningless.
@@ -1301,7 +1326,7 @@ namespace bpkg
template <typename T1, typename T2>
inline auto
- operator<= (const T1& x, const T2& y) -> decltype (x.epoch <= y.epoch)
+ operator<= (const T1& x, const T2& y) -> decltype (x.revision <= y.revision)
{
return compare_version_le (x, y, true);
}
@@ -1310,7 +1335,7 @@ namespace bpkg
template <typename T1, typename T2>
inline auto
compare_version_gt (const T1& x, const T2& y, bool revision, bool iteration)
- -> decltype (x.epoch == y.epoch)
+ -> decltype (x.revision == y.revision)
{
assert (revision || !iteration); // !revision && iteration is meaningless.
@@ -1340,7 +1365,7 @@ namespace bpkg
template <typename T1, typename T2>
inline auto
- operator> (const T1& x, const T2& y) -> decltype (x.epoch > y.epoch)
+ operator> (const T1& x, const T2& y) -> decltype (x.revision > y.revision)
{
return compare_version_gt (x, y, true, true);
}
@@ -1348,7 +1373,7 @@ namespace bpkg
template <typename T1, typename T2>
inline auto
compare_version_ge (const T1& x, const T2& y, bool revision, bool iteration)
- -> decltype (x.epoch == y.epoch)
+ -> decltype (x.revision == y.revision)
{
assert (revision || !iteration); // !revision && iteration is meaningless.
@@ -1393,7 +1418,7 @@ namespace bpkg
template <typename T1, typename T2>
inline auto
- operator>= (const T1& x, const T2& y) -> decltype (x.epoch >= y.epoch)
+ operator>= (const T1& x, const T2& y) -> decltype (x.revision >= y.revision)
{
return compare_version_ge (x, y, true, true);
}
diff --git a/bpkg/package.ixx b/bpkg/package.ixx
index 9359294..f6aa6c4 100644
--- a/bpkg/package.ixx
+++ b/bpkg/package.ixx
@@ -9,11 +9,7 @@ namespace bpkg
inline available_package_id::
available_package_id (package_name n, const bpkg::version& v)
: name (move (n)),
- version {v.epoch,
- v.canonical_upstream,
- v.canonical_release,
- v.revision,
- v.iteration}
+ version (v)
{
}
}
diff --git a/bpkg/package.xml b/bpkg/package.xml
index 6c17f11..2856be1 100644
--- a/bpkg/package.xml
+++ b/bpkg/package.xml
@@ -1,4 +1,6 @@
<changelog xmlns="http://www.codesynthesis.com/xmlns/odb/changelog" database="sqlite" version="1">
+ <changeset version="6"/>
+
<model version="5">
<table name="repository_fragment" kind="object">
<column name="name" type="TEXT" null="true"/>
diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx
index 0844ae9..5a5eaa1 100644
--- a/bpkg/pkg-build.cxx
+++ b/bpkg/pkg-build.cxx
@@ -75,18 +75,14 @@ namespace bpkg
// satisfy this constraint. The same for libfoo <= 1 -- 1+1 should
// satisfy.
//
- // Note that strictly speaking 0 doesn't mean unspecified. Which means
- // with this implementation there is no way to say "I really mean
- // revision 0" since 1 == 1+0. One can, in the current model, say libfoo
- // == 1+1, though. This is probably ok since one would assume any
- // subsequent revision of a package version are just as (un)satisfactory
- // as the first one.
+ // Note that we always compare ignoring the iteration, as it can not be
+ // specified in the manifest/command line. This way the latest iteration
+ // will always be picked up.
//
- // Also note that we always compare ignoring the iteration, as it can
- // not be specified in the manifest/command line. This way the latest
- // iteration will always be picked up.
- //
- query qs (compare_version_eq (vm, wildcard_version, false, false));
+ query qs (compare_version_eq (vm,
+ canonical_version (wildcard_version),
+ false /* revision */,
+ false /* iteration */));
if (c->min_version &&
c->max_version &&
@@ -94,7 +90,12 @@ namespace bpkg
{
const version& v (*c->min_version);
- q = q && (compare_version_eq (vm, v, v.revision != 0, false) || qs);
+ q = q &&
+ (compare_version_eq (vm,
+ canonical_version (v),
+ v.revision.has_value (),
+ false /* iteration */) ||
+ qs);
}
else
{
@@ -103,21 +104,25 @@ namespace bpkg
if (c->min_version)
{
const version& v (*c->min_version);
+ canonical_version cv (v);
+ bool rv (v.revision);
if (c->min_open)
- qr = compare_version_gt (vm, v, v.revision != 0, false);
+ qr = compare_version_gt (vm, cv, rv, false /* iteration */);
else
- qr = compare_version_ge (vm, v, v.revision != 0, false);
+ qr = compare_version_ge (vm, cv, rv, false /* iteration */);
}
if (c->max_version)
{
const version& v (*c->max_version);
+ canonical_version cv (v);
+ bool rv (v.revision);
if (c->max_open)
- qr = qr && compare_version_lt (vm, v, v.revision != 0, false);
+ qr = qr && compare_version_lt (vm, cv, rv, false /* iteration */);
else
- qr = qr && compare_version_le (vm, v, v.revision != 0, false);
+ qr = qr && compare_version_le (vm, cv, rv, false /* iteration */);
}
q = q && (qr || qs);
@@ -2818,6 +2823,20 @@ namespace bpkg
transaction t (db);
+ // Don't fold the zero revision if building the package from source so
+ // that we build the exact X+0 package revision if it is specified.
+ //
+ auto fold_zero_rev = [] (package_scheme sc)
+ {
+ bool r (false);
+ switch (sc)
+ {
+ case package_scheme::none: r = false; break;
+ case package_scheme::sys: r = true; break;
+ }
+ return r;
+ };
+
for (pkg_spec& ps: specs)
{
if (ps.location.empty ())
@@ -2826,14 +2845,14 @@ namespace bpkg
// otherwise add unparsed.
//
const char* s (ps.packages.c_str ());
- package_scheme h (parse_package_scheme (s));
+ package_scheme sc (parse_package_scheme (s));
- if (h != package_scheme::none) // Add parsed.
+ if (sc != package_scheme::none) // Add parsed.
{
- bool sys (h == package_scheme::sys);
+ bool sys (sc == package_scheme::sys);
package_name n (parse_package_name (s));
- version v (parse_package_version (s, sys));
+ version v (parse_package_version (s, sys, fold_zero_rev (sc)));
// For system packages not associated with a specific repository
// location add the stub package to the imaginary system
@@ -2842,7 +2861,7 @@ namespace bpkg
if (sys && !v.empty ())
stubs.push_back (make_shared<available_package> (n));
- pkg_args.push_back (arg_package (h,
+ pkg_args.push_back (arg_package (sc,
move (n),
move (v),
move (ps.options),
@@ -2974,7 +2993,7 @@ namespace bpkg
bool sys (sc == package_scheme::sys);
package_name n (parse_package_name (s));
- version v (parse_package_version (s, sys));
+ version v (parse_package_version (s, sys, fold_zero_rev (sc)));
// Check if the package is present in the repository and its
// complements, recursively. If the version is not specified then
@@ -3311,7 +3330,14 @@ namespace bpkg
// prior to saving them into the package arg.
//
package_name n (parse_package_name (package));
- version v (parse_package_version (package));
+
+ // Don't fold the zero revision so that we build the exact X+0
+ // package revision, if it is specified.
+ //
+ version v (
+ parse_package_version (package,
+ false /* allow_wildcard */,
+ false /* fold_zero_revision */));
pa = arg_package (package_scheme::none,
move (n),
diff --git a/bpkg/pkg-status.cxx b/bpkg/pkg-status.cxx
index aaaedaf..bfba21f 100644
--- a/bpkg/pkg-status.cxx
+++ b/bpkg/pkg-status.cxx
@@ -86,9 +86,9 @@ namespace bpkg
//
if (!p.version.empty ())
q = q && compare_version_eq (query::id.version,
- p.version,
- p.version.revision != 0,
- false);
+ canonical_version (p.version),
+ p.version.revision.has_value (),
+ false /* iteration */);
// And if we found an existing package, then only look for versions
// greater than to what already exists unless we were asked to show
@@ -98,7 +98,7 @@ namespace bpkg
// available versions (since it is 0).
//
if (s != nullptr && !o.old_available ())
- q = q && query::id.version > s->version;
+ q = q && query::id.version > canonical_version (s->version);
q += order_by_version_desc (query::id.version);
@@ -281,7 +281,9 @@ namespace bpkg
{
const char* arg (args.next ());
package p {parse_package_name (arg),
- parse_package_version (arg),
+ parse_package_version (arg,
+ false /* allow_wildcard */,
+ false /* fold_zero_revision */),
nullptr /* selected */,
nullopt /* constraint */};
@@ -292,9 +294,9 @@ namespace bpkg
if (!p.version.empty ())
q = q && compare_version_eq (query::version,
- p.version,
- p.version.revision != 0,
- false);
+ canonical_version (p.version),
+ p.version.revision.has_value (),
+ false /* iteration */);
p.selected = db.query_one<selected_package> (q);
}
diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx
index 413358a..cafa0c1 100644
--- a/bpkg/rep-fetch.cxx
+++ b/bpkg/rep-fetch.cxx
@@ -1307,7 +1307,10 @@ namespace bpkg
const available_package_id& id (prf.package_id);
if (id.name == ap.name &&
- compare_version_eq (id.version, ap.version, true, false))
+ compare_version_eq (id.version,
+ ap.version,
+ true /* revision */,
+ false /* iteration */))
{
shared_ptr<available_package> p (db.load<available_package> (id));
const version& v (p->version);
diff --git a/bpkg/satisfaction.cxx b/bpkg/satisfaction.cxx
index faebce0..53fd3b8 100644
--- a/bpkg/satisfaction.cxx
+++ b/bpkg/satisfaction.cxx
@@ -24,18 +24,27 @@ namespace bpkg
bool s (true);
- // See notes in pkg-build:find_available() on ignoring revision in
+ // Here an absent revision means zero revision and version X must satisfy
+ // the [X+0 ...) dependency constraint. Note that technically X < X+0.
+ //
+ version ev (v.epoch,
+ v.upstream,
+ v.release,
+ v.effective_revision (),
+ v.iteration);
+
+ // See notes in pkg-build:query_available() on ignoring revision in
// comparison.
//
if (c.min_version)
{
- int i (v.compare (*c.min_version, c.min_version->revision == 0));
+ int i (ev.compare (*c.min_version, !c.min_version->revision));
s = c.min_open ? i > 0 : i >= 0;
}
if (s && c.max_version)
{
- int i (v.compare (*c.max_version, c.max_version->revision == 0));
+ int i (ev.compare (*c.max_version, !c.max_version->revision));
s = c.max_open ? i < 0 : i <= 0;
}
@@ -47,16 +56,33 @@ namespace bpkg
{
assert (!l.empty () && l.complete () && !r.empty () && r.complete ());
- // Note: the revision ignoring logic is still unclear/unimplemented. It
- // seems it will be specific to each case below.
+ // Note that a revision should not be ignored if we compare the endpoint
+ // versions. However, an absent revision translates into the effective
+ // revision differently, depending on the range endpoint side and openness
+ // (see libbpkg/manifest.hxx for details). That's why we normalize
+ // endpoint versions prior to comparison.
//
+ auto norm = [] (const version& v, bool min, bool open) -> version
+ {
+ return version (v.epoch,
+ v.upstream,
+ v.release,
+ v.revision ? v.revision :
+ (min && !open) || (!min && open) ? 0 :
+ uint16_t (~0),
+ v.iteration);
+ };
+
bool s (false);
if (l.min_version)
{
if (r.min_version)
{
- int i (l.min_version->compare (*r.min_version, false));
+ version lv (norm (*l.min_version, true /* min */, l.min_open));
+ version rv (norm (*r.min_version, true /* min */, r.min_open));
+
+ int i (lv.compare (rv, false /* ignore_revision */));
if (l.min_open)
// Doesn't matter if r is min_open or not.
//
@@ -76,7 +102,10 @@ namespace bpkg
{
if (r.max_version)
{
- int i (l.max_version->compare (*r.max_version, false));
+ version lv (norm (*l.max_version, false /* min */, l.max_open));
+ version rv (norm (*r.max_version, false /* min */, r.max_open));
+
+ int i (lv.compare (rv, false /* ignore_revision */));
if (l.max_open)
// Doesn't matter if r is max_open or not.
//
diff --git a/bpkg/satisfaction.test.cxx b/bpkg/satisfaction.test.cxx
new file mode 100644
index 0000000..fef30e1
--- /dev/null
+++ b/bpkg/satisfaction.test.cxx
@@ -0,0 +1,58 @@
+// file : bpkg/satisfaction.test.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <bpkg/satisfaction.hxx>
+
+namespace bpkg
+{
+ static int
+ main (int, char*[])
+ {
+ using dc = dependency_constraint;
+
+ assert ( satisfies (dc ("[1.0 2.0]"), dc ("[1.0+0 2.0]")));
+ assert (!satisfies (dc ("[1.0 2.0]"), dc ("[1.0+1 2.0]")));
+ assert ( satisfies (dc ("[1.0+0 2.0]"), dc ("[1.0 2.0]")));
+ assert ( satisfies (dc ("[1.0+1 2.0]"), dc ("[1.0 2.0]")));
+
+ assert (!satisfies (dc ("[1.0+0 2.0]"), dc ("(1.0 2.0]")));
+ assert (!satisfies (dc ("[1.0+1 2.0]"), dc ("(1.0 2.0]")));
+ assert (!satisfies (dc ("(1.0+0 2.0]"), dc ("(1.0 2.0]")));
+ assert (!satisfies (dc ("(1.0+1 2.0]"), dc ("(1.0 2.0]")));
+ assert ( satisfies (dc ("(1.0+0 2.0]"), dc ("[1.0 2.0]")));
+ assert ( satisfies (dc ("(1.0+1 2.0]"), dc ("[1.0 2.0]")));
+
+ assert (!satisfies (dc ("[1.0 2.0+0]"), dc ("[1.0 2.0)")));
+ assert (!satisfies (dc ("[1.0 2.0+1]"), dc ("[1.0 2.0)")));
+ assert ( satisfies (dc ("[1.0 2.0+0)"), dc ("[1.0 2.0)")));
+ assert (!satisfies (dc ("[1.0 2.0+1)"), dc ("[1.0 2.0)")));
+
+ // Swap the above constraints.
+ //
+ assert (!satisfies (dc ("[1.0 2.0]"), dc ("[1.0 2.0+0]")));
+ assert (!satisfies (dc ("[1.0 2.0]"), dc ("[1.0 2.0+1]")));
+ assert ( satisfies (dc ("[1.0 2.0+0]"), dc ("[1.0 2.0]")));
+ assert ( satisfies (dc ("[1.0 2.0+1]"), dc ("[1.0 2.0]")));
+
+ assert ( satisfies (dc ("(1.0 2.0]"), dc ("[1.0+0 2.0]")));
+ assert ( satisfies (dc ("(1.0 2.0]"), dc ("[1.0+1 2.0]")));
+ assert ( satisfies (dc ("(1.0 2.0]"), dc ("(1.0+0 2.0]")));
+ assert ( satisfies (dc ("(1.0 2.0]"), dc ("(1.0+1 2.0]")));
+ assert (!satisfies (dc ("[1.0 2.0]"), dc ("(1.0+0 2.0]")));
+ assert (!satisfies (dc ("[1.0 2.0]"), dc ("(1.0+1 2.0]")));
+
+ assert ( satisfies (dc ("[1.0 2.0)"), dc ("[1.0 2.0+0)")));
+ assert ( satisfies (dc ("[1.0 2.0)"), dc ("[1.0 2.0+1)")));
+ assert (!satisfies (dc ("[1.0 2.0]"), dc ("[1.0 2.0+0)")));
+ assert (!satisfies (dc ("[1.0 2.0]"), dc ("[1.0 2.0+1)")));
+
+ return 0;
+ }
+}
+
+int
+main (int argc, char* argv[])
+{
+ return bpkg::main (argc, argv);
+}
diff --git a/tests/common/satisfy/libbar-1.1.1.tar.gz b/tests/common/satisfy/libbar-1.1.1.tar.gz
new file mode 100644
index 0000000..b4b0bb7
--- /dev/null
+++ b/tests/common/satisfy/libbar-1.1.1.tar.gz
Binary files differ
diff --git a/tests/common/satisfy/libfoo-1.1.0+1.tar.gz b/tests/common/satisfy/libfoo-1.1.0+1.tar.gz
new file mode 100644
index 0000000..8cc49aa
--- /dev/null
+++ b/tests/common/satisfy/libfoo-1.1.0+1.tar.gz
Binary files differ
diff --git a/tests/common/satisfy/t4e/libbar-1.1.0.tar.gz b/tests/common/satisfy/t4e/libbar-1.1.0.tar.gz
new file mode 120000
index 0000000..b9a2de5
--- /dev/null
+++ b/tests/common/satisfy/t4e/libbar-1.1.0.tar.gz
@@ -0,0 +1 @@
+../libbar-1.1.0.tar.gz \ No newline at end of file
diff --git a/tests/common/satisfy/t4e/libbar-1.1.1.tar.gz b/tests/common/satisfy/t4e/libbar-1.1.1.tar.gz
new file mode 120000
index 0000000..0784aba
--- /dev/null
+++ b/tests/common/satisfy/t4e/libbar-1.1.1.tar.gz
@@ -0,0 +1 @@
+../libbar-1.1.1.tar.gz \ No newline at end of file
diff --git a/tests/common/satisfy/t4e/libfoo-1.1.0+1.tar.gz b/tests/common/satisfy/t4e/libfoo-1.1.0+1.tar.gz
new file mode 120000
index 0000000..ca9c01a
--- /dev/null
+++ b/tests/common/satisfy/t4e/libfoo-1.1.0+1.tar.gz
@@ -0,0 +1 @@
+../libfoo-1.1.0+1.tar.gz \ No newline at end of file
diff --git a/tests/common/satisfy/t4e/repositories.manifest b/tests/common/satisfy/t4e/repositories.manifest
new file mode 100644
index 0000000..4cc7c0a
--- /dev/null
+++ b/tests/common/satisfy/t4e/repositories.manifest
@@ -0,0 +1,4 @@
+: 1
+:
+location: ../t4a
+role: complement
diff --git a/tests/pkg-build.testscript b/tests/pkg-build.testscript
index 4465081..6ce1689 100644
--- a/tests/pkg-build.testscript
+++ b/tests/pkg-build.testscript
@@ -10,8 +10,8 @@
# Source repository:
#
# pkg-build
-# |-- libbar-1.0.0.tar.gz
-# |-- libbaz-1.1.0.tar.gz
+# |-- libbar-1.0.0.tar.gz -> libfoo
+# |-- libbaz-1.1.0.tar.gz -> libfoo, libbar
# |-- libfix-0.0.1.tar.gz
# |-- libfoo-0.0.1.tar.gz -> libfix
# |-- libfoo-1.0.0.tar.gz
@@ -95,6 +95,10 @@
# | |-- libfox-1.0.0.tar.gz
# | `-- repositories.manifest
# |
+# |-- t4e
+# | |-- libfoo-1.1.0+1.tar.gz
+# | `-- repositories.manifest
+# |
# |-- t5
# | |-- libbar-1.2.0.tar.gz
# | `-- repositories.manifest
@@ -131,6 +135,7 @@
cp -r $src/t4b $out/t4b && $rep_create $out/t4b &$out/t4b/packages.manifest
cp -r $src/t4c $out/t4c && $rep_create $out/t4c &$out/t4c/packages.manifest
cp -r $src/t4d $out/t4d && $rep_create $out/t4d &$out/t4d/packages.manifest
+ cp -r $src/t4e $out/t4e && $rep_create $out/t4e &$out/t4e/packages.manifest
cp -r $src/t5 $out/t5 && $rep_create $out/t5 &$out/t5/packages.manifest
cp -r $src/t6 $out/t6 && $rep_create $out/t6 &$out/t6/packages.manifest
@@ -315,6 +320,33 @@ test.options += --no-progress
EOE
}
}
+
+ : revision
+ :
+ {
+ +$clone_root_cfg
+ +$rep_add $rep/t4e && $rep_fetch
+
+ : latest
+ :
+ {
+ $clone_cfg;
+
+ $* libfoo/1.1.0 >>EOO
+ new libfoo/1.1.0+1
+ EOO
+ }
+
+ : zero
+ :
+ {
+ $clone_cfg;
+
+ $* libfoo/1.1.0+0 >>EOO
+ new libfoo/1.1.0
+ EOO
+ }
+ }
}
: libbar-libfoo
@@ -420,6 +452,34 @@ test.options += --no-progress
$pkg_purge libfoo 2>'purged libfoo/1.1.0'
}
}
+
+ : dependency-revision
+ :
+ {
+ +$clone_root_cfg && $rep_add $rep/t4e && $rep_fetch
+
+ : latest
+ :
+ {
+ $clone_cfg;
+
+ $* libbar/1.1.0 >>EOO
+ new libfoo/1.1.0+1 (required by libbar)
+ new libbar/1.1.0
+ EOO
+ }
+
+ : zero
+ :
+ {
+ $clone_cfg;
+
+ $* libbar/1.1.1 >>EOO
+ new libfoo/1.1.0 (required by libbar)
+ new libbar/1.1.1
+ EOO
+ }
+ }
}
: libbaz-libbar
diff --git a/tests/pkg-build/t4e b/tests/pkg-build/t4e
new file mode 120000
index 0000000..9cd01c8
--- /dev/null
+++ b/tests/pkg-build/t4e
@@ -0,0 +1 @@
+../common/satisfy/t4e \ No newline at end of file
diff --git a/tests/pkg-status.testscript b/tests/pkg-status.testscript
index 39ea85a..1ac3a97 100644
--- a/tests/pkg-status.testscript
+++ b/tests/pkg-status.testscript
@@ -94,6 +94,11 @@ rep_fetch += -d cfg --auth all --trust-yes 2>!
$clone_cfg;
$* libfoo/1.0.0 >'libfoo available 1.0.0'
+ : libfoo-1.0.0+0
+ :
+ $clone_cfg;
+ $* libfoo/1.0.0+0 >'libfoo available 1.0.0'
+
: libfoo
:
$clone_cfg;
@@ -147,9 +152,30 @@ rep_fetch += -d cfg --auth all --trust-yes 2>!
: testing
:
{
- $clone_cfg ./ && $rep_add $rep/testing && $rep_fetch;
+ +$clone_cfg ./ && $rep_add $rep/testing && $rep_fetch
+
+ clone_cfg = cp -r ../cfg ./
+
+ : no-version
+ :
+ {
+ $clone_cfg;
+ $* libbar >'libbar available [1.1.0+1] 1.1.0 1.0.0+1 1.0.0'
+ }
- $* libbar >'libbar available [1.1.0+1] 1.1.0 1.0.0+1 1.0.0'
+ : no-revision
+ :
+ {
+ $clone_cfg;
+ $* libbar/1.0.0 >'libbar available 1.0.0+1 1.0.0'
+ }
+
+ : zero-revision
+ :
+ {
+ $clone_cfg;
+ $* libbar/1.0.0+0 >'libbar available 1.0.0'
+ }
}
: unstable