From dd0f7ec5e776c25cbb0b6715bf62d52a9965f9b1 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 25 Dec 2015 19:59:45 +0200 Subject: Support version release --- brep/mod-package-details.cxx | 3 +- brep/package | 102 ++++++++++++++++++++++++++++++++----------- brep/package-extra.sql | 16 +++++-- 3 files changed, 91 insertions(+), 30 deletions(-) (limited to 'brep') diff --git a/brep/mod-package-details.cxx b/brep/mod-package-details.cxx index ba6387e..ca01d55 100644 --- a/brep/mod-package-details.cxx +++ b/brep/mod-package-details.cxx @@ -187,7 +187,8 @@ handle (request& rq, response& rs) db_->query ( search_params (name, squery) + "ORDER BY rank DESC, version_epoch DESC, " - "version_canonical_upstream DESC, version_revision DESC" + + "version_canonical_upstream DESC, version_canonical_release DESC, " + "version_revision DESC" + "OFFSET" + to_string (page * res_page) + "LIMIT" + to_string (res_page))) { diff --git a/brep/package b/brep/package index 8a9dcb2..9e4dde6 100644 --- a/brep/package +++ b/brep/package @@ -9,6 +9,7 @@ #include #include #include // ostream +#include #include // static_assert #include @@ -28,8 +29,10 @@ namespace brep { uint16_t epoch; string canonical_upstream; + string canonical_release; uint16_t revision; string upstream; + string release; }; } @@ -50,12 +53,17 @@ void assert (int); // bpkg namespace from which we "borrow" types (and some of them use // version and comparison). // -#pragma db map type(bpkg::version) as(brep::_version) \ - to(brep::_version{(?).epoch, \ - (?).canonical_upstream, \ - (?).revision, \ - (?).upstream}) \ - from(bpkg::version ((?).epoch, std::move ((?).upstream), (?).revision)) +#pragma db map type(bpkg::version) as(brep::_version) \ + to(brep::_version{(?).epoch, \ + (?).canonical_upstream, \ + (?).canonical_release, \ + (?).revision, \ + (?).upstream, \ + (?).release}) \ + from(bpkg::version ((?).epoch, \ + std::move ((?).upstream), \ + std::move ((?).release), \ + (?).revision)) #pragma db map type(bpkg::comparison) as(brep::string) \ to(bpkg::to_string (?)) \ @@ -119,27 +127,58 @@ namespace brep { uint16_t epoch; string canonical_upstream; + string canonical_release; uint16_t revision; + // @@ The following function will fail the assertion for versions like + // 0.0.0 (canonical_upstream is empty, canonical_release set to "~"). + // The problem here is that it's possible to specify such a version + // which canonical representation is indistinguishable from that of + // the empty version. Example: 0.0.0- + // This effectivelly make it impossible to use canonical_version as a + // primary key. Need to think on fixing that problem on the version + // specification level. Probably canonical upstream (and release) for + // non-empty version should always start with '.'. + // Examples: ".00000001.a" for "1.A", ".", for "0.0.0" + // + // @@ Also version spec do not mention that trailing zero-only components + // get removed. + // + // @@ If by some reason decide to leave canonical upstream representation + // as is, then need to drop the function below, make the loader not + // using it. + // bool empty () const noexcept { - // No sense to test epoch and revision for 0 as a valid canonical_version - // object can not have them different from 0 if canonical_upstream is - // empty. The predicate semantics is equal to the one of the - // bpkg::version class. - // - assert (!canonical_upstream.empty () || (epoch == 0 && revision == 0)); - return canonical_upstream.empty (); + bool e (canonical_upstream.empty ()); + assert (!e || + (epoch == 0 && canonical_release.empty () && revision == 0)); + return e; } + + // Change collation to ensure the proper comparison of the "absent" release + // with a specified one. + // + // The default collation for UTF8-encoded TEXT columns in PostgreSQL is + // UCA-compliant. This makes the statement 'a' < '~' to be false, which + // in turn makes the statement 2.1.alpha < 2.1 to be false as well. + // + // Unicode Collation Algorithm (UCA): http://unicode.org/reports/tr10/ + // + #pragma db member(canonical_release) options("COLLATE \"C\"") }; #pragma db value transient struct upstream_version: version { - #pragma db member(upstream_) virtual(string) \ - get(this.upstream) \ - set(this = brep::version (0, std::move (?), 0)) + #pragma db member(upstream_) virtual(string) \ + get(this.upstream) \ + set(this = brep::version (0, std::move (?), "~", 0)) + + #pragma db member(release_) virtual(string) \ + get(this.release) \ + set(this = brep::version (0, this.upstream, std::move (?), 0)) upstream_version () = default; upstream_version (version v): version (move (v)) {} @@ -149,8 +188,9 @@ namespace brep void init (const canonical_version& cv, const upstream_version& uv) { - *this = version (cv.epoch, uv.upstream, cv.revision); - assert (cv.canonical_upstream == canonical_upstream); + *this = version (cv.epoch, uv.upstream, uv.release, cv.revision); + assert (cv.canonical_upstream == canonical_upstream && + cv.canonical_release == canonical_release); } }; @@ -200,7 +240,8 @@ namespace brep package_id () = default; package_id (string n, const brep::version& v) : name (move (n)), - version {v.epoch, v.canonical_upstream, v.revision} + version { + v.epoch, v.canonical_upstream, v.canonical_release, v.revision} { } }; @@ -586,8 +627,8 @@ namespace brep // Version comparison operators. // - // They allow comparing objects that have epoch, canonical_upstream - // and revision data members. + // They allow comparing objects that have epoch, canonical_upstream, + // canonical_release, and revision data members. // template inline auto @@ -595,6 +636,7 @@ namespace brep { return x.epoch == y.epoch && x.canonical_upstream == y.canonical_upstream && + x.canonical_release == y.canonical_release && x.revision == y.revision; } @@ -604,6 +646,7 @@ namespace brep { return x.epoch != y.epoch || x.canonical_upstream != y.canonical_upstream || + x.canonical_release != y.canonical_release || x.revision != y.revision; } @@ -614,7 +657,9 @@ namespace brep return x.epoch < y.epoch || (x.epoch == y.epoch && x.canonical_upstream < y.canonical_upstream) || (x.epoch == y.epoch && x.canonical_upstream == y.canonical_upstream && - x.revision < y.revision); + x.canonical_release < y.canonical_release) || + (x.epoch == y.epoch && x.canonical_upstream == y.canonical_upstream && + x.canonical_release == y.canonical_release && x.revision < y.revision); } template @@ -624,7 +669,9 @@ namespace brep return x.epoch < y.epoch || (x.epoch == y.epoch && x.canonical_upstream < y.canonical_upstream) || (x.epoch == y.epoch && x.canonical_upstream == y.canonical_upstream && - x.revision <= y.revision); + x.canonical_release < y.canonical_release) || + (x.epoch == y.epoch && x.canonical_upstream == y.canonical_upstream && + x.canonical_release == y.canonical_release && x.revision <= y.revision); } template @@ -634,7 +681,9 @@ namespace brep return x.epoch > y.epoch || (x.epoch == y.epoch && x.canonical_upstream > y.canonical_upstream) || (x.epoch == y.epoch && x.canonical_upstream == y.canonical_upstream && - x.revision > y.revision); + x.canonical_release > y.canonical_release) || + (x.epoch == y.epoch && x.canonical_upstream == y.canonical_upstream && + x.canonical_release == y.canonical_release && x.revision > y.revision); } template @@ -644,7 +693,9 @@ namespace brep return x.epoch > y.epoch || (x.epoch == y.epoch && x.canonical_upstream > y.canonical_upstream) || (x.epoch == y.epoch && x.canonical_upstream == y.canonical_upstream && - x.revision >= y.revision); + x.canonical_release > y.canonical_release) || + (x.epoch == y.epoch && x.canonical_upstream == y.canonical_upstream && + x.canonical_release == y.canonical_release && x.revision >= y.revision); } template @@ -655,6 +706,7 @@ namespace brep return "ORDER BY" + x.epoch + "DESC," + x.canonical_upstream + "DESC," + + x.canonical_release + "DESC," + x.revision + "DESC"; } diff --git a/brep/package-extra.sql b/brep/package-extra.sql index 6859173..acf1489 100644 --- a/brep/package-extra.sql +++ b/brep/package-extra.sql @@ -20,7 +20,9 @@ RETURNS SETOF package AS $$ p1.version_epoch = p2.version_epoch AND (p1.version_canonical_upstream < p2.version_canonical_upstream OR p1.version_canonical_upstream = p2.version_canonical_upstream AND - p1.version_revision < p2.version_revision))) + (p1.version_canonical_release < p2.version_canonical_release OR + p1.version_canonical_release = p2.version_canonical_release AND + p1.version_revision < p2.version_revision)))) WHERE p1.internal_repository IS NOT NULL AND p2.name IS NULL; $$ LANGUAGE SQL STABLE; @@ -33,9 +35,11 @@ CREATE FUNCTION latest_package(INOUT name TEXT, OUT version_epoch SMALLINT, OUT version_canonical_upstream TEXT, + OUT version_canonical_release TEXT, OUT version_revision SMALLINT) RETURNS SETOF record AS $$ - SELECT name, version_epoch, version_canonical_upstream, version_revision + SELECT name, version_epoch, version_canonical_upstream, + version_canonical_release, version_revision FROM latest_packages() WHERE name = latest_package.name; $$ LANGUAGE SQL STABLE; @@ -50,10 +54,12 @@ search_latest_packages(IN query tsquery, OUT name TEXT, OUT version_epoch SMALLINT, OUT version_canonical_upstream TEXT, + OUT version_canonical_release TEXT, OUT version_revision SMALLINT, OUT rank real) RETURNS SETOF record AS $$ - SELECT name, version_epoch, version_canonical_upstream, version_revision, + SELECT name, version_epoch, version_canonical_upstream, + version_canonical_release, version_revision, CASE WHEN query IS NULL THEN 0 -- Weight mapping: D C B A @@ -72,10 +78,12 @@ search_packages(IN query tsquery, INOUT name TEXT, OUT version_epoch SMALLINT, OUT version_canonical_upstream TEXT, + OUT version_canonical_release TEXT, OUT version_revision SMALLINT, OUT rank real) RETURNS SETOF record AS $$ - SELECT name, version_epoch, version_canonical_upstream, version_revision, + SELECT name, version_epoch, version_canonical_upstream, + version_canonical_release, version_revision, CASE WHEN query IS NULL THEN 0 -- Weight mapping: D C B A -- cgit v1.1