aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2022-06-20 20:58:47 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2022-06-23 12:26:48 +0300
commit3de5120d299a5e17c9c17dfd2bfc4bb4e6340941 (patch)
tree9929ec4d27f38fb4a653ee2b586b502e9c719331
parent9c476d4b12ba91677716fdcadfc14a5fc9859d5d (diff)
Add support for additional *-build package manifest values and alternative buildfile naming
-rw-r--r--libbpkg/manifest.cxx90
-rw-r--r--libbpkg/manifest.hxx33
-rw-r--r--tests/manifest/testscript206
3 files changed, 323 insertions, 6 deletions
diff --git a/libbpkg/manifest.cxx b/libbpkg/manifest.cxx
index 9578977..4555bbc 100644
--- a/libbpkg/manifest.cxx
+++ b/libbpkg/manifest.cxx
@@ -3367,6 +3367,20 @@ namespace bpkg
return (fl & f) != package_manifest_flags::none;
};
+ // Based on the `*-build[2]` value name set the manifest's alt_naming flag
+ // if absent and verify that it doesn't change otherwise.
+ //
+ auto alt_naming = [&m, &bad_name] (const string& n)
+ {
+ bool v (n.size () > 7 && n.compare (n.size () - 7, 7, "-build2") == 0);
+
+ if (!m.alt_naming)
+ m.alt_naming = v;
+ else if (*m.alt_naming != v)
+ bad_name (string (*m.alt_naming ? "alternative" : "standard") +
+ " buildfile naming scheme is already used");
+ };
+
// Cache the upstream version manifest value and validate whether it's
// allowed later, after the version value is parsed.
//
@@ -3701,20 +3715,77 @@ namespace bpkg
tests.push_back (move (nv));
}
- else if (n == "bootstrap-build")
+ else if (n == "bootstrap-build" || n == "bootstrap-build2")
{
+ alt_naming (n);
+
if (m.bootstrap_build)
- bad_name ("package bootstrap-build redefinition");
+ bad_name ("package " + n + " redefinition");
m.bootstrap_build = move (v);
}
- else if (n == "root-build")
+ else if (n == "root-build" || n == "root-build2")
{
+ alt_naming (n);
+
if (m.root_build)
- bad_name ("package root-build redefinition");
+ bad_name ("package " + n + " redefinition");
m.root_build = move (v);
}
+ else if ((n.size () > 6 && n.compare (n.size () - 6, 6, "-build") == 0) ||
+ (n.size () > 7 && n.compare (n.size () - 7, 7, "-build2") == 0))
+ {
+ alt_naming (n);
+
+ // Verify that the path doesn't contain backslashes which would be
+ // interpreted differently on Windows and POSIX.
+ //
+ if (n.find ('\\') != string::npos)
+ bad_name ("backslash in package buildfile path");
+
+ // Strip the '-build' suffix.
+ //
+ n.resize (n.size () - (*m.alt_naming ? 7 : 6));
+
+ try
+ {
+ path f (move (n)); // Note: not empty.
+
+ // Fail if the value name is something like `config/-build`.
+ //
+ if (f.to_directory ())
+ bad_name ("empty package buildfile name");
+
+ if (f.absolute ())
+ bad_name ("absolute package buildfile path");
+
+ // Verify that the path refers inside the package's build/
+ // subdirectory.
+ //
+ f.normalize (); // Note: can't throw since the path is relative.
+
+ if (dir_path::traits_type::parent (*f.begin ()))
+ bad_name ("package buildfile path refers outside build/ "
+ "subdirectory");
+
+ // Check for duplicates.
+ //
+ vector<buildfile>& bs (m.buildfiles);
+ if (find_if (bs.begin (), bs.end (),
+ [&f] (const auto& v) {return v.path == f;}) !=
+ bs.end ())
+ {
+ bad_name ("package buildfile redefinition");
+ }
+
+ bs.push_back (buildfile (move (f), move (v)));
+ }
+ catch (const invalid_path&)
+ {
+ bad_name ("invalid package buildfile path");
+ }
+ }
else if (n == "location")
{
if (flag (package_manifest_flags::forbid_location))
@@ -4446,11 +4517,18 @@ namespace bpkg
: c.config + "/" + *c.target,
c.comment));
+ bool an (m.alt_naming && *m.alt_naming);
+
if (m.bootstrap_build)
- s.next ("bootstrap-build", *m.bootstrap_build);
+ s.next (an ? "bootstrap-build2" : "bootstrap-build",
+ *m.bootstrap_build);
if (m.root_build)
- s.next ("root-build", *m.root_build);
+ s.next (an ? "root-build2" : "root-build", *m.root_build);
+
+ for (const auto& bf: m.buildfiles)
+ s.next (bf.path.posix_string () + (an ? "-build2" : "-build"),
+ bf.content);
if (m.location)
s.next ("location", m.location->posix_string ());
diff --git a/libbpkg/manifest.hxx b/libbpkg/manifest.hxx
index 09d64d1..a3415cc 100644
--- a/libbpkg/manifest.hxx
+++ b/libbpkg/manifest.hxx
@@ -1054,6 +1054,29 @@ namespace bpkg
string () const;
};
+ // Package's buildfile path and content.
+ //
+ struct buildfile
+ {
+ // The path is relative to the package's build/ subdirectory with the
+ // extension stripped.
+ //
+ // For example, for the build/config/common.build file the path will be
+ // config/common.
+ //
+ // Note that the actual file path depends on the project's buildfile
+ // naming scheme and for the config/common example above the actual path
+ // can also be build2/config/common.build2.
+ //
+ butl::path path;
+ std::string content;
+
+ buildfile () = default;
+ buildfile (butl::path p, std::string c)
+ : path (std::move (p)),
+ content (std::move (c)) {}
+ };
+
class LIBBPKG_EXPORT package_manifest
{
public:
@@ -1090,9 +1113,19 @@ namespace bpkg
butl::small_vector<build_class_expr, 1> builds;
std::vector<build_constraint> build_constraints;
+ // If true, then this package use the alternative buildfile naming scheme
+ // (build2/, .build2). In the manifest serialization this is encoded as
+ // either *-build or *-build2 value names.
+ //
+ butl::optional<bool> alt_naming;
+
butl::optional<std::string> bootstrap_build;
butl::optional<std::string> root_build;
+ // Additional buildfiles which are potentially included by root.build.
+ //
+ std::vector<buildfile> buildfiles;
+
// The following values are only valid in the manifest list (and only for
// certain repository types).
//
diff --git a/tests/manifest/testscript b/tests/manifest/testscript
index ded4c57..760a9de 100644
--- a/tests/manifest/testscript
+++ b/tests/manifest/testscript
@@ -3174,6 +3174,212 @@
stdin:6:8: error: unexpected enable clause
EOE
}
+
+ : buildfile
+ :
+ {
+ : standard-naming
+ :
+ $* <<EOF >>EOF
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ bootstrap-build:\
+ project = libfoo
+
+ using version
+ using config
+ using dist
+ using test
+ using install
+ \
+ root-build:\
+ include config/common.build
+
+ cxx.std = latest
+
+ using cxx
+ \
+ config/common-build:\
+ {
+ config [bool] config.libfoo.extras ?= false
+ }
+ \
+ EOF
+
+ : alt-naming
+ :
+ $* <<EOF >>EOF
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ bootstrap-build2:\
+ project = libfoo
+
+ using version
+ using config
+ using dist
+ using test
+ using install
+ \
+ root-build2:\
+ include config/common.build
+
+ cxx.std = latest
+
+ using cxx
+ \
+ config/common-build2:\
+ {
+ config [bool] config.libfoo.extras ?= false
+ }
+ \
+ EOF
+
+ : mixed-naming
+ :
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ bootstrap-build:\
+ project = libfoo
+
+ using version
+ using config
+ using dist
+ using test
+ using install
+ \
+ root-build:\
+ include config/common.build
+
+ cxx.std = latest
+
+ using cxx
+ \
+ config/common-build2:\
+ {
+ config [bool] config.libfoo.extras ?= false
+ }
+ \
+ EOI
+ stdin:22:1: error: standard buildfile naming scheme is already used
+ EOE
+
+ : backslash
+ :
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ config\common-build:\
+ {
+ config [bool] config.libfoo.extras ?= false
+ }
+ \
+ EOI
+ stdin:6:1: error: backslash in package buildfile path
+ EOE
+
+ : unknown
+ :
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ common.build:\
+ {
+ config [bool] config.libfoo.extras ?= false
+ }
+ \
+ EOI
+ stdin:6:1: error: unknown name 'common.build' in package manifest
+ EOE
+
+ : empty-name
+ :
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ config/-build:\
+ {
+ config [bool] config.libfoo.extras ?= false
+ }
+ \
+ EOI
+ stdin:6:1: error: empty package buildfile name
+ EOE
+
+ : absolute-invalid
+ :
+ $* <<EOI 2>>~%EOE% != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ /config/common-build:\
+ {
+ config [bool] config.libfoo.extras ?= false
+ }
+ \
+ EOI
+ %stdin:6:1: error: (absolute|invalid) package buildfile path%
+ EOE
+
+ : outside
+ :
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ common/../../common-build:\
+ {
+ config [bool] config.libfoo.extras ?= false
+ }
+ \
+ EOI
+ stdin:6:1: error: package buildfile path refers outside build/ subdirectory
+ EOE
+
+ : redefinition
+ :
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ common-build:\
+ {
+ config [bool] config.libfoo.extras ?= false
+ }
+ \
+ common-build:\
+ {
+ config [bool] config.libfoo.extras ?= false
+ }
+ \
+ EOI
+ stdin:11:1: error: package buildfile redefinition
+ EOE
+ }
}
: package-list