From f8851063035424e441259af9f26c28af090542b4 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 29 Jan 2019 16:08:35 +0300 Subject: Add package_manifest constructor that translates package version Also complete ~$/^$ dependency constraints using standard_version_constraint class. --- libbpkg/manifest.cxx | 139 +++++++++++++++++++++------------------------------ 1 file changed, 58 insertions(+), 81 deletions(-) (limited to 'libbpkg/manifest.cxx') diff --git a/libbpkg/manifest.cxx b/libbpkg/manifest.cxx index 2f98b4c..79e2977 100644 --- a/libbpkg/manifest.cxx +++ b/libbpkg/manifest.cxx @@ -855,10 +855,10 @@ namespace bpkg // The dependent package version can't be empty or earliest. // if (v.empty ()) - throw invalid_argument ("empty version"); + throw invalid_argument ("dependent version is empty"); if (v.release && v.release->empty ()) - throw invalid_argument ("earliest version"); + throw invalid_argument ("dependent version is earliest"); // For the more detailed description of the following semantics refer to // the depends value documentation. @@ -882,79 +882,27 @@ namespace bpkg string vs (v.string ()); - if (optional sv = parse_standard_version (vs)) - try - { - char op (min_open ? '~' : '^'); - standard_version_constraint vc (op + vs); - - // The shortcut operators' representation is a range. - // - assert (vc.min_version && vc.max_version); - - standard_version& mnv (*vc.min_version); - standard_version& mxv (*vc.max_version); - - // For a release adjust the min version endpoint, setting its patch to - // zero. For ^ also set the minor version to zero, unless the major - // version is zero (reduced to ~). - // - if (sv->release ()) - { - mnv = standard_version ( - sv->epoch, - sv->major (), - op == '^' && sv->major () != 0 ? 0 : sv->minor (), - 0 /* patch */); - } - // - // For a final pre-release or a patch snapshot we check if there has - // been a compatible final release (patch is not zero for ~ and - // minor/patch are not zero for ^). If that's the case, then fallback - // to the release case and start the range from the first alpha - // otherwise. - // - else if (sv->final () || (sv->snapshot () && sv->patch () != 0)) - { - mnv = standard_version ( - sv->epoch, - sv->major (), - op == '^' && sv->major () != 0 ? 0 : sv->minor (), - 0 /* patch */, - sv->patch () != 0 || (op == '^' && sv->minor () != 0) - ? 0 - : 1 /* pre-release */); - } - // - // For a major/minor snapshot we assume that all the packages are - // developed in the lockstep and convert the constraint range to - // represent this "snapshot series". - // - else - { - assert (sv->snapshot () && sv->patch () == 0); + // Note that a stub dependent is not allowed for the shortcut operator. + // However, we allow it here to fail later (in + // standard_version_constraint()) with a more precise description. + // + optional sv ( + parse_standard_version (vs, standard_version::allow_stub)); - uint16_t pr (*sv->pre_release ()); + if (!sv) + throw invalid_argument ("dependent version is not standard"); - mnv = standard_version (sv->epoch, - sv->major (), - sv->minor (), - 0 /* patch */, - pr, - 1 /* snapshot_sn */, - "" /* snapshot_id */); + standard_version_constraint vc (min_open ? "~$" : "^$", *sv); - // Note: the max version endpoint is already open. - // - mxv = standard_version (sv->epoch, - sv->major (), - sv->minor (), - 0 /* patch */, - pr + 1); - } + try + { + assert (vc.min_version && vc.max_version); - return dependency_constraint (version (mnv.string ()), vc.min_open, - version (mxv.string ()), vc.max_open); + return dependency_constraint ( + version (vc.min_version->string ()), + vc.min_open, + version (vc.max_version->string ()), + vc.max_open); } catch (const invalid_argument&) { @@ -962,8 +910,6 @@ namespace bpkg // assert (false); } - - throw invalid_argument (vs + " is not a standard version"); } // Calculate effective constraint for a range. @@ -1448,12 +1394,14 @@ namespace bpkg // pkg_package_manifest // static void - parse_package_manifest (parser& p, - name_value nv, - bool iu, - bool cd, - package_manifest_flags fl, - package_manifest& m) + parse_package_manifest ( + parser& p, + name_value nv, + const function& tf, + bool iu, + bool cd, + package_manifest_flags fl, + package_manifest& m) { auto bad_name ([&p, &nv](const string& d) { throw parsing (p.name (), nv.name_line, nv.name_column, d);}); @@ -1560,6 +1508,24 @@ namespace bpkg // if (m.version.release && m.version.release->empty ()) bad_value ("invalid package version release"); + + if (tf) + { + tf (m.version); + + // Re-validate the version after the translation. + // + // The following description will be confusing for the end user. + // However, they shouldn't ever see it unless the translation + // function is broken. + // + if (m.version.empty ()) + bad_value ("empty translated package version"); + + if (m.version.release && m.version.release->empty ()) + bad_value ("invalid translated package version " + + m.version.string () + ": earliest release"); + } } else if (n == "project") { @@ -2007,11 +1973,12 @@ namespace bpkg // package_manifest:: package_manifest (manifest_parser& p, + const function& tf, bool iu, bool cd, package_manifest_flags fl) { - parse_package_manifest (p, p.next (), iu, cd, fl, *this); + parse_package_manifest (p, p.next (), tf, iu, cd, fl, *this); // Make sure this is the end. // @@ -2023,12 +1990,22 @@ namespace bpkg package_manifest:: package_manifest (manifest_parser& p, + bool iu, + bool cd, + package_manifest_flags fl) + : package_manifest (p, function (), iu, cd, fl) + { + } + + package_manifest:: + package_manifest (manifest_parser& p, name_value nv, bool iu, bool cd, package_manifest_flags fl) { - parse_package_manifest (p, move (nv), iu, cd, fl, *this); + parse_package_manifest ( + p, move (nv), function (), iu, cd, fl, *this); } static const string description_file ("description-file"); -- cgit v1.1