aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2023-01-12 21:51:27 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2023-01-16 10:29:03 +0300
commit8cb3544c88bdbd4da9f1f4962ad2fe9ff741ef2e (patch)
tree3bdfd85b2f2ee699a05bca0a6722f3e19b7c5aca
parent3251fe0b1793ee0b1897ec595f9a9e8f9f484a7b (diff)
Add *-name, *-version, and *-to-downstream-version package manifest values
-rw-r--r--libbpkg/manifest.cxx153
-rw-r--r--libbpkg/manifest.hxx63
-rw-r--r--tests/manifest/driver.cxx8
-rw-r--r--tests/manifest/testscript97
4 files changed, 269 insertions, 52 deletions
diff --git a/libbpkg/manifest.cxx b/libbpkg/manifest.cxx
index 57684df..119f894 100644
--- a/libbpkg/manifest.cxx
+++ b/libbpkg/manifest.cxx
@@ -3346,7 +3346,7 @@ namespace bpkg
const function<name_value ()>& next,
const function<package_manifest::translate_function>& translate,
bool iu,
- bool cd,
+ bool cv,
package_manifest_flags fl,
package_manifest& m)
{
@@ -3431,6 +3431,41 @@ namespace bpkg
}
};
+ // Note: the n argument is the distribution name length.
+ //
+ auto parse_distribution = [&bad_name, &bad_value] (string&& nm, size_t n,
+ string&& vl)
+ {
+ size_t p (nm.find ('-'));
+
+ // Distribution-related manifest value name always has a dash-starting
+ // suffix (-name, etc).
+ //
+ assert (p != string::npos);
+
+ if (p < n)
+ bad_name ("distribution name '" + string (nm, 0, n) + "' contains '-'");
+
+ if (vl.empty ())
+ bad_value ("empty package distribution value");
+
+ return distribution_name_value (move (nm), move (vl));
+ };
+
+ auto add_distribution = [&m, &bad_name] (distribution_name_value&& nv,
+ bool unique)
+ {
+ if (unique &&
+ find_if (m.distributions.begin (), m.distributions.end (),
+ [&nv] (const distribution_name_value& dnv)
+ {return dnv.name == nv.name;}) != m.distributions.end ())
+ {
+ bad_name ("package distribution value redefinition");
+ }
+
+ m.distributions.push_back (move (nv));
+ };
+
auto flag = [fl] (package_manifest_flags f)
{
return (fl & f) != package_manifest_flags::none;
@@ -3886,8 +3921,8 @@ namespace bpkg
m.build_constraints.push_back (
parse_build_constraint (nv, true /* exclusion */, name));
}
- else if ((n.size () > 13 &&
- n.compare (n.size () - 13, 13, "-build-config") == 0))
+ else if (n.size () > 13 &&
+ n.compare (n.size () - 13, 13, "-build-config") == 0)
{
auto vc (parser::split_comment (v));
@@ -3901,7 +3936,7 @@ namespace bpkg
bc.arguments = move (vc.first);
bc.comment = move (vc.second);
}
- else if ((n.size () > 7 && n.compare (n.size () - 7, 7, "-builds") == 0))
+ else if (n.size () > 7 && n.compare (n.size () - 7, 7, "-builds") == 0)
{
n.resize (n.size () - 7);
@@ -3910,8 +3945,8 @@ namespace bpkg
bc.builds.push_back (
parse_build_class_expr (nv, bc.builds.empty (), name));
}
- else if ((n.size () > 14 &&
- n.compare (n.size () - 14, 14, "-build-include") == 0))
+ else if (n.size () > 14 &&
+ n.compare (n.size () - 14, 14, "-build-include") == 0)
{
n.resize (n.size () - 14);
@@ -3920,8 +3955,8 @@ namespace bpkg
bc.constraints.push_back (
parse_build_constraint (nv, false /* exclusion */, name));
}
- else if ((n.size () > 14 &&
- n.compare (n.size () - 14, 14, "-build-exclude") == 0))
+ else if (n.size () > 14 &&
+ n.compare (n.size () - 14, 14, "-build-exclude") == 0)
{
n.resize (n.size () - 14);
@@ -4001,6 +4036,39 @@ namespace bpkg
bad_value ("path with build or build2 extension expected");
}
+ else if (n.size () > 5 && n.compare (n.size () - 5, 5, "-name") == 0)
+ {
+ add_distribution (
+ parse_distribution (move (n), n.size () - 5, move (v)),
+ true /* unique */);
+ }
+ // Note: must precede the check for the "-version" suffix.
+ //
+ else if (n.size () > 22 &&
+ n.compare (n.size () - 22, 22, "-to-downstream-version") == 0)
+ {
+ add_distribution (
+ parse_distribution (move (n), n.size () - 22, move (v)),
+ false /* unique */);
+ }
+ else if (n.size () > 8 && n.compare (n.size () - 8, 8, "-version") == 0)
+ {
+ // If the value is forbidden then throw, but only after the name is
+ // validated. Thus, check for that before we move the value from.
+ //
+ bool bad (v == "$" &&
+ flag (package_manifest_flags::forbid_incomplete_values));
+
+ // Can throw.
+ //
+ distribution_name_value d (
+ parse_distribution (move (n), n.size () - 8, move (v)));
+
+ if (bad)
+ bad_value ("$ not allowed");
+
+ add_distribution (move (d), true /* unique */);
+ }
else if (n == "location")
{
if (flag (package_manifest_flags::forbid_location))
@@ -4152,7 +4220,7 @@ namespace bpkg
// Now, when the version manifest value is parsed, we can parse the
// dependencies and complete their constraints, if requested.
//
- auto complete_constraint = [&m, cd, &flag] (auto&& dep)
+ auto complete_constraint = [&m, cv, &flag] (auto&& dep)
{
if (dep.constraint)
try
@@ -4160,12 +4228,12 @@ namespace bpkg
version_constraint& vc (*dep.constraint);
if (!vc.complete () &&
- flag (package_manifest_flags::forbid_incomplete_dependencies))
+ flag (package_manifest_flags::forbid_incomplete_values))
throw invalid_argument ("$ not allowed");
// Complete the constraint.
//
- if (cd)
+ if (cv)
vc = vc.effective (m.version);
}
catch (const invalid_argument& e)
@@ -4238,6 +4306,30 @@ namespace bpkg
}
}
+ // Now, when the version manifest value is parsed, we complete the
+ // <distribution>-version values, if requested.
+ //
+ if (cv)
+ {
+ for (distribution_name_value& nv: m.distributions)
+ {
+ const string& n (nv.name);
+ string& v (nv.value);
+
+ if (v == "$" &&
+ (n.size () > 8 && n.compare (n.size () - 8, 8, "-version") == 0) &&
+ (n.size () <= 22 ||
+ n.compare (n.size () - 22, 22, "-to-downstream-version") != 0))
+ {
+ v = version (default_epoch (m.version),
+ move (m.version.upstream),
+ nullopt /* release */,
+ nullopt /* revision */,
+ 0 /* iteration */).string ();
+ }
+ }
+ }
+
if (!m.location && flag (package_manifest_flags::require_location))
bad_name ("no package location specified");
@@ -4277,7 +4369,7 @@ namespace bpkg
name_value nv,
const function<package_manifest::translate_function>& tf,
bool iu,
- bool cd,
+ bool cv,
package_manifest_flags fl,
package_manifest& m)
{
@@ -4297,7 +4389,7 @@ namespace bpkg
[&p] () {return p.next ();},
tf,
iu,
- cd,
+ cv,
fl,
m);
}
@@ -4309,12 +4401,12 @@ namespace bpkg
p,
move (nv),
iu,
- false /* complete_depends */,
- package_manifest_flags::forbid_file |
- package_manifest_flags::forbid_fragment |
- package_manifest_flags::forbid_incomplete_dependencies |
- package_manifest_flags::require_location |
- package_manifest_flags::require_description_type |
+ false /* complete_values */,
+ package_manifest_flags::forbid_file |
+ package_manifest_flags::forbid_fragment |
+ package_manifest_flags::forbid_incomplete_values |
+ package_manifest_flags::require_location |
+ package_manifest_flags::require_description_type |
package_manifest_flags::require_bootstrap_build);
}
@@ -4324,10 +4416,10 @@ namespace bpkg
package_manifest (manifest_parser& p,
const function<translate_function>& tf,
bool iu,
- bool cd,
+ bool cv,
package_manifest_flags fl)
{
- parse_package_manifest (p, p.next (), tf, iu, cd, fl, *this);
+ parse_package_manifest (p, p.next (), tf, iu, cv, fl, *this);
// Make sure this is the end.
//
@@ -4340,9 +4432,9 @@ namespace bpkg
package_manifest::
package_manifest (manifest_parser& p,
bool iu,
- bool cd,
+ bool cv,
package_manifest_flags fl)
- : package_manifest (p, function<translate_function> (), iu, cd, fl)
+ : package_manifest (p, function<translate_function> (), iu, cv, fl)
{
}
@@ -4351,7 +4443,7 @@ namespace bpkg
vector<name_value>&& vs,
const function<translate_function>& tf,
bool iu,
- bool cd,
+ bool cv,
package_manifest_flags fl)
{
auto i (vs.begin ());
@@ -4366,7 +4458,7 @@ namespace bpkg
},
tf,
iu,
- cd,
+ cv,
fl,
*this);
}
@@ -4375,13 +4467,13 @@ namespace bpkg
package_manifest (const string& name,
vector<name_value>&& vs,
bool iu,
- bool cd,
+ bool cv,
package_manifest_flags fl)
: package_manifest (name,
move (vs),
function<translate_function> (),
iu,
- cd,
+ cv,
fl)
{
}
@@ -4390,11 +4482,11 @@ namespace bpkg
package_manifest (manifest_parser& p,
name_value nv,
bool iu,
- bool cd,
+ bool cv,
package_manifest_flags fl)
{
parse_package_manifest (
- p, move (nv), function<translate_function> (), iu, cd, fl, *this);
+ p, move (nv), function<translate_function> (), iu, cv, fl, *this);
}
optional<text_type> package_manifest::
@@ -5033,6 +5125,9 @@ namespace bpkg
for (const path& f: m.buildfile_paths)
s.next ("build-file", f.posix_string () + (an ? ".build2" : ".build"));
+ for (const distribution_name_value& nv: m.distributions)
+ s.next (nv.name, nv.value);
+
if (m.location)
s.next ("location", m.location->posix_string ());
diff --git a/libbpkg/manifest.hxx b/libbpkg/manifest.hxx
index 0fd5feb..120884a 100644
--- a/libbpkg/manifest.hxx
+++ b/libbpkg/manifest.hxx
@@ -811,18 +811,18 @@ namespace bpkg
//
enum class package_manifest_flags: std::uint16_t
{
- none = 0x000,
-
- forbid_file = 0x001, // Forbid *-file manifest values.
- forbid_location = 0x002,
- forbid_sha256sum = 0x004,
- forbid_fragment = 0x008,
- forbid_incomplete_dependencies = 0x010,
-
- require_location = 0x020,
- require_sha256sum = 0x040,
- require_description_type = 0x080,
- require_bootstrap_build = 0x100
+ none = 0x000,
+
+ forbid_file = 0x001, // Forbid *-file manifest values.
+ forbid_location = 0x002,
+ forbid_sha256sum = 0x004,
+ forbid_fragment = 0x008,
+ forbid_incomplete_values = 0x010, // depends, <distribution>-version, etc.
+
+ require_location = 0x020,
+ require_sha256sum = 0x040,
+ require_description_type = 0x080,
+ require_bootstrap_build = 0x100
};
inline package_manifest_flags
@@ -1130,6 +1130,27 @@ namespace bpkg
content (std::move (c)) {}
};
+ // Binary distribution package information.
+ //
+ // The name is prefixed with the distribution name/version and has the
+ // `<name>[_<version>]-*` form. For example:
+ //
+ // debian
+ // debian_10
+ //
+ // Note that the value semantics can be distribution-specific.
+ //
+ struct distribution_name_value
+ {
+ std::string name;
+ std::string value;
+
+ distribution_name_value () = default;
+ distribution_name_value (std::string n, std::string v)
+ : name (std::move (n)),
+ value (std::move (v)) {}
+ };
+
class LIBBPKG_EXPORT package_manifest
{
public:
@@ -1189,6 +1210,10 @@ namespace bpkg
std::vector<buildfile> buildfiles; // Buildfiles content.
std::vector<butl::path> buildfile_paths;
+ // The binary distributions package information.
+ //
+ std::vector<distribution_name_value> distributions;
+
// The following values are only valid in the manifest list (and only for
// certain repository types).
//
@@ -1220,7 +1245,7 @@ namespace bpkg
//
package_manifest (butl::manifest_parser&,
bool ignore_unknown = false,
- bool complete_dependencies = true,
+ bool complete_values = true,
package_manifest_flags =
package_manifest_flags::forbid_location |
package_manifest_flags::forbid_sha256sum |
@@ -1242,7 +1267,7 @@ namespace bpkg
package_manifest (butl::manifest_parser&,
const std::function<translate_function>&,
bool ignore_unknown = false,
- bool complete_depends = true,
+ bool complete_values = true,
package_manifest_flags =
package_manifest_flags::forbid_location |
package_manifest_flags::forbid_sha256sum |
@@ -1257,7 +1282,7 @@ namespace bpkg
package_manifest (const std::string& name,
std::vector<butl::manifest_name_value>&&,
bool ignore_unknown = false,
- bool complete_dependencies = true,
+ bool complete_values = true,
package_manifest_flags =
package_manifest_flags::forbid_location |
package_manifest_flags::forbid_sha256sum |
@@ -1267,7 +1292,7 @@ namespace bpkg
std::vector<butl::manifest_name_value>&&,
const std::function<translate_function>&,
bool ignore_unknown = false,
- bool complete_depends = true,
+ bool complete_values = true,
package_manifest_flags =
package_manifest_flags::forbid_location |
package_manifest_flags::forbid_sha256sum |
@@ -1278,7 +1303,7 @@ namespace bpkg
package_manifest (butl::manifest_parser&,
butl::manifest_name_value start,
bool ignore_unknown,
- bool complete_depends,
+ bool complete_values,
package_manifest_flags);
// Override manifest values with the specified. Throw manifest_parsing if
@@ -1382,9 +1407,9 @@ namespace bpkg
inline package_manifest
pkg_package_manifest (butl::manifest_parser& p,
bool ignore_unknown = false,
- bool complete_depends = true)
+ bool complete_values = true)
{
- return package_manifest (p, ignore_unknown, complete_depends);
+ return package_manifest (p, ignore_unknown, complete_values);
}
LIBBPKG_EXPORT package_manifest
diff --git a/tests/manifest/driver.cxx b/tests/manifest/driver.cxx
index c0d8693..fb40f7e 100644
--- a/tests/manifest/driver.cxx
+++ b/tests/manifest/driver.cxx
@@ -40,7 +40,7 @@ using namespace bpkg;
// In the second form read and parse the package manifest from stdin and
// serialize it to stdout.
//
-// -c complete the dependency constraints
+// -c complete the incomplete values (depends, <distribution>-version, etc)
// -i ignore unknown
//
// Note: the above options should go after -p on the command line.
@@ -74,7 +74,7 @@ main (int argc, char* argv[])
{
if (mode == "-p")
{
- bool complete_dependencies (false);
+ bool complete_values (false);
bool ignore_unknown (false);
bool long_lines (false);
@@ -83,7 +83,7 @@ main (int argc, char* argv[])
string o (argv[i]);
if (o == "-c")
- complete_dependencies = true;
+ complete_values = true;
else if (o == "-i")
ignore_unknown = true;
else if (o == "-l")
@@ -114,7 +114,7 @@ main (int argc, char* argv[])
}
},
ignore_unknown,
- complete_dependencies).serialize (s);
+ complete_values).serialize (s);
}
else if (mode == "-ec")
{
diff --git a/tests/manifest/testscript b/tests/manifest/testscript
index 336b288..c696be7 100644
--- a/tests/manifest/testscript
+++ b/tests/manifest/testscript
@@ -606,6 +606,103 @@
}
}
+ : distribution
+ :
+ {
+ : incomplete
+ :
+ {
+ $* <<EOF >>EOF
+ : 1
+ name: libcrypto
+ version: 1.1.1+18
+ upstream-version: 1.1.1n
+ summary: C library providing general cryptography and X.509 support
+ license: OpenSSL
+ debian-name: libssl1.1 libssl-dev
+ debian-version: 1.1.1n
+ debian-to-downstream-version: /([^.])\.([^.])\.([^.])n/\1.\2.\3+18/
+ debian-to-downstream-version: /([^.])\.([^.])\.([^.])o/\1.\2.\3+19/
+ debian-to-downstream-version: /([^.])\.([^.])\.([^.])p/\1.\2.\3+20/
+ fedora-name: openssl-libs openssl-devel
+ fedora-version: $
+ EOF
+ }
+
+ : complete
+ :
+ {
+ $* -c <<EOI >>EOO
+ : 1
+ name: libcrypto
+ version: +2-1.1.1-a.1+2
+ upstream-version: 1.1.1n
+ summary: C library providing general cryptography and X.509 support
+ license: OpenSSL
+ fedora-name: openssl-libs openssl-devel
+ fedora-version: $
+ EOI
+ : 1
+ name: libcrypto
+ version: +2-1.1.1-a.1+2
+ upstream-version: 1.1.1n
+ summary: C library providing general cryptography and X.509 support
+ license: OpenSSL
+ fedora-name: openssl-libs openssl-devel
+ fedora-version: 1.1.1
+ EOO
+ }
+
+ : dash-in-name
+ :
+ {
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: libcrypto
+ version: 1.1.1+18
+ upstream-version: 1.1.1n
+ summary: C library providing general cryptography and X.509 support
+ license: OpenSSL
+ de-bian-name: libssl1.1 libssl-dev
+ EOI
+ stdin:7:1: error: distribution name 'de-bian' contains '-'
+ EOE
+ }
+
+ : empty-value
+ :
+ {
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: libcrypto
+ version: 1.1.1+18
+ upstream-version: 1.1.1n
+ summary: C library providing general cryptography and X.509 support
+ license: OpenSSL
+ debian-name:
+ EOI
+ stdin:7:13: error: empty package distribution value
+ EOE
+ }
+
+ : redefinition
+ :
+ {
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: libcrypto
+ version: 1.1.1+18
+ upstream-version: 1.1.1n
+ summary: C library providing general cryptography and X.509 support
+ license: OpenSSL
+ debian-name: libssl1.1 libssl-dev
+ debian-name: libssl1.1 libssl-dev
+ EOI
+ stdin:8:1: error: package distribution value redefinition
+ EOE
+ }
+ }
+
: depends
:
{