From 4b074f21d097e02a8343a4c1d8ad48e6661d622a Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 30 Dec 2015 20:24:29 +0200 Subject: Support package dependency version range --- bpkg/fetch.cxx | 2 +- bpkg/help.cxx | 12 +++--- bpkg/package | 58 +++++++++++++++---------- bpkg/package.xml | 52 +++++++++++++--------- bpkg/pkg-build.cxx | 34 +++++++-------- bpkg/satisfaction.cxx | 116 ++++++++++++++++++++------------------------------ 6 files changed, 137 insertions(+), 137 deletions(-) diff --git a/bpkg/fetch.cxx b/bpkg/fetch.cxx index f63a6e3..484d014 100644 --- a/bpkg/fetch.cxx +++ b/bpkg/fetch.cxx @@ -590,7 +590,7 @@ namespace bpkg ifs.exceptions (ofstream::badbit | ofstream::failbit); ofs.exceptions (ofstream::badbit | ofstream::failbit); - ofs << ifs.rdbuf(); + ofs << ifs.rdbuf (); // In case they throw. // diff --git a/bpkg/help.cxx b/bpkg/help.cxx index 3c44c52..16ef4e8 100644 --- a/bpkg/help.cxx +++ b/bpkg/help.cxx @@ -33,7 +33,7 @@ using namespace butl; namespace bpkg { - struct pager: protected std::streambuf + struct pager: protected streambuf { pager (const common_options& co, const string& name) { @@ -142,10 +142,10 @@ namespace bpkg buf_ = stream ().rdbuf (this); } - std::ostream& + ostream& stream () { - return os_.is_open () ? os_ : std::cout; + return os_.is_open () ? os_ : cout; } bool @@ -168,8 +168,8 @@ namespace bpkg // streambuf output interface. // protected: - using int_type = std::streambuf::int_type; - using traits_type = std::streambuf::traits_type; + using int_type = streambuf::int_type; + using traits_type = streambuf::traits_type; virtual int_type overflow (int_type c) @@ -198,7 +198,7 @@ namespace bpkg string indent_; int_type prev_ = '\n'; // Previous character. - std::streambuf* buf_ = nullptr; + streambuf* buf_ = nullptr; }; int diff --git a/bpkg/package b/bpkg/package index 318f09d..99b7924 100644 --- a/bpkg/package +++ b/bpkg/package @@ -18,7 +18,7 @@ #include #include -#pragma db model version(1, 1, open) +#pragma db model version(2, 2, open) namespace bpkg { @@ -67,7 +67,7 @@ namespace bpkg string canonical_release; uint16_t revision; string upstream; - string release; + optional release; }; } @@ -103,31 +103,29 @@ namespace bpkg { uint16_t epoch; string canonical_upstream; - - // By a fluke SQLite 3 uses BINARY collation for UTF-8-encoded TEXT columns - // by default. So no need to adjust it to make "absent" and specified - // canonical releases to compare properly. But better to keep an eye on - // it not to miss a moment if SQLite plug UCA-compliant collation. - // Note: PostgreSQL uses UCA-compliant one by default for UTF8-encoded - // TEXT columns. - // - // Unicode Collation Algorithm (UCA): http://unicode.org/reports/tr10/ - // string canonical_release; - uint16_t revision; + + // 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 + // in case the Unicode Collation Algorithm (UCA, where '~' < 'a') becomes + // the default. + // + #pragma db member(canonical_release) options("COLLATE BINARY") }; #pragma db value transient struct upstream_version: version { - #pragma db member(upstream_) virtual(string) \ - get(this.upstream) \ - set(this = bpkg::version (0, std::move (?), "~", 0)) + #pragma db member(upstream_) virtual(string) \ + get(this.upstream) \ + set(this = bpkg::version (0, std::move (?), std::string (), 0)) - #pragma db member(release_) virtual(string) \ - get(this.release) \ - set(this = bpkg::version (0, this.upstream, std::move (?), 0)) + #pragma db member(release_) virtual(optional_string) \ + get(this.release) \ + set(this = bpkg::version ( \ + 0, std::move (this.upstream), std::move (?), 0)) upstream_version () = default; upstream_version (version v): version (move (v)) {} @@ -155,6 +153,24 @@ namespace bpkg std::move ((?).release), \ (?).revision)) + using optional_version = optional; + using _optional_version = optional<_version>; + + #pragma db map type(optional_version) as(_optional_version) \ + to((?) \ + ? bpkg::_version{(?)->epoch, \ + (?)->canonical_upstream, \ + (?)->canonical_release, \ + (?)->revision, \ + (?)->upstream, \ + (?)->release} \ + : bpkg::_optional_version ()) \ + from((?) \ + ? bpkg::version ((?)->epoch, \ + std::move ((?)->upstream), \ + std::move ((?)->release), \ + (?)->revision) \ + : bpkg::optional_version ()) // repository_location // @@ -236,10 +252,6 @@ namespace bpkg // dependencies // - #pragma db map type(comparison) as(string) \ - to(to_string (?)) \ - from(bpkg::to_comparison (?)) - #pragma db value(dependency_constraint) definition #pragma db value(dependency) definition #pragma db member(dependency::constraint) column("") diff --git a/bpkg/package.xml b/bpkg/package.xml index f2c470c..80a4aa7 100644 --- a/bpkg/package.xml +++ b/bpkg/package.xml @@ -1,5 +1,5 @@ - + @@ -49,7 +49,7 @@ - + @@ -65,7 +65,7 @@ - + @@ -101,7 +101,7 @@ - + @@ -135,18 +135,25 @@ - + - - - - - - - + + + + + + + + + + + + + + @@ -193,13 +200,20 @@
- - - - - - - + + + + + + + + + + + + + + diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index d896b40..40f67b5 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -50,7 +50,7 @@ namespace bpkg // Return the package and the repository in which it was found or // NULL for both if not found. // - std::pair, shared_ptr> + pair, shared_ptr> find_available (database& db, const string& name, const shared_ptr& r, @@ -64,25 +64,26 @@ namespace bpkg // If there is a constraint, then translate it to the query. Otherwise, // get the latest version. // - bool order (true); if (c) { - const version& v (c->version); + if (c->min_version) + { + if (c->min_open) + q = q && vm > *c->min_version; + else + q = q && vm >= *c->min_version; + } - // Note that the constraint's version is always rhs (libfoo >= 1.2.3). - // - switch (c->operation) + if (c->max_version) { - case comparison::eq: q = q && vm == v; order = false; break; - case comparison::lt: q = q && vm < v; break; - case comparison::gt: q = q && vm > v; break; - case comparison::le: q = q && vm <= v; break; - case comparison::ge: q = q && vm >= v; break; + if (c->max_open) + q = q && vm < *c->max_version; + else + q = q && vm <= *c->max_version; } } - if (order) - q += order_by_version_desc (vm); + q += order_by_version_desc (vm); // Filter the result based on the repository to which each version // belongs. @@ -95,7 +96,7 @@ namespace bpkg // that the package locations list is left empty and that the // returned repository could be NULL if the package is an orphan. // - std::pair, shared_ptr> + pair, shared_ptr> make_available (const common_options& options, const dir_path& cd, database& db, @@ -844,8 +845,7 @@ namespace bpkg auto rp ( v.empty () ? find_available (db, n, root, nullopt) - : find_available (db, n, root, - dependency_constraint {comparison::eq, v})); + : find_available (db, n, root, dependency_constraint (v))); ap = rp.first; ar = rp.second; @@ -960,7 +960,7 @@ namespace bpkg if (!v.empty ()) p.constraints.emplace_back ( "command line", - dependency_constraint {comparison::eq, v}); + dependency_constraint (v)); pkgs.collect (o, c, db, move (p)); names.push_back (n); diff --git a/bpkg/satisfaction.cxx b/bpkg/satisfaction.cxx index af531f4..8198283 100644 --- a/bpkg/satisfaction.cxx +++ b/bpkg/satisfaction.cxx @@ -15,94 +15,68 @@ namespace bpkg bool satisfies (const version& v, const dependency_constraint& c) { - using op = comparison; + assert (!c.empty ()); - // Note that the constraint's version is always rhs (libfoo >= 1.2.3). - // - switch (c.operation) - { - case op::eq: return v == c.version; - case op::lt: return v < c.version; - case op::gt: return v > c.version; - case op::le: return v <= c.version; - case op::ge: return v >= c.version; - } + bool s (true); + + if (c.min_version) + s = c.min_open ? v > *c.min_version : v >= *c.min_version; - assert (false); - return false; + if (s && c.max_version) + s = c.max_open ? v < *c.max_version : v <= *c.max_version; + + return s; } bool satisfies (const dependency_constraint& l, const dependency_constraint& r) { - using op = comparison; - - op lo (l.operation); - op ro (r.operation); + assert (!l.empty () && !r.empty ()); - const version& lv (l.version); - const version& rv (r.version); + bool s (false); - switch (lo) + if (l.min_version) { - case op::eq: // == - { - switch (ro) - { - case op::eq: return lv == rv; - case op::lt: return lv < rv; - case op::le: return lv <= rv; - case op::gt: return lv > rv; - case op::ge: return lv >= rv; - } - } - case op::lt: // < - { - switch (ro) - { - case op::lt: return lv <= rv; - case op::le: return lv < rv; - case op::eq: - case op::gt: - case op::ge: return false; - } - } - case op::le: // <= + if (r.min_version) { - switch (ro) - { - case op::lt: return lv < rv; - case op::le: return lv <= rv; - case op::eq: - case op::gt: - case op::ge: return false; - } + if (l.min_open) + // Doesn't matter if r is min_open or not. + // + s = *l.min_version >= *r.min_version; + else + s = r.min_open + ? *l.min_version > *r.min_version + : *l.min_version >= *r.min_version; } - case op::gt: // > - { - switch (ro) - { - case op::gt: return lv >= rv; - case op::ge: return lv > rv; - case op::eq: - case op::lt: - case op::le: return false; - } - } - case op::ge: // >= + else + s = true; // Doesn't matter what l.min_version is. + } + else + s = !r.min_version; + + if (s) + { + if (l.max_version) { - switch (ro) + if (r.max_version) { - case op::gt: return lv > rv; - case op::ge: return lv >= rv; - case op::eq: - case op::lt: - case op::le: return false; + if (l.max_open) + // Doesn't matter if r is max_open or not. + // + s = *l.max_version <= *r.max_version; + else + s = r.max_open + ? *l.max_version < *r.max_version + : *l.max_version <= *r.max_version; } + else + // Doesn't matter what l.max_version is, so leave s to be true. + ; } + else + s = !r.max_version; } - assert (false); - return false; + return s; } } -- cgit v1.1