From 2fb83c8eba765621106531e834fc1b0c2e3bd6b0 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Sat, 5 May 2018 15:38:42 +0300 Subject: Add support for dependency constraint shortcut operators --- libbpkg/manifest.cxx | 84 +++++++++++++++++++++++++++++++++++++++++++---- tests/manifest/testscript | 2 +- 2 files changed, 79 insertions(+), 7 deletions(-) diff --git a/libbpkg/manifest.cxx b/libbpkg/manifest.cxx index 9fb68f3..26039c7 100644 --- a/libbpkg/manifest.cxx +++ b/libbpkg/manifest.cxx @@ -20,6 +20,7 @@ // digit(), xdigit() #include #include +#include using namespace std; using namespace butl; @@ -607,8 +608,14 @@ namespace bpkg 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->release && min_version->release->empty ()) + throw invalid_argument ("equal version endpoints are earliest"); + } } } @@ -626,6 +633,36 @@ namespace bpkg if (*c.min_version == *c.max_version) return o << "== " << *c.min_version; + // If the range can potentially be represented as a range shortcut + // operator (^ or ~), having the [ ) + // form, then print it using the standard version constraint code. + // + if (!c.min_open && c.max_open) + { + if (optional mnv = + parse_standard_version (c.min_version->string (), + standard_version::allow_earliest)) + { + if (optional mxv = + parse_standard_version (c.max_version->string (), + standard_version::allow_earliest)) + try + { + return o << standard_version_constraint ( + move (*mnv), c.min_open, move (*mxv), c.max_open); + } + catch (const invalid_argument&) + { + // Invariants for both types of constraints are the same, so the + // conversion should never fail. + // + assert (false); + } + } + } + + // Print as a range. + // return o << (c.min_open ? '(' : '[') << *c.min_version << " " << *c.max_version << (c.max_open ? ')' : ']'); } @@ -1008,7 +1045,7 @@ namespace bpkg // Find end of name (ne). // - static const string cb ("=<>(["); + static const string cb ("=<>([~^"); for (char c; i != e && cb.find (c = *i) == string::npos; ++i) { if (!space (c)) @@ -1028,10 +1065,10 @@ namespace bpkg // dependency_constraint dc; const char* op (&*i); - char mnv (*op); - if (mnv == '(' || mnv == '[') + char c (*op); + if (c == '(' || c == '[') { - bool min_open (mnv == '('); + bool min_open (c == '('); string::size_type pos (lv.find_first_not_of (spaces, ++i - b)); if (pos == string::npos) @@ -1107,6 +1144,41 @@ namespace bpkg bad_value ( "unexpected text after prerequisite package version range"); } + else if (c == '~' || c == '^') // The shortcut operator. + { + // To be used in the shortcut operator the package version must + // be a standard version. + // + standard_version_constraint vc; + + try + { + vc = standard_version_constraint (op); + } + catch (const invalid_argument& e) + { + bad_value (string ("invalid dependency constraint: ") + + e.what ()); + } + + try + { + assert (vc.min_version && vc.max_version); + + dc = dependency_constraint ( + version (vc.min_version->string ()), + vc.min_open, + version (vc.max_version->string ()), + vc.max_open); + } + catch (const invalid_argument&) + { + // The standard version is a package version, so the conversion + // should never fail. + // + assert (false); + } + } else { // Version comparison notation. diff --git a/tests/manifest/testscript b/tests/manifest/testscript index 8bfe73a..4fa4c8d 100644 --- a/tests/manifest/testscript +++ b/tests/manifest/testscript @@ -35,7 +35,7 @@ package-email: libfoo-1.2.3+2@example.org; Bug reports are welcome. build-email: libfoo-builds@example.org; Mailing list for bbot notification\ emails. - depends: libz + depends: libz ~1.0.0 | libz ^2.0.0 depends: libgnutls <= 1.2.3 | libopenssl >= 2.3.4 depends: ? libboost-regex >= 1.52.0; Only if C++ compiler does not support\ C++11 . -- cgit v1.1