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 --- INSTALL | 3 +- INSTALL-DEV | 3 +- brep/mod-package-details.cxx | 3 +- brep/package | 102 +++++++++++++++++++++++++++++++---------- brep/package-extra.sql | 16 +++++-- loader/loader.cxx | 1 + tests/loader/1/math/packages | 14 +++--- tests/loader/1/misc/packages | 8 ++-- tests/loader/1/stable/packages | 15 ++++-- tests/loader/driver.cxx | 42 +++++++++++++---- 10 files changed, 152 insertions(+), 55 deletions(-) diff --git a/INSTALL b/INSTALL index 1354921..1944228 100644 --- a/INSTALL +++ b/INSTALL @@ -103,7 +103,8 @@ $ cd .. # Back to brep home. $ sudo sudo -u postgres psql # Note: double sudo is not a mistake. -CREATE DATABASE brep; +CREATE DATABASE brep TEMPLATE template0 ENCODING 'UTF8' \ +LC_COLLATE 'en_US.UTF8' LC_CTYPE 'en_US.UTF8'; CREATE USER brep; GRANT ALL PRIVILEGES ON DATABASE brep TO brep; CREATE USER "www-data" INHERIT IN ROLE brep; diff --git a/INSTALL-DEV b/INSTALL-DEV index 62c2437..3ba9ff5 100644 --- a/INSTALL-DEV +++ b/INSTALL-DEV @@ -28,7 +28,8 @@ group, not user. However, most installations use the same name for both.] $ sudo sudo -u postgres psql # Note: double sudo is not a mistake. -CREATE DATABASE brep; +CREATE DATABASE brep TEMPLATE template0 ENCODING 'UTF8' \ +LC_COLLATE 'en_US.UTF8' LC_CTYPE 'en_US.UTF8'; CREATE USER ; GRANT ALL PRIVILEGES ON DATABASE brep TO ; CREATE USER "www-data" INHERIT IN ROLE ; 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 diff --git a/loader/loader.cxx b/loader/loader.cxx index 68f145b..2c74e34 100644 --- a/loader/loader.cxx +++ b/loader/loader.cxx @@ -280,6 +280,7 @@ load_packages (const shared_ptr& rp, database& db) { pm.version.epoch, pm.version.canonical_upstream, + pm.version.canonical_release, pm.version.revision } })); diff --git a/tests/loader/1/math/packages b/tests/loader/1/math/packages index 4d34c13..7b81c5e 100644 --- a/tests/loader/1/math/packages +++ b/tests/loader/1/math/packages @@ -1,6 +1,6 @@ : 1 name: libstudxml -version: 1.0.0-1 +version: 1.0.0+1 summary: Modern C++ XML API license: MIT tags: c++, xml, parser, serializer, pull, streaming, modern @@ -12,10 +12,10 @@ email: studxml-users@codesynthesis.com; Public mailing list, posts by\ package-email: boris@codesynthesis.com; Direct email to the author. depends: libexpat >= 2.0.0 depends: libgenx -location: libstudxml-1.0.0-1.tar.gz +location: libstudxml-1.0.0+1.tar.gz : name: libexp -version: 1+1.2 +version: 1~1.2 summary: The exponent description: The exponent math function. license: MIT @@ -23,10 +23,10 @@ tags: c++, exponent url: http://www.exp.com email: users@exp.com depends: libmisc -location: libexp-1+1.2.tar.gz +location: libexp-1~1.2.tar.gz : name: libfoo -version: 1.2.4-1 +version: 1.2.4+1 summary: The Foo Math Library description:\ A modern C++ library with easy to use linear algebra and lot of optimization @@ -52,9 +52,9 @@ requires: linux | windows | macosx; Symbian support is coming. requires: c++11 requires: ? ; libc++ standard library if using Clang on Mac OS X. requires: ? vc++ >= 12.0; Only if using VC++ on Windows. -location: libfoo-1.2.4-1.tar.gz +location: libfoo-1.2.4+1.tar.gz changes:\ -1.2.4-1 +1.2.4+1 * applied patch for critical bug-219 * regenerated documentation diff --git a/tests/loader/1/misc/packages b/tests/loader/1/misc/packages index e47208d..fec3780 100644 --- a/tests/loader/1/misc/packages +++ b/tests/loader/1/misc/packages @@ -31,17 +31,17 @@ email: foo-users@example.com location: libfoo-0.1.tar.gz : name: libfoo -version: 1.2.4-1 +version: 1.2.4+1 summary: Foo Library license: MIT url: http://www.example.com/foo/ email: foo-users@example.com -location: libfoo-1.2.4-1.tar.gz +location: libfoo-1.2.4+1.tar.gz : name: libfoo -version: 1.2.4-2 +version: 1.2.4+2 summary: Foo Library license: MIT url: http://www.example.com/foo/ email: foo-users@example.com -location: libfoo-1.2.4-2.tar.gz +location: libfoo-1.2.4+2.tar.gz diff --git a/tests/loader/1/stable/packages b/tests/loader/1/stable/packages index 756a562..1a385c3 100644 --- a/tests/loader/1/stable/packages +++ b/tests/loader/1/stable/packages @@ -1,13 +1,13 @@ : 1 name: libfoo -version: 1.2.3-4 +version: 1.2.3+4 summary: The Foo library license: MIT tags: c++, foo url: http://www.example.com/foo/ email: foo-users@example.com depends: libmisc >= 2.0.0 -location: libfoo-1.2.3-4.tar.gz +location: libfoo-1.2.3+4.tar.gz : name: libfoo version: 1.2.2 @@ -17,10 +17,19 @@ tags: c++, foo url: http://www.example.com/foo/ email: foo-users@example.com depends: libbar <= 2.4.0 -depends: libexp == 1+1.2 +depends: libexp == 1~1.2 location: libfoo-1.2.2.tar.gz : name: libfoo +version: 1.2.2-alpha.1 +summary: The Foo library +license: MIT +tags: c++, foo +url: http://www.example.com/foo/ +email: foo-users@example.com +location: libfoo-1.2.2-alpha.1.tar.gz +: +name: libfoo version: 1.2.4 summary: The Foo Library description: Very good foo library. diff --git a/tests/loader/driver.cxx b/tests/loader/driver.cxx index 7ca1e6e..51f2ed8 100644 --- a/tests/loader/driver.cxx +++ b/tests/loader/driver.cxx @@ -99,7 +99,7 @@ main (int argc, char* argv[]) transaction t (db.begin ()); assert (db.query ().size () == 5); - assert (db.query ().size () == 14); + assert (db.query ().size () == 15); shared_ptr sr (db.load ("cppget.org/stable")); shared_ptr mr (db.load ("cppget.org/math")); @@ -138,8 +138,12 @@ main (int argc, char* argv[]) db.load (package_id ("libfoo", version ("1.2.2")))); assert (check_location (fpv2)); + shared_ptr fpv2a ( + db.load (package_id ("libfoo", version ("1.2.2-alpha.1")))); + assert (check_location (fpv2a)); + shared_ptr fpv3 ( - db.load (package_id ("libfoo", version ("1.2.3-4")))); + db.load (package_id ("libfoo", version ("1.2.3+4")))); assert (check_location (fpv3)); shared_ptr fpv4 ( @@ -218,9 +222,29 @@ main (int argc, char* argv[]) dep ( "libexp", optional ( - dependency_constraint{comparison::eq, version ("1+1.2")}))); + dependency_constraint{comparison::eq, version ("1~1.2")}))); - assert (fpv2->requirements.empty ()); + // libfoo-1.2.2-alpha.1 + // + assert (fpv2a->summary == "The Foo library"); + assert (fpv2a->tags == strings ({"c++", "foo"})); + assert (!fpv2a->description); + assert (fpv2a->url == "http://www.example.com/foo/"); + assert (!fpv2a->package_url); + assert (fpv2a->email == "foo-users@example.com"); + assert (!fpv2a->package_email); + + assert (fpv2a->internal_repository.load () == sr); + assert (fpv2a->other_repositories.empty ()); + assert (fpv2a->priority == priority::low); + assert (fpv2a->changes.empty ()); + + assert (fpv2a->license_alternatives.size () == 1); + assert (fpv2a->license_alternatives[0].size () == 1); + assert (fpv2a->license_alternatives[0][0] == "MIT"); + + assert (fpv2a->dependencies.empty ()); + assert (fpv2a->requirements.empty ()); // libfoo-1.2.3-4 // @@ -303,15 +327,15 @@ main (int argc, char* argv[]) assert (mr->internal); shared_ptr epv ( - db.load (package_id ("libexp", version ("1+1.2")))); + db.load (package_id ("libexp", version ("1~1.2")))); assert (check_location (epv)); shared_ptr fpv5 ( - db.load (package_id ("libfoo", version ("1.2.4-1")))); + db.load (package_id ("libfoo", version ("1.2.4+1")))); assert (check_location (fpv5)); shared_ptr xpv ( - db.load (package_id ("libstudxml", version ("1.0.0-1")))); + db.load (package_id ("libstudxml", version ("1.0.0+1")))); assert (check_location (xpv)); assert (mr->complements.empty ()); @@ -383,7 +407,7 @@ main (int argc, char* argv[]) assert (fpv5->priority.comment == "Critical bug fixes, performance improvement."); - const char ch[] = R"DLM(1.2.4-1 + const char ch[] = R"DLM(1.2.4+1 * applied patch for critical bug-219 * regenerated documentation @@ -512,7 +536,7 @@ main (int argc, char* argv[]) assert (check_location (fpv0)); shared_ptr fpv6 ( - db.load (package_id ("libfoo", version ("1.2.4-2")))); + db.load (package_id ("libfoo", version ("1.2.4+2")))); assert (check_location (fpv6)); assert (cr->prerequisites.empty ()); -- cgit v1.1