diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2017-04-27 19:36:58 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2017-04-28 12:08:08 +0300 |
commit | 5bb170316ebad036ee5b8b18dee7ce3d09c72df4 (patch) | |
tree | acb30c55637b40e7fb4ff9679cb9187ffa410c68 | |
parent | dad361a3415e88475a78d1b2702133629fb6e548 (diff) |
Add support for standard version earliest pre-release
-rw-r--r-- | butl/standard-version | 30 | ||||
-rw-r--r-- | butl/standard-version.cxx | 88 | ||||
-rw-r--r-- | butl/standard-version.ixx | 20 | ||||
-rw-r--r-- | tests/standard-version/driver.cxx | 15 | ||||
-rw-r--r-- | tests/standard-version/testscript | 50 |
5 files changed, 141 insertions, 62 deletions
diff --git a/butl/standard-version b/butl/standard-version index c9637d8..0c7b9bc 100644 --- a/butl/standard-version +++ b/butl/standard-version @@ -16,17 +16,20 @@ namespace butl { - // The build2 "standard version": + // The build2 "standard version" (specific and earliest): // // [<epoch>~]<maj>.<min>.<patch>[-(a|b).<num>[.<snapsn>[.<snapid>]]][+<rev>] + // [<epoch>~]<maj>.<min>.<patch>- // struct LIBBUTL_EXPORT standard_version { // Invariants: // - // 1. (E == 0) == (snapshot_sn == 0 && snapshot_id.empty ()) + // 1. allow_earliest + // ? (E == 1) || (snapshot_sn == 0) + // : (E == 0) == (snapshot_sn == 0) // - // 2. snapshot_sn != latest_sn || snapshot_id.empty () + // 2. snapshot_sn != latest_sn && snapshot_sn != 0 || snapshot_id.empty () // static const std::uint64_t latest_sn = std::uint64_t (~0); @@ -58,6 +61,13 @@ namespace butl bool beta () const noexcept; bool snapshot () const noexcept {return snapshot_sn != 0;} + // Is represented by DDDE being 0001 and snapshot_sn being 0. + // + // Note that the earliest version is a final alpha pre-release. + // + bool + earliest () const noexcept; + int compare (const standard_version&) const noexcept; @@ -65,23 +75,27 @@ namespace butl // recognizable or components are invalid. // explicit - standard_version (const std::string&); + standard_version (const std::string&, bool allow_earliest = false); explicit - standard_version (std::uint64_t version); + standard_version (std::uint64_t version, bool allow_earliest = false); - standard_version (std::uint64_t version, const std::string& snapshot); + standard_version (std::uint64_t version, + const std::string& snapshot, + bool allow_earliest = false); standard_version (std::uint16_t epoch, std::uint64_t version, const std::string& snapshot, - std::uint16_t revision); + std::uint16_t revision, + bool allow_earliest = false); standard_version (std::uint16_t epoch, std::uint64_t version, std::uint64_t snapshot_sn, std::string snapshot_id, - std::uint16_t revision); + std::uint16_t revision, + bool allow_earliest = false); // Create empty version. // diff --git a/butl/standard-version.cxx b/butl/standard-version.cxx index 552aac8..16095c0 100644 --- a/butl/standard-version.cxx +++ b/butl/standard-version.cxx @@ -38,7 +38,7 @@ namespace butl } static void - check_version (uint64_t version, bool snapshot) + check_version (uint64_t version, bool snapshot, bool allow_earliest) { // Check that the version isn't too large. // @@ -46,9 +46,18 @@ namespace butl bool r (version < 10000000000000ULL); // Check that E version component is consistent with the snapshot flag. + // Note that if the allow_earliest flag is true, then E can be 1 for the + // snapshot flag being false, denoting the earliest pre-release of the + // version. // if (r) - r = (version % 10) == (snapshot ? 1 : 0); + { + uint64_t e (version % 10); + if (!allow_earliest) + r = e == (snapshot ? 1 : 0); + else + r = e == 1 || (e == 0 && !snapshot); + } // Check that pre-release number is consistent with the snapshot flag. // @@ -78,7 +87,7 @@ namespace butl // standard_version // standard_version:: - standard_version (const std::string& s) + standard_version (const std::string& s, bool allow_earliest) { auto bail = [] (const char* m) {throw invalid_argument (m);}; @@ -127,56 +136,66 @@ namespace butl // Parse the pre-release component if present. // + bool earliest (false); if (s[p] == '-') { char k (s[++p]); - if (k != 'a' && k != 'b') - bail ("'a' or 'b' expected in pre-release"); + if (k == '\0' && allow_earliest) // Dash is the last string character. + earliest = true; + else + { + if (k != 'a' && k != 'b') + bail ("'a' or 'b' expected in pre-release"); - if (s[++p] != '.') - bail ("'.' expected after pre-release letter"); + if (s[++p] != '.') + bail ("'.' expected after pre-release letter"); - ab = parse_num (s, ++p, "invalid pre-release", 0, 499); + ab = parse_num (s, ++p, "invalid pre-release", 0, 499); - if (k == 'b') - ab += 500; + if (k == 'b') + ab += 500; - // Parse the snapshot components if present. Note that pre-release number - // can't be zero for the final pre-release. - // - if (s[p] == '.') - parse_snapshot (s, ++p); - else if (ab == 0 || ab == 500) - bail ("invalid final pre-release"); + // Parse the snapshot components if present. Note that pre-release number + // can't be zero for the final pre-release. + // + if (s[p] == '.') + parse_snapshot (s, ++p); + else if (ab == 0 || ab == 500) + bail ("invalid final pre-release"); + } } if (s[p] == '+') + { + assert (!earliest); // Would bail out earlier (a or b expected after -). + revision = parse_num (s, ++p, "invalid revision", 1, uint16_t (~0)); + } if (p != s.size ()) bail ("junk after version"); - if (ab != 0) + if (ab != 0 || snapshot_sn != 0 || earliest) version -= 10000 - ab * 10; - if (snapshot_sn != 0) + if (snapshot_sn != 0 || earliest) version += 1; } standard_version:: - standard_version (uint64_t v) + standard_version (uint64_t v, bool allow_earliest) : version (v) { - check_version (v, false); + check_version (v, false, allow_earliest); } standard_version:: - standard_version (uint64_t v, const std::string& s) + standard_version (uint64_t v, const std::string& s, bool allow_earliest) : version (v) { bool snapshot (!s.empty ()); - check_version (version, snapshot); + check_version (version, snapshot, allow_earliest); if (snapshot) { @@ -193,14 +212,15 @@ namespace butl uint64_t vr, uint64_t sn, std::string si, - uint16_t rv) + uint16_t rv, + bool allow_earliest) : epoch (ep), version (vr), snapshot_sn (sn), snapshot_id (move (si)), revision (rv) { - check_version (vr, true); + check_version (vr, true, allow_earliest); if (!snapshot_id.empty () && (snapshot_id.size () > 16 || snapshot_sn == 0 || @@ -244,7 +264,7 @@ namespace butl { std::string r; - if (alpha () || beta ()) + if ((alpha () && !earliest ()) || beta ()) { uint64_t ab (version / 10 % 1000); @@ -360,7 +380,7 @@ namespace butl try { - min_version = standard_version (s.substr (p, e - p)); + min_version = standard_version (s.substr (p, e - p), true); } catch (const invalid_argument& e) { @@ -377,7 +397,7 @@ namespace butl try { - max_version = standard_version (s.substr (p, e - p)); + max_version = standard_version (s.substr (p, e - p), true); } catch (const invalid_argument& e) { @@ -425,7 +445,7 @@ namespace butl try { - v = standard_version (s.substr (p)); + v = standard_version (s.substr (p), operation != comparison::eq); } catch (const invalid_argument& e) { @@ -482,8 +502,14 @@ namespace butl if (*min_version > *max_version) throw invalid_argument ("min version is greater than max version"); - if (*min_version == *max_version && (min_open || max_open)) - throw invalid_argument ("equal version endpoints not closed"); + if (*min_version == *max_version) + { + if (min_open || max_open) + throw invalid_argument ("equal version endpoints not closed"); + + if (min_version->earliest ()) + throw invalid_argument ("equal version endpoints are earliest"); + } } } diff --git a/butl/standard-version.ixx b/butl/standard-version.ixx index b01faef..332eb02 100644 --- a/butl/standard-version.ixx +++ b/butl/standard-version.ixx @@ -8,8 +8,9 @@ namespace butl standard_version ( std::uint16_t e, std::uint64_t v, const std::string& s, - std::uint16_t r) - : standard_version (v, s) + std::uint16_t r, + bool allow_earliest) + : standard_version (v, s, allow_earliest) { // Can't initialize above due to ctor delegating. // @@ -20,9 +21,10 @@ namespace butl inline std::uint16_t standard_version:: major () const noexcept { + std::uint64_t e (version % 10); std::uint64_t v (version / 10); std::uint64_t ab (v % 1000); - if (ab != 0) + if (ab != 0 || e == 1) v += 1000 - ab; return static_cast<std::uint16_t> (v / 1000000000 % 1000); @@ -31,9 +33,10 @@ namespace butl inline std::uint16_t standard_version:: minor () const noexcept { + std::uint64_t e (version % 10); std::uint64_t v (version / 10); std::uint64_t ab (v % 1000); - if (ab != 0) + if (ab != 0 || e == 1) v += 1000 - ab; return static_cast<std::uint16_t> (v / 1000000 % 1000); @@ -42,9 +45,10 @@ namespace butl inline std::uint16_t standard_version:: patch () const noexcept { + std::uint64_t e (version % 10); std::uint64_t v (version / 10); std::uint64_t ab (v % 1000); - if (ab != 0) + if (ab != 0 || e == 1) v += 1000 - ab; return static_cast<std::uint16_t> (v / 1000 % 1000); @@ -74,6 +78,12 @@ namespace butl return abe > 5000; } + inline bool standard_version:: + earliest () const noexcept + { + return version % 10000 == 1 && !snapshot (); + } + inline int standard_version:: compare (const standard_version& v) const noexcept { diff --git a/tests/standard-version/driver.cxx b/tests/standard-version/driver.cxx index d301c8c..e6a21ef 100644 --- a/tests/standard-version/driver.cxx +++ b/tests/standard-version/driver.cxx @@ -17,9 +17,9 @@ using namespace butl; // Create standard version from string, and also test another ctors. // static standard_version -version (const string& s) +version (const string& s, bool allow_earliest = true) { - standard_version r (s); + standard_version r (s, allow_earliest); try { @@ -28,7 +28,8 @@ version (const string& s) r.snapshot () ? r.string_snapshot () : string (), - r.revision); + r.revision, + allow_earliest); assert (r == v); @@ -37,12 +38,13 @@ version (const string& s) standard_version v (r.version, r.snapshot () ? r.string_snapshot () - : string ()); + : string (), + allow_earliest); assert (r == v); if (!r.snapshot ()) { - standard_version v (r.version); + standard_version v (r.version, allow_earliest); assert (r == v); } } @@ -53,7 +55,8 @@ version (const string& s) r.version, r.snapshot_sn, r.snapshot_id, - r.revision); + r.revision, + allow_earliest); assert (r == v); } diff --git a/tests/standard-version/testscript b/tests/standard-version/testscript index 9c80ddb..e5e3248 100644 --- a/tests/standard-version/testscript +++ b/tests/standard-version/testscript @@ -30,6 +30,12 @@ 1.2.3-a.0.456 1.2.3-a.1.456.340c0a26a5ef EOF + + : earliest + : + $* <<EOF >>EOF + 1.2.3- + EOF } : revision @@ -76,11 +82,7 @@ : $* <'1~0.0.0' 2>'0.0.0 version' == 1 - : a-b-expected1 - : - $* <'1.2.3-' 2>"'a' or 'b' expected in pre-release" == 1 - - : a-b-expected2 + : a-b-expected : $* <'1.2.3-k' 2>"'a' or 'b' expected in pre-release" == 1 @@ -122,6 +124,10 @@ : snapshot-id : $* <'1.2.3-a.0.1.83jdgsf+0' 2>'invalid revision' == 1 + + : earliest-prerelease + : + $* <'1.2.3-+1' 2>"'a' or 'b' expected in pre-release" == 1 } : trailing-junk-after @@ -146,6 +152,7 @@ $* '1.2.3-b.1' >n: beta $* '1.2.3-a.1' >y: final $* '1.2.3-a.0.1' >y: snapshot + $* '1.2.3-' >y: earliest } : beta @@ -157,6 +164,7 @@ $* '1.2.3-a.1' >n: alpha $* '1.2.3-b.1' >y: final $* '1.2.3-b.0.1' >y: snapshot + $* '1.2.3-' >n: earliest } : compare @@ -182,10 +190,16 @@ : { $* '1.2.3-a.1' '1.2.3-a.1' >'0' : equal - $* '1.2.3' '1.2.3-a.1' >'1' : release-gt-prereleas + $* '1.2.3' '1.2.3-a.1' >'1' : release-gt-prerelease $* '1.2.3-a.2' '1.2.3-b.1' >'-1' : a-lt-b $* '1.2.3-a.1' '1.2.3-a.1.2' >'-1' : final-lt-snapshot $* '1.2.3-a.1.2.xy' '1.2.3-a.1.2' >'0' : ignore-snapshot-id + $* '1.2.3' '1.2.3-a.0.1' >'1' : release-gt-snapshot + $* '1.2.3-a.0.1' '1.2.3-a.1' >'-1' : snapshot-lt-final + $* '1.2.3' '1.2.3-' >'1' : release-gt-earliest + $* '1.2.3-a.1' '1.2.3-' >'1' : final-gt-earliest + $* '1.2.3-a.0.1' '1.2.3-' >'1' : snapshot-gt-earliest + $* '1.2.2-b.499.z' '1.2.3-' >'-1' : prev-max-snapshot-lt-earliest } } @@ -202,11 +216,11 @@ $* <<EOI >>EOE [1.2.3 1.2.4] (1.2.3 1.2.4) - [ 1.2.3 1.2.4 ] + [ 1.2.3- 1.2.4- ] EOI [1.2.3 1.2.4] (1.2.3 1.2.4) - [1.2.3 1.2.4] + [1.2.3- 1.2.4-] EOE : invalid @@ -234,6 +248,10 @@ : open-end : $* <'[1.2.3 1.2.3)' 2>'equal version endpoints not closed' == 1 + + : earliest-prerelease + : + $* <'[1.2.3- 1.2.3-]' 2>'equal version endpoints are earliest' == 1 } } @@ -248,16 +266,20 @@ <= 1.2.3 > 1.2.3 < 1.2.3 - <=1.2.3 - <1.2.3 + >=1.2.3- + <=1.2.3- + >1.2.3- + <1.2.3- EOI == 1.2.3 >= 1.2.3 <= 1.2.3 > 1.2.3 < 1.2.3 - <= 1.2.3 - < 1.2.3 + >= 1.2.3- + <= 1.2.3- + > 1.2.3- + < 1.2.3- EOE : invalid @@ -265,6 +287,10 @@ { $* <'>=' 2>'no version' == 1 : no-version + : eq-earliest + : + $* <'==1.2.3-' 2>"invalid version: 'a' or 'b' expected in pre-release" == 1 + : junk : $* <'>= 1.2.3-a.1.1.ads@' 2>'invalid version: junk after version' == 1 |