From a6bf026d143b559ac0358dfd4b89f317901fd02e Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 30 Aug 2019 20:55:55 +0300 Subject: Make version revision optional --- libbpkg/manifest.cxx | 62 +- libbpkg/manifest.hxx | 47 +- tests/manifest/testscript | 1166 +++++++++++++++++++------------------- tests/package-version/driver.cxx | 23 +- 4 files changed, 678 insertions(+), 620 deletions(-) diff --git a/libbpkg/manifest.cxx b/libbpkg/manifest.cxx index bba616f..19f24ab 100644 --- a/libbpkg/manifest.cxx +++ b/libbpkg/manifest.cxx @@ -162,7 +162,7 @@ namespace bpkg version (uint16_t e, std::string u, optional l, - uint16_t r, + optional r, uint32_t i) : epoch (e), upstream (move (u)), @@ -170,11 +170,14 @@ namespace bpkg revision (r), iteration (i), canonical_upstream ( - data_type (upstream.c_str (), data_type::parse::upstream). + data_type (upstream.c_str (), + data_type::parse::upstream, + false /* fold_zero_revision */). canonical_upstream), canonical_release ( data_type (release ? release->c_str () : nullptr, - data_type::parse::release). + data_type::parse::release, + false /* fold_zero_revision */). canonical_release) { // Check members constrains. @@ -187,7 +190,7 @@ namespace bpkg if (!release || !release->empty ()) throw invalid_argument ("not-empty release for empty version"); - if (revision != 0) + if (revision) throw invalid_argument ("revision for empty version"); if (iteration != 0) @@ -196,7 +199,7 @@ namespace bpkg // Empty release signifies the earliest possible release. Revision and/or // iteration are meaningless in such a context. // - else if (release && release->empty () && (revision != 0 || iteration != 0)) + else if (release && release->empty () && (revision || iteration != 0)) throw invalid_argument ("revision for earliest possible release"); } @@ -251,8 +254,11 @@ namespace bpkg } version::data_type:: - data_type (const char* v, parse pr): revision (0) + data_type (const char* v, parse pr, bool fold_zero_rev) { + if (fold_zero_rev) + assert (pr == parse::full); + // Otherwise compiler gets confused with string() member. // using std::string; @@ -418,7 +424,10 @@ namespace bpkg if (lnn >= cb) // Contains non-digits. bad_arg ("revision should be 2-byte unsigned integer"); - revision = uint16 (cb, "revision"); + std::uint16_t rev (uint16 (cb, "revision")); + + if (rev != 0 || !fold_zero_rev) + revision = rev; } else if (cb != p) { @@ -489,7 +498,7 @@ namespace bpkg canonical_upstream.empty () && canonical_release.empty ()) { - assert (revision == 0); // Can't happen if through all previous checks. + assert (!revision); // Can't happen if through all previous checks. bad_arg ("empty version"); } } @@ -534,10 +543,10 @@ namespace bpkg if (!ignore_revision) { - if (revision != 0) + if (revision) { v += '+'; - v += to_string (revision); + v += to_string (*revision); } if (!ignore_iteration && iteration != 0) @@ -646,7 +655,7 @@ namespace bpkg if (mnv != "$") try { - min_version = version (mnv); + min_version = version (mnv, false /* fold_zero_revision */); } catch (const invalid_argument& e) { @@ -674,7 +683,7 @@ namespace bpkg if (mxv != "$") try { - max_version = version (mxv); + max_version = version (mxv, false /* fold_zero_revision */); } catch (const invalid_argument& e) { @@ -735,6 +744,11 @@ namespace bpkg { assert (vc.min_version && vc.max_version); + // Note that standard_version::string() folds the zero revision. + // However, that's ok since the shortcut operator ~X.Y.Z+0 + // translates into [X.Y.Z+0 X.Y+1.0-) which covers the same versions + // set as [X.Y.Z X.Y+1.0-). + // *this = dependency_constraint ( version (vc.min_version->string ()), vc.min_open, @@ -789,7 +803,7 @@ namespace bpkg // version. // if (vs != "$") - v = version (vs); + v = version (vs, false /* fold_zero_revision */); switch (operation) { @@ -844,7 +858,19 @@ namespace bpkg // max version. // if (*min_version > *max_version && !mxe) - throw invalid_argument ("min version is greater than max version"); + { + // Handle the (X+Y X] and [X+Y X] corner cases (any revision of + // version X greater (or equal) than X+Y). Note that technically + // X+Y > X (see version::compare() for details). + // + // Also note that we reasonably fail for (X+Y X) and [X+Y X). + // + if (!(!max_open && + !max_version->revision && + max_version->compare (*min_version, + true /* ignore_revision */) == 0)) + throw invalid_argument ("min version is greater than max version"); + } if (*min_version == *max_version) { @@ -884,7 +910,7 @@ namespace bpkg v = version (v.epoch, move (v.upstream), move (v.release), - 0 /* revision */, + nullopt /* revision */, 0 /* iteration */); // Calculate effective constraint for a shortcut operator. @@ -1601,7 +1627,7 @@ namespace bpkg return email (move (v), move (c)); } - const version stub_version (0, "0", nullopt, 0, 0); + const version stub_version (0, "0", nullopt, nullopt, 0); static void parse_package_manifest ( @@ -1747,7 +1773,7 @@ namespace bpkg try { - m.version = version (move (v)); + m.version = version (v); } catch (const invalid_argument& e) { @@ -2104,7 +2130,7 @@ namespace bpkg // nv = move (*upstream_version); - if (m.version.compare (stub_version, true) == 0) + if (m.version.compare (stub_version, true /* ignore_revision */) == 0) bad_name ("upstream package version specified for a stub"); m.upstream_version = move (nv.value); diff --git a/libbpkg/manifest.hxx b/libbpkg/manifest.hxx index c0901e9..3d02e50 100644 --- a/libbpkg/manifest.hxx +++ b/libbpkg/manifest.hxx @@ -42,7 +42,13 @@ namespace bpkg const std::uint16_t epoch; const std::string upstream; const butl::optional release; - const std::uint16_t revision; + + // The absent revision semantics depends on the context the version object + // is used in. Normally, it is equivalent to zero revision but may have a + // special meaning, for example, denoting any package revision. + // + const butl::optional revision; + const std::uint32_t iteration; // Upstream part canonical representation. @@ -56,29 +62,37 @@ namespace bpkg // Create a special empty version. It is less than any other valid // version (and is conceptually equivalent to +0-0-). // - version (): epoch (0), release (""), revision (0), iteration (0) {} + version (): epoch (0), release (""), iteration (0) {} - // Throw std::invalid_argument if the passed string is not a valid - // version representation. + // By default, treat the zero revision as no revision. Throw + // std::invalid_argument if the passed string is not a valid version + // representation. // explicit - version (const std::string& v): version (v.c_str ()) {} + version (const std::string& v, bool fold_zero_revision = true) + : version (v.c_str (), fold_zero_revision) {} explicit - version (const char* v): version (data_type (v, data_type::parse::full)) {} + version (const char* v, bool fold_zero_revision = true) + : version (data_type (v, data_type::parse::full, fold_zero_revision)) + { + } // Create the version object from separate epoch, upstream, release, // revision, and iteration parts. // // Note that it is possible (and legal) to create the special empty - // version via this interface as version(0, string(), string(), 0, 0). + // version via this interface as version(0, string(), string(), nullopt, 0). // version (std::uint16_t epoch, std::string upstream, butl::optional release, - std::uint16_t revision, + butl::optional revision, std::uint32_t iteration); + std::uint16_t + effective_revision () const noexcept {return revision ? *revision : 0;} + version (version&&) = default; version (const version&) = default; version& operator= (version&&); @@ -145,7 +159,7 @@ namespace bpkg assert (!e || (epoch == 0 && release && release->empty () && - revision == 0 && iteration == 0)); + !revision && iteration == 0)); return e; } @@ -155,7 +169,7 @@ namespace bpkg { enum class parse {full, upstream, release}; - data_type (const char*, parse); + data_type (const char*, parse, bool fold_zero_revision); // Note that there is no iteration component as it can't be present in // the string representation passed to the ctor. @@ -163,7 +177,7 @@ namespace bpkg std::uint16_t epoch; std::string upstream; butl::optional release; - std::uint16_t revision; + butl::optional revision; std::string canonical_upstream; std::string canonical_release; }; @@ -305,6 +319,13 @@ namespace bpkg // `~$` (min endpoint is open) or `^$` (max endpoint is open). Note that // equal endpoints can never be both open. // + // An absent endpoint version revision has the 'any revision' meaning and + // so translates into the effective revision differently, depending on the + // range endpoint side and openness: + // + // [X Y) == [X+0 Y+0) + // (X Y] == (X+max Y+max] + // class LIBBPKG_EXPORT dependency_constraint { public: @@ -313,11 +334,15 @@ namespace bpkg bool min_open; bool max_open; + // Preserve the zero endpoint version revisions (see above for details). + // + explicit dependency_constraint (const std::string&); dependency_constraint (butl::optional min_version, bool min_open, butl::optional max_version, bool max_open); + explicit dependency_constraint (const version& v) : dependency_constraint (v, false, v, false) {} diff --git a/tests/manifest/testscript b/tests/manifest/testscript index 9406a2a..2af195d 100644 --- a/tests/manifest/testscript +++ b/tests/manifest/testscript @@ -2,294 +2,385 @@ # copyright : Copyright (c) 2014-2019 Code Synthesis Ltd # license : MIT; see accompanying LICENSE file -: packages +: package : { + test.options += -p + : name : { : valid : - $* -pp <>EOF + $* <>EOF : 1 - sha256sum: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - : name: libfoo.c++-2 version: 2.0.0 summary: Modern C++ parser license: LGPLv2 url: http://www.example.org/projects/libfoo/ email: libfoo-users@example.org - location: libfoo.c++-2-2.0.0.tar.bz2 - sha256sum: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EOF - : invalid + : short : - { - : short - : - $* -pp <'stdin:4:7: error: invalid package name: length is less than two characters' != 0 - : 1 - sha256sum: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - : - name: b - EOI + $* <'stdin:2:7: error: invalid package name: length is less than two characters' != 0 + : 1 + name: b + EOI - : illegal - : - $* -pp <'stdin:4:7: error: invalid package name: illegal name' != 0 - : 1 - sha256sum: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - : - name: com3 - EOI + : illegal + : + $* <'stdin:2:7: error: invalid package name: illegal name' != 0 + : 1 + name: com3 + EOI + + : illegal-first-char + : + $* <'stdin:2:7: error: invalid package name: illegal first character (must be alphabetic)' != 0 + : 1 + name: 2b + EOI + + : illegal-last-char + : + $* <'stdin:2:7: error: invalid package name: illegal last character (must be alphabetic, digit, or plus)' != 0 + : 1 + name: foo_ + EOI + + : illegal-char + : + $* <'stdin:2:7: error: invalid package name: illegal character' != 0 + : 1 + name: foo'bar + EOI + } + + : upstream-version + : + { + : valid + : + $* <>EOF + : 1 + name: libfoo + version: 2.0.0 + upstream-version: 0.28.0.abc.15 + summary: Modern C++ parser + license: LGPLv2 + description: libfoo is a very modern C++ XML parser. + EOF + + : duplicate + : + $* <>EOE != 0 + : 1 + name: libfoo + version: 2.0.0 + upstream-version: 0.28.0.abc.15 + summary: Modern C++ parser + license: LGPLv2 + description: libfoo is a very modern C++ XML parser. + upstream-version: 0.28.0.abc.15 + EOI + stdin:8:1: error: upstream package version redefinition + EOE + + : stub + : + $* <>EOE != 0 + : 1 + name: libfoo + version: 0+1 + upstream-version: 0.28.0.abc.15 + summary: Modern C++ parser + license: LGPLv2 + description: libfoo is a very modern C++ XML parser. + EOI + stdin:4:1: error: upstream package version specified for a stub + EOE + } + + : topics + : + { + : valid + : + $* <>EOF + : 1 + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + topics: c++ library, foo library, libfoo + EOF + + : too-many + : + $* <>EOE != 0 + : 1 + topics: c++, library, lib, foo, libfoo, libbar + EOI + stdin:2:9: error: up to five topics allowed + EOE + } + + : keywords + : + { + : valid + : + $* <>EOF + : 1 + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + keywords: c++ library lib foo libfoo + EOF + + : redefinition + : + $* <>EOE != 0 + : 1 + keywords: c++ library lib foo libfoo + keywords: c++ library lib foo libfoo + EOI + stdin:3:1: error: package keywords redefinition + EOE + + : too-many + : + $* <>EOE != 0 + : 1 + keywords: c++ library lib foo libfoo libbar + EOI + stdin:2:11: error: up to five keywords allowed + EOE - : first-char + : empty + : + $* <>EOE != 0 + : 1 + keywords: + EOI + stdin:2:10: error: empty package keywords specification + EOE + } + + : tags + : + { + : truncate + : + $* <>EOO + : 1 + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + tags: c++, library, lib, foo, libfoo, libbar + EOI + : 1 + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + keywords: c++ library lib foo libfoo + EOO + + : with-space + : + $* <>EOE != 0 + : 1 + tags: c++ library, lib, foo, libfoo + EOI + stdin:2:7: error: only single-word tags allowed + EOE + } + + : description-file + : + { + : absolute-path + : + $* <>~%EOE% != 0 + : 1 + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + description-file: /README + EOI + %( + stdin:6:19: error: package description-file path is absolute + %| + stdin:6:19: error: invalid package description file: invalid filesystem path + %) + EOE + } + + : description-type + : + { + : absent + : + $* <>EOF + : 1 + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + description: libfoo is a very modern C++ XML parser. + EOF + + : not-text + : + $* <>EOE != 0 + : 1 + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + description: libfoo is a very modern C++ XML parser. + description-type: image/gif + EOI + stdin:7:19: error: invalid package description type: text type expected + EOE + + : deducing + : + { + : fail : - $* -pp <'stdin:4:7: error: invalid package name: illegal first character (must be alphabetic)' != 0 + $* <>EOE != 0 : 1 - sha256sum: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - : - name: 2b + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + description-file: README.rtf EOI + stdin:6:19: error: invalid package description file: unknown text type + EOE - : last-char + : ignore-unknown : - $* -pp <'stdin:4:7: error: invalid package name: illegal last character (must be alphabetic, digit, or plus)' != 0 + $* -i <>EOF : 1 - sha256sum: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - : - name: foo_ - EOI + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + description-file: README.rtf + EOF + } - : char + : unknown + : + { + : fail : - $* -pp <'stdin:4:7: error: invalid package name: illegal character' != 0 + $* <>EOE != 0 : 1 - sha256sum: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - : - name: foo'bar + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + description: libfoo is a very modern C++ XML parser. + description-type: text/markdowns EOI + stdin:7:19: error: invalid package description type: unknown text type + EOE - : dependency + : ignore : - $* -pp <'stdin:8:10: error: invalid prerequisite package name: length is less than two characters' != 0 + $* -i <>EOF : 1 - sha256sum: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - : - name: foo + name: libfoo version: 2.0.0 summary: Modern C++ parser license: LGPLv2 - depends: b - EOI + description: libfoo is a very modern C++ XML parser. + description-type: text/markdowns + EOF + } - : dependency-constraint + : plain + : + { + : valid : - $* -pp <'stdin:8:10: error: $ not allowed' != 0 + $* <>EOF : 1 - sha256sum: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - : - name: foo + name: libfoo version: 2.0.0 summary: Modern C++ parser license: LGPLv2 - depends: bar == $ - EOI + description: libfoo is a very modern C++ XML parser. + description-type: text/plain + EOF - : dependency-constraint-version + : invalid : - $* -p -c <'stdin:6:10: error: invalid dependency constraint: min version is greater than max version' != 0 + $* <>EOE != 0 : 1 - name: foo + name: libfoo version: 2.0.0 summary: Modern C++ parser license: LGPLv2 - depends: bar [$ 1.0.0] + description: libfoo is a very modern C++ XML parser. + description-type: text/plain; EOI + stdin:7:19: error: invalid package description type: missing '=' + EOE } - } - : pkg - : - { - : manifest + : markdown : { - test.options += -p - - : invalid + : default : - { - : description-file - : - $* <>~%EOE% != 0 - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description-file: /README - EOI - %( - stdin:6:19: error: package description-file path is absolute - %| - stdin:6:19: error: invalid package description file: invalid filesystem path - %) - EOE - - : url - : - { - : no-scheme - : - $* <>EOE != 0 - : 1 - src-url: libfoo - EOI - stdin:2:10: error: invalid src url: no scheme - EOE - - : rootless - : - $* <>EOE != 0 - : 1 - src-url: pkcs11:libfoo - EOI - stdin:2:10: error: invalid src url: rootless URL - EOE - - : local - : - $* <>EOE != 0 - : 1 - src-url: file:/libfoo/bar - EOI - stdin:2:10: error: invalid src url: local URL - EOE - - : authority-absent - : - $* <>EOE != 0 - : 1 - src-url: http:/libfoo/bar - EOI - stdin:2:10: error: invalid src url: no authority - EOE - - : authority-empty - : - $* <>EOE != 0 - : 1 - src-url: http:///libfoo/bar - EOI - stdin:2:10: error: invalid src url: no authority - EOE - } - } + $* <>EOF + : 1 + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + description: libfoo is a very modern C++ XML parser. + description-type: text/markdown + EOF - : complete + : gfm : - { - test.options += -c - - : final - : - $* <>EOO - : 1 - name: foo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - depends: bar == $ | libbaz ~$ | libbox ^$ | libfox [1.0 $) - EOI - : 1 - name: foo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - depends: bar == 2.0.0 | libbaz ~2.0.0 | libbox ^2.0.0 | libfox [1.0 2.0.0) - EOO - - : non-standard - : - $* <>EOO - : 1 - name: foo - version: 2.0.0-x - summary: Modern C++ parser - license: LGPLv2 - depends: bar == $ | libfox [1.0 $) - EOI - : 1 - name: foo - version: 2.0.0-x - summary: Modern C++ parser - license: LGPLv2 - depends: bar == 2.0.0-x | libfox [1.0 2.0.0-x) - EOO - - : non-standard-shortcut - : - $* <>EOE != 0 - : 1 - name: foo - version: 2.0.0-x - summary: Modern C++ parser - license: LGPLv2 - depends: bar ~$ - EOI - stdin:6:10: error: invalid dependency constraint: dependent version is not standard - EOE - - : latest-snapshot - : - $* <>EOO - : 1 - name: foo - version: 2.0.0-a.0.z - summary: Modern C++ parser - license: LGPLv2 - depends: bar == $ | libbaz ~$ | libbox ^$ | libfox [1.0 $) - EOI - : 1 - name: foo - version: 2.0.0-a.0.123 - summary: Modern C++ parser - license: LGPLv2 - depends: bar == 2.0.0-a.0.123 | libbaz [2.0.0-a.0.1 2.0.0-a.1) | libbox\ - [2.0.0-a.0.1 2.0.0-a.1) | libfox [1.0 2.0.0-a.0.123) - EOO - - } + $* <>EOF + : 1 + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + description: libfoo is a very modern C++ XML parser. + description-type: text/markdown; variant=GFM + EOF - : incomplete + : common-mark : $* <>EOF : 1 - name: foo + name: libfoo version: 2.0.0 summary: Modern C++ parser license: LGPLv2 - depends: bar == $ | libbaz ~$ | libbox ^$ | libfox [1.0 $) + description: libfoo is a very modern C++ XML parser. + description-type: text/markdown; variant=CommonMark EOF - : description-type + : invalid-variant : { - : absent - : - $* <>EOF - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description: libfoo is a very modern C++ XML parser. - EOF - - : not-text + : fail : $* <>EOE != 0 : 1 @@ -298,364 +389,251 @@ summary: Modern C++ parser license: LGPLv2 description: libfoo is a very modern C++ XML parser. - description-type: image/gif + description-type: text/markdown; variant=Original EOI - stdin:7:19: error: invalid package description type: text type expected + stdin:7:19: error: invalid package description type: unknown text type EOE - : deducing - : - { - : fail - : - $* <>EOE != 0 - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description-file: README.rtf - EOI - stdin:6:19: error: invalid package description file: unknown text type - EOE - - : ignore-unknown - : - $* -i <>EOF - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description-file: README.rtf - EOF - } - - : unknown - : - { - : fail - : - $* <>EOE != 0 - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description: libfoo is a very modern C++ XML parser. - description-type: text/markdowns - EOI - stdin:7:19: error: invalid package description type: unknown text type - EOE - - : ignore - : - $* -i <>EOF - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description: libfoo is a very modern C++ XML parser. - description-type: text/markdowns - EOF - } - - : plain - : - { - : valid - : - $* <>EOF - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description: libfoo is a very modern C++ XML parser. - description-type: text/plain - EOF - - : invalid - : - $* <>EOE != 0 - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description: libfoo is a very modern C++ XML parser. - description-type: text/plain; - EOI - stdin:7:19: error: invalid package description type: missing '=' - EOE - } - - : markdown - : - { - : default - : - $* <>EOF - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description: libfoo is a very modern C++ XML parser. - description-type: text/markdown - EOF - - : gfm - : - $* <>EOF - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description: libfoo is a very modern C++ XML parser. - description-type: text/markdown; variant=GFM - EOF - - : common-mark - : - $* <>EOF - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description: libfoo is a very modern C++ XML parser. - description-type: text/markdown; variant=CommonMark - EOF - - : invalid-variant - : - { - : fail - : - $* <>EOE != 0 - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description: libfoo is a very modern C++ XML parser. - description-type: text/markdown; variant=Original - EOI - stdin:7:19: error: invalid package description type: unknown text type - EOE - - : ignore - : - $* -i <>EOF - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description: libfoo is a very modern C++ XML parser. - description-type: text/markdown; variant=Original - EOF - } - - : invalid-parameter - : - { - : fail - : - $* <>EOE != 0 - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description: libfoo is a very modern C++ XML parser. - description-type: text/markdown; variants=GFM - EOI - stdin:7:19: error: invalid package description type: unknown text type - EOE - - : ignore - : - $* -i <>EOF - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - description: libfoo is a very modern C++ XML parser. - description-type: text/markdown; variants=GFM - EOF - } - } - } - - : builds - : - { - : invalid - : - { - : empty - : - $* <"stdin:2:9: error: invalid package builds: class expression separator ':' expected" != 0 - : 1 - builds: default -gcc - EOI - } - } - - : upstream-version - : - { - : valid + : ignore : - $* <>EOF + $* -i <>EOF : 1 name: libfoo version: 2.0.0 - upstream-version: 0.28.0.abc.15 summary: Modern C++ parser license: LGPLv2 description: libfoo is a very modern C++ XML parser. + description-type: text/markdown; variant=Original EOF + } - : duplicate + : invalid-parameter + : + { + : fail : $* <>EOE != 0 : 1 name: libfoo version: 2.0.0 - upstream-version: 0.28.0.abc.15 summary: Modern C++ parser license: LGPLv2 description: libfoo is a very modern C++ XML parser. - upstream-version: 0.28.0.abc.15 + description-type: text/markdown; variants=GFM EOI - stdin:8:1: error: upstream package version redefinition + stdin:7:19: error: invalid package description type: unknown text type EOE - : stub + : ignore : - $* <>EOE != 0 + $* -i <>EOF : 1 name: libfoo - version: 0+1 - upstream-version: 0.28.0.abc.15 + version: 2.0.0 summary: Modern C++ parser license: LGPLv2 description: libfoo is a very modern C++ XML parser. - EOI - stdin:4:1: error: upstream package version specified for a stub - EOE + description-type: text/markdown; variants=GFM + EOF } + } + } - : keywords - : - { - : valid - : - $* <>EOF - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - keywords: c++ library lib foo libfoo - EOF + : src-url + : + { + : no-scheme + : + $* <>EOE != 0 + : 1 + src-url: libfoo + EOI + stdin:2:10: error: invalid src url: no scheme + EOE - : redefinition - : - $* <>EOE != 0 - : 1 - keywords: c++ library lib foo libfoo - keywords: c++ library lib foo libfoo - EOI - stdin:3:1: error: package keywords redefinition - EOE + : rootless + : + $* <>EOE != 0 + : 1 + src-url: pkcs11:libfoo + EOI + stdin:2:10: error: invalid src url: rootless URL + EOE - : too-many - : - $* <>EOE != 0 - : 1 - keywords: c++ library lib foo libfoo libbar - EOI - stdin:2:11: error: up to five keywords allowed - EOE + : local + : + $* <>EOE != 0 + : 1 + src-url: file:/libfoo/bar + EOI + stdin:2:10: error: invalid src url: local URL + EOE - : empty - : - $* <>EOE != 0 - : 1 - keywords: - EOI - stdin:2:10: error: empty package keywords specification - EOE - } + : authority-absent + : + $* <>EOE != 0 + : 1 + src-url: http:/libfoo/bar + EOI + stdin:2:10: error: invalid src url: no authority + EOE + + : authority-empty + : + $* <>EOE != 0 + : 1 + src-url: http:///libfoo/bar + EOI + stdin:2:10: error: invalid src url: no authority + EOE + } + + : builds + : + { + : empty + : + $* <"stdin:2:9: error: invalid package builds: class expression separator ':' expected" != 0 + : 1 + builds: default -gcc + EOI + } + + : dependency + : + { + : short-name + : + $* <'stdin:6:10: error: invalid prerequisite package name: length is less than two characters' != 0 + : 1 + name: foo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + depends: b + EOI + + : invalid-version-range + : + $* -c <'stdin:6:10: error: invalid dependency constraint: min version is greater than max version' != 0 + : 1 + name: foo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + depends: bar [$ 1.0.0] + EOI + + : corner-case + : + $* <>EOF + : 1 + name: foo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + depends: bar [1.0.0+2 1.0.0] + EOF - : tags + : complete + : + { + test.options += -c + + : final : - { - : truncate - : - $* <>EOO - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - tags: c++, library, lib, foo, libfoo, libbar - EOI - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - keywords: c++ library lib foo libfoo - EOO + $* <>EOO + : 1 + name: foo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + depends: bar == $ | libbaz ~$ | libbox ^$ | libfox [1.0 $) + EOI + : 1 + name: foo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + depends: bar == 2.0.0 | libbaz ~2.0.0 | libbox ^2.0.0 | libfox [1.0 2.0.0) + EOO - : with-space - : - $* <>EOE != 0 - : 1 - tags: c++ library, lib, foo, libfoo - EOI - stdin:2:7: error: only single-word tags allowed - EOE - } + : non-standard + : + $* <>EOO + : 1 + name: foo + version: 2.0.0-x + summary: Modern C++ parser + license: LGPLv2 + depends: bar == $ | libfox [1.0 $) + EOI + : 1 + name: foo + version: 2.0.0-x + summary: Modern C++ parser + license: LGPLv2 + depends: bar == 2.0.0-x | libfox [1.0 2.0.0-x) + EOO - : topics + : non-standard-shortcut : - { - : valid - : - $* <>EOF - : 1 - name: libfoo - version: 2.0.0 - summary: Modern C++ parser - license: LGPLv2 - topics: c++ library, foo library, libfoo - EOF + $* <>EOE != 0 + : 1 + name: foo + version: 2.0.0-x + summary: Modern C++ parser + license: LGPLv2 + depends: bar ~$ + EOI + stdin:6:10: error: invalid dependency constraint: dependent version is not standard + EOE + + : latest-snapshot + : + $* <>EOO + : 1 + name: foo + version: 2.0.0-a.0.z + summary: Modern C++ parser + license: LGPLv2 + depends: bar == $ | libbaz ~$ | libbox ^$ | libfox [1.0 $) + EOI + : 1 + name: foo + version: 2.0.0-a.0.123 + summary: Modern C++ parser + license: LGPLv2 + depends: bar == 2.0.0-a.0.123 | libbaz [2.0.0-a.0.1 2.0.0-a.1) | libbox\ + [2.0.0-a.0.1 2.0.0-a.1) | libfox [1.0 2.0.0-a.0.123) + EOO - : too-many - : - $* <>EOE != 0 - : 1 - topics: c++, library, lib, foo, libfoo, libbar - EOI - stdin:2:9: error: up to five topics allowed - EOE - } } - : manifest-list + : incomplete : - : Roundtrip the pkg package manifest list. + $* <>EOF + : 1 + name: foo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + depends: bar == $ | libbaz ~$ | libbox ^$ | libfox [1.0 $) + EOF + } +} + +: package-list +: +{ + : pkg + : + { + test.options += -pp + + : roundtrip : - $* -pp <>EOF + $* <>EOF : 1 sha256sum: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 : @@ -725,22 +703,37 @@ location: libbaz/libbaz-+2-3.4A.5+3.tar.gz sha256sum: b5b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EOF + + : dependency + : + { + : incomplete + : + $* <'stdin:8:10: error: $ not allowed' != 0 + : 1 + sha256sum: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + : + name: foo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + depends: bar == $ + EOI + } } : dir : { + test.options += -dp + : empty : - : Roundtrip an empty dir package manifest list. - : - $* -gp <"" >:"" + $* <"" >:"" : non-empty : - : Roundtrip the dir package manifest list. - : - $* -gp <>EOF + $* <>EOF : 1 location: hello/ : @@ -749,7 +742,7 @@ : duplicate : - $* -gp <'stdin:5:1: error: duplicate package manifest' != 0 + $* <'stdin:5:1: error: duplicate package manifest' != 0 : 1 location: hello/ : @@ -762,9 +755,11 @@ : git : { + test.options += -gp + : fragment : - $* -gp <>EOF + $* <>EOF : 1 location: hello/ fragment: ca602c2d46b0dca7a9ebc856871767b0ba6b74f3 @@ -775,39 +770,17 @@ } } -: repositories +: repository-list : { - : base-manifest-redefinition - : - $* -pr <'stdin:3:1: error: base repository manifest redefinition' != 0 - : 1 - url: http://cppget.org - : - url: http://cppget.org - EOI - - : no-base - : - $* -pr <>EOO - : 1 - location: http://pkg.example.org/1/math - type: pkg - role: prerequisite - : - location: ../stable - type: pkg - role: complement - EOO - : pkg : { - : manifest - : - : Roundtrip the pkg repository manifest list. + test.options += -pr + + : roundtrip : - $* -pr <>EOF + $* <>EOF : 1 location: http://pkg.example.org/1/math type: pkg @@ -858,7 +831,7 @@ : prerequisite-type : - $* -pr <>EOO + $* <>EOO : 1 url: http://cppget.org : @@ -904,16 +877,38 @@ trust: 37:CE:2C:A5:1D:CF:93:81:D7:07:46:AD:66:B3:C3:90:83:B8:96:9E:34:F0:E7:B\ 3:A2:B0:6C:EF:66:A4:BE:65 EOO + + : no-base + : + $* <>EOO + : 1 + location: http://pkg.example.org/1/math + type: pkg + role: prerequisite + : + location: ../stable + type: pkg + role: complement + EOO + + : base-manifest-redefinition + : + $* <'stdin:3:1: error: base repository manifest redefinition' != 0 + : 1 + url: http://cppget.org + : + url: http://cppget.org + EOI } : git : { - : manifest - : - : Roundtrip the git repository manifest list. + test.options += -gr + + : roundtrip : - $* -gr <>EOF + $* <>EOF : 1 location: http://example.org/math.git#master type: git @@ -936,7 +931,7 @@ : fragment : - $* -gr <>EOF + $* <>EOF : 1 location: http://example.org/math.git#master type: git @@ -972,7 +967,7 @@ : prerequisite-type : - $* -gr <>EOO + $* <>EOO : 1 location: http://example.org/math.git#master role: prerequisite @@ -1013,11 +1008,11 @@ : dir : { - : manifest - : - : Roundtrip the dir repository manifest list. + test.options += -dr + + : roundtrip : - $* -dr <>EOF + $* <>EOF : 1 location: ../stable type: dir @@ -1027,7 +1022,7 @@ : prerequisite-with-fragment : - $* -dr <>EOE != 0 + $* <>EOE != 0 : 1 location: ../stable.git#stable type: dir @@ -1039,13 +1034,10 @@ } } - : signature : -: Roundtrip the signature manifest. -: { - : manifest + : roundtrip : $* -s <>EOF : 1 diff --git a/tests/package-version/driver.cxx b/tests/package-version/driver.cxx index e81115a..5cf7e09 100644 --- a/tests/package-version/driver.cxx +++ b/tests/package-version/driver.cxx @@ -123,6 +123,7 @@ namespace bpkg assert (bad_version ("1-a.00000000000000000")); // Same. assert (bad_version (0, "1", "", 1)); // Revision for empty release. + assert (bad_version (0, "1", "", 0)); // Same. assert (bad_version (1, "+1-1.1", "", 2)); // Epoch in upstream. assert (bad_version (1, "1.1-1", "", 2)); // Release in upstream. assert (bad_version (1, "1.1+1", "", 2)); // Revision in upstream. @@ -133,6 +134,7 @@ namespace bpkg assert (bad_version (1, "", "", 0)); // Unexpected epoch. assert (bad_version (0, "", "1", 0)); // Unexpected release. assert (bad_version (0, "", "", 1)); // Unexpected revision. + assert (bad_version (0, "", "", 0)); // Same. assert (bad_version (0, "", "", 0, 1)); // Unexpected iteration. { @@ -243,12 +245,24 @@ namespace bpkg assert (test_constructor (v)); } { + version v ("+10-B"); + assert (v.string () == "+10-B"); + assert (v.canonical_upstream == "b"); + assert (test_constructor (v)); + } + { version v ("+10-B+0"); assert (v.string () == "+10-B"); assert (v.canonical_upstream == "b"); assert (test_constructor (v)); } { + version v ("+10-B+0", false /* fold_zero_revision */); + assert (v.string () == "+10-B+0"); + assert (v.canonical_upstream == "b"); + assert (test_constructor (v)); + } + { version v ("+3-1A.31.0.4.0+7"); assert (v.string () == "+3-1A.31.0.4.0+7"); assert (v.canonical_upstream == @@ -298,7 +312,7 @@ namespace bpkg assert (test_constructor (v)); } { - version v (2, "1", string (), 0, 0); + version v (2, "1", string (), nullopt, 0); assert (v.string () == "+2-1-"); assert (v.release && v.release->empty ()); assert (v.canonical_release.empty ()); @@ -311,7 +325,8 @@ namespace bpkg assert (v.string (true, false) == "+3-2.0"); assert (v.string (false, true) == "+3-2.0+3"); - assert (version (3, "2.0", nullopt, 0, 1).string () == "+3-2.0#1"); + assert (version (3, "2.0", nullopt, nullopt, 1).string () == "+3-2.0#1"); + assert (version (3, "2.0", nullopt, 0, 1).string () == "+3-2.0+0#1"); assert (version (3, "2.0", nullopt, 1, 0).string () == "+3-2.0+1"); } @@ -363,8 +378,8 @@ namespace bpkg assert (version ("1.1.1a+1") < version ("1.1.1b")); assert (version (1, "2.0", nullopt, 3, 0) == version ("+1-2+3")); - assert (version (1, "2.0", string (), 0, 0) == version ("+1-2-")); - assert (version (0, "", string (), 0, 0) == version ()); + assert (version (1, "2.0", string (), nullopt, 0) == version ("+1-2-")); + assert (version (0, "", string (), nullopt, 0) == version ()); assert (version (1, "2.0", nullopt, 3, 4).compare ( version (1, "2.0", nullopt, 3, 4)) == 0); -- cgit v1.1