aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbpkg/manifest.cxx371
-rw-r--r--libbpkg/manifest.hxx158
-rw-r--r--tests/manifest/testscript328
-rw-r--r--tests/overrides/testscript276
4 files changed, 1090 insertions, 43 deletions
diff --git a/libbpkg/manifest.cxx b/libbpkg/manifest.cxx
index 923b113..bd69b85 100644
--- a/libbpkg/manifest.cxx
+++ b/libbpkg/manifest.cxx
@@ -3069,6 +3069,44 @@ namespace bpkg
match_classes (cs, im, expr, r);
}
+ // build_auxiliary
+ //
+ optional<pair<string, string>> build_auxiliary::
+ parse_value_name (const string& n)
+ {
+ // Check if the value name matches exactly.
+ //
+ if (n == "build-auxiliary")
+ return make_pair (string (), string ());
+
+ // Check if this is a *-build-auxiliary name.
+ //
+ if (n.size () > 16 &&
+ n.compare (n.size () - 16, 16, "-build-auxiliary") == 0)
+ {
+ return make_pair (string (n, 0, n.size () - 16), string ());
+ }
+
+ // Check if this is a build-auxiliary-* name.
+ //
+ if (n.size () > 16 && n.compare (0, 16, "build-auxiliary-") == 0)
+ return make_pair (string (), string (n, 16));
+
+ // Check if this is a *-build-auxiliary-* name.
+ //
+ size_t p (n.find ("-build-auxiliary-"));
+
+ if (p != string::npos &&
+ p != 0 && // Not '-build-auxiliary-*'?
+ p + 17 != n.size () && // Not '*-build-auxiliary-'?
+ n.find ("-build-auxiliary-", p + 17) == string::npos) // Unambiguous?
+ {
+ return make_pair (string (n, 0, p), string (n, p + 17));
+ }
+
+ return nullopt;
+ }
+
// test_dependency_type
//
string
@@ -3318,6 +3356,62 @@ namespace bpkg
return email (move (v), move (c));
}
+ // Parse the [*-]build-auxiliary[-*] manifest value.
+ //
+ // Note that the environment name is expected to already be retrieved using
+ // build_auxiliary::parse_value_name().
+ //
+ static build_auxiliary
+ parse_build_auxiliary (const name_value& nv,
+ string&& env_name,
+ const string& source_name)
+ {
+ auto bad_value = [&nv, &source_name] (const string& d)
+ {
+ throw !source_name.empty ()
+ ? parsing (source_name, nv.value_line, nv.value_column, d)
+ : parsing (d);
+ };
+
+ pair<string, string> vc (parser::split_comment (nv.value));
+ string& v (vc.first);
+ string& c (vc.second);
+
+ if (v.empty ())
+ bad_value ("empty build auxiliary configuration name pattern");
+
+ return build_auxiliary (move (env_name), move (v), move (c));
+ }
+
+ // Parse the [*-]build-bot manifest value and append it to the specified
+ // custom bot public keys list. Make sure the specified key is not empty and
+ // is not a duplicate and throw parsing if that's not the case.
+ //
+ // Note: value name is not used by this function (and so can be moved out,
+ // etc before the call).
+ //
+ static void
+ parse_build_bot (const name_value& nv, const string& source_name, strings& r)
+ {
+ const string& v (nv.value);
+
+ auto bad_value = [&nv, &source_name, &v] (const string& d,
+ bool add_key = true)
+ {
+ throw !source_name.empty ()
+ ? parsing (source_name, nv.value_line, nv.value_column, d)
+ : parsing (!add_key ? d : (d + ":\n" + v));
+ };
+
+ if (v.empty ())
+ bad_value ("empty custom build bot public key", false /* add_key */);
+
+ if (find (r.begin (), r.end (), v) != r.end ())
+ bad_value ("duplicate custom build bot public key");
+
+ r.push_back (v);
+ }
+
const version stub_version (0, "0", nullopt, nullopt, 0);
// Parse until next() returns end-of-manifest value.
@@ -3340,16 +3434,37 @@ namespace bpkg
auto bad_value ([&name, &nv](const string& d) {
throw parsing (name, nv.value_line, nv.value_column, d);});
- auto parse_email = [&bad_name] (const name_value& nv,
- optional<email>& r,
- const char* what,
- const string& source_name,
- bool empty = false)
+ auto parse_email = [&bad_name, &name] (const name_value& nv,
+ optional<email>& r,
+ const char* what,
+ bool empty = false)
{
if (r)
bad_name (what + string (" email redefinition"));
- r = bpkg::parse_email (nv, what, source_name, empty);
+ r = bpkg::parse_email (nv, what, name, empty);
+ };
+
+ // Parse the [*-]build-auxiliary[-*] manifest value and append it to the
+ // specified build auxiliary list. Make sure that the list contains not
+ // more than one entry with unspecified environment name and throw parsing
+ // if that's not the case. Also make sure that there are no entry
+ // redefinitions (multiple entries with the same environment name).
+ //
+ auto parse_build_auxiliary = [&bad_name, &name] (const name_value& nv,
+ string&& en,
+ vector<build_auxiliary>& r)
+ {
+ build_auxiliary a (bpkg::parse_build_auxiliary (nv, move (en), name));
+
+ if (find_if (r.begin (), r.end (),
+ [&a] (const build_auxiliary& ba)
+ {
+ return ba.environment_name == a.environment_name;
+ }) != r.end ())
+ bad_name ("build auxiliary environment redefinition");
+
+ r.push_back (move (a));
};
auto parse_url = [&bad_value] (const string& v,
@@ -3908,7 +4023,7 @@ namespace bpkg
}
else if (n == "email")
{
- parse_email (nv, m.email, "project", name);
+ parse_email (nv, m.email, "project");
}
else if (n == "doc-url")
{
@@ -3933,19 +4048,19 @@ namespace bpkg
}
else if (n == "package-email")
{
- parse_email (nv, m.package_email, "package", name);
+ parse_email (nv, m.package_email, "package");
}
else if (n == "build-email")
{
- parse_email (nv, m.build_email, "build", name, true /* empty */);
+ parse_email (nv, m.build_email, "build", true /* empty */);
}
else if (n == "build-warning-email")
{
- parse_email (nv, m.build_warning_email, "build warning", name);
+ parse_email (nv, m.build_warning_email, "build warning");
}
else if (n == "build-error-email")
{
- parse_email (nv, m.build_error_email, "build error", name);
+ parse_email (nv, m.build_error_email, "build error");
}
else if (n == "priority")
{
@@ -4019,6 +4134,23 @@ namespace bpkg
m.build_constraints.push_back (
parse_build_constraint (nv, true /* exclusion */, name));
}
+ else if (optional<pair<string, string>> ba =
+ build_auxiliary::parse_value_name (n))
+ {
+ if (ba->first.empty ()) // build-auxiliary*?
+ {
+ parse_build_auxiliary (nv, move (ba->second), m.build_auxiliaries);
+ }
+ else // *-build-auxiliary*
+ {
+ build_package_config& bc (build_conf (move (ba->first)));
+ parse_build_auxiliary (nv, move (ba->second), bc.auxiliaries);
+ }
+ }
+ else if (n == "build-bot")
+ {
+ parse_build_bot (nv, name, m.build_bot_keys);
+ }
else if (n.size () > 13 &&
n.compare (n.size () - 13, 13, "-build-config") == 0)
{
@@ -4063,6 +4195,14 @@ namespace bpkg
bc.constraints.push_back (
parse_build_constraint (nv, true /* exclusion */, name));
}
+ else if (n.size () > 10 &&
+ n.compare (n.size () - 10, 10, "-build-bot") == 0)
+ {
+ n.resize (n.size () - 10);
+
+ build_package_config& bc (build_conf (move (n)));
+ parse_build_bot (nv, name, bc.bot_keys);
+ }
else if (n.size () > 12 &&
n.compare (n.size () - 12, 12, "-build-email") == 0)
{
@@ -4440,8 +4580,7 @@ namespace bpkg
// Note: the argument can only be one of the build_config_*emails
// variables (see above) to distinguish between the email kinds.
//
- auto parse_build_config_emails = [&name,
- &nv,
+ auto parse_build_config_emails = [&nv,
&build_config_emails,
&build_config_warning_emails,
&build_config_error_emails,
@@ -4479,7 +4618,6 @@ namespace bpkg
(ek == email_kind::build ? "build configuration" :
ek == email_kind::warning ? "build configuration warning" :
"build configuration error"),
- name,
ek == email_kind::build /* empty */);
}
};
@@ -4811,6 +4949,14 @@ namespace bpkg
//
const manifest_name_value* pbc (nullptr);
+ // The first {build-bot} override value.
+ //
+ const manifest_name_value* cbb (nullptr);
+
+ // The first {*-build-bot} override value.
+ //
+ const manifest_name_value* pbb (nullptr);
+
// The first {build-*email} override value.
//
const manifest_name_value* cbe (nullptr);
@@ -4825,10 +4971,23 @@ namespace bpkg
//
vector<pair<size_t, bool>> obcs;
+ // List of indexes of the build configurations with the overridden bots.
+ //
+ vector<size_t> obbs;
+
// List of indexes of the build configurations with the overridden emails.
//
vector<size_t> obes;
+ // Return true if the specified package build configuration is newly
+ // created by the *-build-config override.
+ //
+ auto config_created = [&m, confs_num = m.build_configs.size ()]
+ (const build_package_config& c)
+ {
+ return &c >= m.build_configs.data () + confs_num;
+ };
+
// Apply overrides.
//
for (const manifest_name_value& nv: nvs)
@@ -4877,7 +5036,7 @@ namespace bpkg
// otherwise.
//
// The n argument specifies the length of the configuration name in
- // *-build-config, *-builds, *-build-{include,exclude}, and
+ // *-build-config, *-builds, *-build-{include,exclude}, *-build-bot, and
// *-build-*email values.
//
auto build_conf =
@@ -4914,7 +5073,9 @@ namespace bpkg
// the build config-specific builds group value override, if exists. If
// no configuration matches, then throw manifest_parsing, except for the
// validate-only mode in which case just add an empty configuration with
- // this name and return the reference to it.
+ // this name and return the reference to it. Also verify that no common
+ // build constraints group value overrides are applied yet and throw if
+ // that's not the case.
//
auto build_conf_constr =
[&pbc, &cbc, &nv, &obcs, &bad_name, &build_conf, &m, validate_only]
@@ -4979,6 +5140,75 @@ namespace bpkg
return r;
};
+ // Reset the {build-bot} value group on the first call but throw if any
+ // of the {*-build-bot} override values are already encountered.
+ //
+ auto reset_build_bots = [&cbb, &pbb, &nv, &bad_name, &m] ()
+ {
+ if (cbb == nullptr)
+ {
+ if (pbb != nullptr)
+ bad_name ('\'' + nv.name + "' override specified together with '" +
+ pbb->name + "' override");
+
+ m.build_bot_keys.clear ();
+ cbb = &nv;
+ }
+ };
+
+ // Return the reference to the package build configuration which matches
+ // the build config-specific build bot value override, if exists. If no
+ // configuration matches, then throw manifest_parsing, except for the
+ // validate-only mode in which case just add an empty configuration with
+ // this name and return the reference to it. Also verify that no common
+ // build bot value overrides are applied yet and throw if that's not the
+ // case.
+ //
+ auto build_conf_bot =
+ [&pbb, &cbb, &nv, &obbs, &bad_name, &build_conf, &m, validate_only]
+ (size_t n) -> build_package_config&
+ {
+ const string& nm (nv.name);
+
+ // If this is the first build config override value, then save its
+ // address. But first verify that no common build bot value overrides
+ // are applied yet and throw if that's not the case.
+ //
+ if (pbb == nullptr)
+ {
+ if (cbb != nullptr)
+ bad_name ('\'' + nm + "' override specified together with '" +
+ cbb->name + "' override");
+
+ pbb = &nv;
+ }
+
+ small_vector<build_package_config, 1>& cs (m.build_configs);
+
+ // Find the build package configuration. If there is no such a
+ // configuration then throw, except for the validate-only mode in
+ // which case just add an empty configuration with this name.
+ //
+ // Note that we are using indexes rather then configuration addresses
+ // due to potential reallocations.
+ //
+ build_package_config& r (build_conf (n, validate_only));
+ size_t ci (&r - cs.data ());
+
+ // If this is the first encountered {*-build-bot} override for this
+ // build config, then clear this config' bot_keys members and add an
+ // entry to the overridden configs list.
+ //
+ if (find (obbs.begin (), obbs.end (), ci) == obbs.end ())
+ {
+ r.bot_keys.clear ();
+
+ obbs.push_back (ci);
+ }
+
+ return r;
+ };
+
// Reset the {build-*email} value group on the first call but throw if
// any of the {*-build-*email} override values are already encountered.
//
@@ -5001,7 +5231,9 @@ namespace bpkg
// the build config-specific emails group value override, if exists. If
// no configuration matches, then throw manifest_parsing, except for the
// validate-only mode in which case just add an empty configuration with
- // this name and return the reference to it.
+ // this name and return the reference to it. Also verify that no common
+ // build emails group value overrides are applied yet and throw if
+ // that's not the case.
//
auto build_conf_email =
[&pbe, &cbe, &nv, &obes, &bad_name, &build_conf, &m, validate_only]
@@ -5050,6 +5282,45 @@ namespace bpkg
return r;
};
+ // Parse the [*-]build-auxiliary[-*] value override. If the mode is not
+ // validate-only, then override the matching value and throw
+ // manifest_parsing if no match. But throw only unless this is a
+ // configuration-specific override (build_config is not NULL) for a
+ // newly created configuration, in which case add the value instead.
+ //
+ auto override_build_auxiliary =
+ [&bad_name,
+ &name,
+ &config_created,
+ validate_only] (const name_value& nv,
+ string&& en,
+ vector<build_auxiliary>& r,
+ build_package_config* build_config = nullptr)
+ {
+ build_auxiliary a (bpkg::parse_build_auxiliary (nv, move (en), name));
+
+ if (!validate_only)
+ {
+ auto i (find_if (r.begin (), r.end (),
+ [&a] (const build_auxiliary& ba)
+ {
+ return ba.environment_name == a.environment_name;
+ }));
+
+ if (i != r.end ())
+ {
+ *i = move (a);
+ }
+ else
+ {
+ if (build_config != nullptr && config_created (*build_config))
+ r.emplace_back (move (a));
+ else
+ bad_name ("no match for '" + nv.name + "' value override");
+ }
+ }
+ };
+
const string& n (nv.name);
if (n == "builds")
@@ -5073,6 +5344,12 @@ namespace bpkg
m.build_constraints.push_back (
parse_build_constraint (nv, true /* exclusion */, name));
}
+ else if (n == "build-bot")
+ {
+ reset_build_bots ();
+
+ parse_build_bot (nv, name, m.build_bot_keys);
+ }
else if ((n.size () > 13 &&
n.compare (n.size () - 13, 13, "-build-config") == 0))
{
@@ -5107,6 +5384,12 @@ namespace bpkg
bc.constraints.push_back (
parse_build_constraint (nv, true /* exclusion */, name));
}
+ else if (n.size () > 10 &&
+ n.compare (n.size () - 10, 10, "-build-bot") == 0)
+ {
+ build_package_config& bc (build_conf_bot (n.size () - 10));
+ parse_build_bot (nv, name, bc.bot_keys);
+ }
else if (n == "build-email")
{
reset_build_emails ();
@@ -5145,6 +5428,21 @@ namespace bpkg
bc.error_email = parse_email (nv, "build configuration error", name);
}
+ else if (optional<pair<string, string>> ba =
+ build_auxiliary::parse_value_name (n))
+ {
+ if (ba->first.empty ()) // build-auxiliary*?
+ {
+ override_build_auxiliary (nv, move (ba->second), m.build_auxiliaries);
+ }
+ else // *-build-auxiliary*
+ {
+ build_package_config& bc (
+ build_conf (ba->first.size (), validate_only));
+
+ override_build_auxiliary (nv, move (ba->second), bc.auxiliaries, &bc);
+ }
+ }
else
bad_name ("cannot override '" + n + "' value");
}
@@ -5155,8 +5453,9 @@ namespace bpkg
assert (cbc == nullptr || pbc == nullptr);
// Now, if not in the validate-only mode, as all the potential build
- // constraint/email overrides are applied, perform the final adjustments
- // to the build config constraints/emails.
+ // constraint, bot keys, and email overrides are applied, perform the
+ // final adjustments to the build config constraints, bot keys, and
+ // emails.
//
if (!validate_only)
{
@@ -5185,6 +5484,12 @@ namespace bpkg
}
}
+ if (cbb != nullptr) // Common build bots are overridden?
+ {
+ for (build_package_config& c: m.build_configs)
+ c.bot_keys.clear ();
+ }
+
if (cbe != nullptr) // Common build emails are overridden?
{
for (build_package_config& c: m.build_configs)
@@ -5516,6 +5821,15 @@ namespace bpkg
: c.config + '/' + *c.target,
c.comment));
+ for (const build_auxiliary& ba: m.build_auxiliaries)
+ s.next ((!ba.environment_name.empty ()
+ ? "build-auxiliary-" + ba.environment_name
+ : "build-auxiliary"),
+ serializer::merge_comment (ba.config, ba.comment));
+
+ for (const string& k: m.build_bot_keys)
+ s.next ("build-bot", k);
+
for (const build_package_config& bc: m.build_configs)
{
if (!bc.builds.empty ())
@@ -5538,6 +5852,25 @@ namespace bpkg
c.comment));
}
+ if (!bc.auxiliaries.empty ())
+ {
+ string n (bc.name + "-build-auxiliary");
+
+ for (const build_auxiliary& ba: bc.auxiliaries)
+ s.next ((!ba.environment_name.empty ()
+ ? n + '-' + ba.environment_name
+ : n),
+ serializer::merge_comment (ba.config, ba.comment));
+ }
+
+ if (!bc.bot_keys.empty ())
+ {
+ string n (bc.name + "-build-bot");
+
+ for (const string& k: bc.bot_keys)
+ s.next (n, k);
+ }
+
if (!bc.arguments.empty () || !bc.comment.empty ())
s.next (bc.name + "-build-config",
serializer::merge_comment (bc.arguments, bc.comment));
diff --git a/libbpkg/manifest.hxx b/libbpkg/manifest.hxx
index 834b681..feb3b96 100644
--- a/libbpkg/manifest.hxx
+++ b/libbpkg/manifest.hxx
@@ -10,7 +10,7 @@
#include <cassert>
#include <cstdint> // uint*_t
#include <ostream>
-#include <utility> // move()
+#include <utility> // move(), pair
#include <functional>
#include <libbutl/url.hxx>
@@ -980,14 +980,55 @@ namespace bpkg
return os << bce.string ();
}
+ // Build auxiliary configuration name-matching wildcard. Includes optional
+ // environment name (specified as a suffix in the [*-]build-auxiliary[-*]
+ // value name) and comment.
+ //
+ class LIBBPKG_EXPORT build_auxiliary
+ {
+ public:
+ std::string environment_name;
+
+ // Filesystem wildcard pattern for the build auxiliary configuration name.
+ //
+ std::string config;
+
+ std::string comment;
+
+ build_auxiliary () = default;
+ build_auxiliary (std::string en,
+ std::string cf,
+ std::string cm)
+ : environment_name (std::move (en)),
+ config (std::move (cf)),
+ comment (std::move (cm)) {}
+
+ // Parse a package manifest value name in the [*-]build-auxiliary[-*] form
+ // into the pair of the build package configuration name (first) and the
+ // build auxiliary environment name (second), with an unspecified name
+ // represented as an empty string. Return nullopt if the value name
+ // doesn't match this form.
+ //
+ static butl::optional<std::pair<std::string, std::string>>
+ parse_value_name (const std::string&);
+ };
+
// Package build configuration. Includes comment and optional overrides for
- // target build configuration class expressions/constraints and build
- // notification emails.
+ // target build configuration class expressions/constraints, auxiliaries,
+ // custom bot public keys, and notification emails.
+ //
+ // Note that in the package manifest the build bot keys list contains the
+ // public keys data (std::string type). However, for other use cases it may
+ // be convenient to store some other key representations (public key object
+ // pointers represented as key fingerprints, etc; see brep for such a use
+ // case).
//
- class build_package_config
+ template <typename K>
+ class build_package_config_template
{
public:
using email_type = bpkg::email;
+ using key_type = K;
std::string name;
@@ -1002,16 +1043,44 @@ namespace bpkg
butl::small_vector<build_class_expr, 1> builds;
std::vector<build_constraint> constraints;
+ // Note that all entries in this list must have distinct environment names
+ // (with empty name being one of the possibilities).
+ //
+ std::vector<build_auxiliary> auxiliaries;
+
+ std::vector<key_type> bot_keys;
+
butl::optional<email_type> email;
butl::optional<email_type> warning_email;
butl::optional<email_type> error_email;
- build_package_config () = default;
+ build_package_config_template () = default;
+
+ build_package_config_template (std::string n,
+ std::string a,
+ std::string c,
+ butl::small_vector<build_class_expr, 1> bs,
+ std::vector<build_constraint> cs,
+ std::vector<build_auxiliary> as,
+ std::vector<key_type> bks,
+ butl::optional<email_type> e,
+ butl::optional<email_type> we,
+ butl::optional<email_type> ee)
+ : name (move (n)),
+ arguments (move (a)),
+ comment (move (c)),
+ builds (move (bs)),
+ constraints (move (cs)),
+ auxiliaries (move (as)),
+ bot_keys (move (bks)),
+ email (move (e)),
+ warning_email (move (we)),
+ error_email (move (ee)) {}
// Built incrementally.
//
explicit
- build_package_config (std::string n): name (move (n)) {}
+ build_package_config_template (std::string n): name (move (n)) {}
// Return the configuration's build class expressions/constraints if they
// override the specified common expressions/constraints and return the
@@ -1032,6 +1101,25 @@ namespace bpkg
return !builds.empty () || !constraints.empty () ? constraints : common;
}
+ // Return the configuration's auxiliaries, if specified, and the common
+ // ones otherwise.
+ //
+ const std::vector<build_auxiliary>&
+ effective_auxiliaries (const std::vector<build_auxiliary>& common) const
+ noexcept
+ {
+ return !auxiliaries.empty () ? auxiliaries : common;
+ }
+
+ // Return the configuration's custom bot public keys, if specified, and
+ // the common ones otherwise.
+ //
+ const std::vector<key_type>&
+ effective_bot_keys (const std::vector<key_type>& common) const noexcept
+ {
+ return !bot_keys.empty () ? bot_keys : common;
+ }
+
// Return the configuration's build notification emails if they override
// the specified common build notification emails and return the latter
// otherwise (see package_manifest::override() for the override semantics
@@ -1058,6 +1146,8 @@ namespace bpkg
}
};
+ using build_package_config = build_package_config_template<std::string>;
+
enum class test_dependency_type
{
tests,
@@ -1205,11 +1295,16 @@ namespace bpkg
std::vector<requirement_alternatives> requirements;
butl::small_vector<test_dependency, 1> tests;
- // Common build classes/constraints that apply to all configurations
- // unless overridden.
+ // Common build classes, constraints, auxiliaries, and custom bot public
+ // keys that apply to all configurations unless overridden.
+ //
+ // Note that all entries in build_auxiliaries must have distinct
+ // environment names (with empty name being one of the possibilities).
//
butl::small_vector<build_class_expr, 1> builds;
std::vector<build_constraint> build_constraints;
+ std::vector<build_auxiliary> build_auxiliaries;
+ strings build_bot_keys;
// Note that the parsing constructor adds the implied (empty) default
// configuration at the beginning of the list. Also note that serialize()
@@ -1357,23 +1452,31 @@ namespace bpkg
// any value is invalid, cannot be overridden, or its name is not
// recognized.
//
- // The specified values override the whole groups they belong to,
- // resetting all the group values prior to being applied. Currently, only
- // the following value groups can be overridden:
+ // The specified values other than [*-]build-auxiliary[-*] override the
+ // whole groups they belong to, resetting all the group values prior to
+ // being applied. The [*-]build-auxiliary[-*] values only override the
+ // matching values, which are expected to already be present in the
+ // manifest. Currently, only the following value groups/values can be
+ // overridden:
//
// {build-*email}
// {builds, build-{include,exclude}}
+ // {build-bot}
// {*-builds, *-build-{include,exclude}}
+ // {*-build-bot}
// {*-build-config}
// {*-build-*email}
//
+ // [*-]build-auxiliary[-*]
+ //
// Throw manifest_parsing if the configuration specified by the build
- // package configuration-specific build constraints or emails group value
- // overrides doesn't exists. In contrast, for the build config override
- // add a new configuration if it doesn't exist and update the arguments of
- // the existing configuration otherwise. In the former case, all the
- // potential build constraints and emails overrides for such a newly added
- // configuration must follow the respective *-build-config override.
+ // package configuration-specific build constraint, email, auxiliary, or
+ // custom bot public key value override doesn't exists. In contrast, for
+ // the build config override add a new configuration if it doesn't exist
+ // and update the arguments of the existing configuration otherwise. In
+ // the former case, all the potential build constraint, email, auxiliary,
+ // and bot key overrides for such a newly added configuration must follow
+ // the respective *-build-config override.
//
// Note that the build constraints group values (both common and build
// config-specific) are overridden hierarchically so that the
@@ -1388,13 +1491,20 @@ namespace bpkg
// constraints are reset to `builds: none`.
//
// Similar to the build constraints groups, the common and build
- // config-specific build emails group value overrides are mutually
- // exclusive. If the common build emails are overridden, then all the
- // build config-specific emails are reset to nullopt. Otherwise, if some
- // build config-specific emails are overridden, then for the remaining
- // configs the email is reset to the empty value and the warning and error
- // emails are reset to nullopt (which effectively disables email
- // notifications for such configurations).
+ // config-specific custom bot key value overrides are mutually
+ // exclusive. If the common custom bot keys are overridden, then all the
+ // build config-specific custom bot keys are removed. Otherwise, if some
+ // build config-specific custom bot keys are overridden, then for the
+ // remaining configs the custom bot keys are left unchanged.
+ //
+ // Similar to the above, the common and build config-specific build emails
+ // group value overrides are mutually exclusive. If the common build
+ // emails are overridden, then all the build config-specific emails are
+ // reset to nullopt. Otherwise, if some build config-specific emails are
+ // overridden, then for the remaining configs the email is reset to the
+ // empty value and the warning and error emails are reset to nullopt
+ // (which effectively disables email notifications for such
+ // configurations).
//
// If a non-empty source name is specified, then the specified values are
// assumed to also include the line/column information and the possibly
diff --git a/tests/manifest/testscript b/tests/manifest/testscript
index 4f6433b..d7ec37f 100644
--- a/tests/manifest/testscript
+++ b/tests/manifest/testscript
@@ -1048,6 +1048,225 @@
EOI
}
+ : build-auxiliary
+ :
+ {
+ : named
+ :
+ {
+ $* <<EOF >>EOF
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary-pgsql: *-postgresql_*
+ build-auxiliary-mysql: *-mysql_*
+ EOF
+ }
+
+ : unnamed
+ :
+ {
+ $* <<EOF >>EOF
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary: *-postgresql**
+ EOF
+ }
+
+ : empty-config-pattern
+ :
+ {
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary:
+ EOI
+ stdin:6:17: error: empty build auxiliary configuration name pattern
+ EOE
+ }
+
+ : mixed
+ :
+ {
+ : named-unnamed
+ :
+ {
+ $* <<EOF >>EOF
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary-pgsql: *-postgresql**
+ build-auxiliary: *-mysql**
+ EOF
+ }
+
+ : unnamed-named
+ :
+ {
+ $* <<EOF >>EOF
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary: *-mysql**
+ build-auxiliary-pgsql: *-postgresql**
+ EOF
+ }
+
+ : unnamed-unnamed
+ :
+ {
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary: *-mysql**
+ build-auxiliary: *-postgresql**
+ EOI
+ stdin:7:1: error: build auxiliary environment redefinition
+ EOE
+ }
+
+ : redefinition
+ :
+ {
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary-pgsql: *-postgresql**
+ build-auxiliary-pgsql: *-postgresql**
+ EOI
+ stdin:7:1: error: build auxiliary environment redefinition
+ EOE
+ }
+ }
+ }
+
+ : build-bot
+ :
+ {
+ : basics
+ :
+ {
+ $* <<EOF >>EOF
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-bot:\
+ -----BEGIN PUBLIC KEY-----
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw5liP5pyU9ebC/nD3djZ
+ 1H2dlKmUyiX0Z8POvKhLREd0B3rM59bPcnbRB4HMIhj0J0hUBvS8xb4u5udCPToa
+ x0A/LMWZ6claiivNtJ3CdLV98eklWdNUg5WXOuqq9QDKXw2ZpGbwDwCOh6aHSWVq
+ 98N9AQx0ZMmMWz3qhRyxPfh+GeJ05uj2ohU9FeUJxeqUcgJT/UcMZ3+7KYbwr+Uq
+ /HCoX1BmN6nvzhQGHvJIZ2IcjvOQ0AUrPmpSZN01Zr3ZEpkHM3hJWNLu3ntJLGBQ
+ 0aT5kG3iqFyr9q3M3c4J8c0AWrnDjvj0qnCyjNwqW+qIpatmCNT43DmgYr9fQLW0
+ UHusburz53AbXs12zu3gZzkb0irlShatkMqqQaqaU0/+zw1LnoZ+rvmn2XV97UuK
+ LFKMKXCnyi2ZG65IZHGkjBVAPuvsX6RgLNyner/QtkDJTbfhktInbG08dCPqv1EF
+ 1OtcYKMTn8I5P2VmMO6SXXDLMSdU8b5DA5EY6Ca6JBB8g06S9sqGqXgQFysAnZs1
+ VFgMopf8WZqj23x+DX+9KKT2pVnjbwRvBAntuCDoO75gWoETDnCQXEei/PbyamPq
+ 9+NjNsTDn67iJTGncZbII+eciY2YiFHm6GMzBPsUYlQcxiuO4X36jW6m2rwuw37K
+ oFDbGI3uY4LnhwmDFLbjtk8CAwEAAQ==
+ -----END PUBLIC KEY-----
+ \
+ build-bot:\
+ -----BEGIN PUBLIC KEY-----
+ AIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw5liP5pyU9ebC/nD3djZ
+ 2H2dlKmUyiX0Z8POvKhLREd0B3rM59bPcnbRB4HMIhj0J0hUBvS8xb4u5udCPToa
+ x0A/LMWZ6claiivNtJ3CdLV98eklWdNUg5WXOuqq9QDKXw2ZpGbwDwCOh6aHSWVq
+ 98N9AQx0ZMmMWz3qhRyxPfh+GeJ05uj2ohU9FeUJxeqUcgJT/UcMZ3+7KYbwr+Uq
+ /HCoX1BmN6nvzhQGHvJIZ2IcjvOQ0AUrPmpSZN01Zr3ZEpkHM3hJWNLu3ntJLGBQ
+ 0aT5kG3iqFyr9q3M3c4J8c0AWrnDjvj0qnCyjNwqW+qIpatmCNT43DmgYr9fQLW0
+ UHusburz53AbXs12zu3gZzkb0irlShatkMqqQaqaU0/+zw1LnoZ+rvmn2XV97UuK
+ LFKMKXCnyi2ZG65IZHGkjBVAPuvsX6RgLNyner/QtkDJTbfhktInbG08dCPqv1EF
+ 1OtcYKMTn8I5P2VmMO6SXXDLMSdU8b5DA5EY6Ca6JBB8g06S9sqGqXgQFysAnZs1
+ VFgMopf8WZqj23x+DX+9KKT2pVnjbwRvBAntuCDoO75gWoETDnCQXEei/PbyamPq
+ 9+NjNsTDn67iJTGncZbII+eciY2YiFHm6GMzBPsUYlQcxiuO4X36jW6m2rwuw37K
+ oFDbGI3uY4LnhwmDFLbjtk8CAwEAAQ==
+ -----END PUBLIC KEY-----
+ \
+ EOF
+ }
+
+ : empty
+ :
+ {
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-bot:
+ EOI
+ stdin:6:11: error: empty custom build bot public key
+ EOE
+ }
+
+ : duplicate
+ :
+ {
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-bot:\
+ -----BEGIN PUBLIC KEY-----
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw5liP5pyU9ebC/nD3djZ
+ 1H2dlKmUyiX0Z8POvKhLREd0B3rM59bPcnbRB4HMIhj0J0hUBvS8xb4u5udCPToa
+ x0A/LMWZ6claiivNtJ3CdLV98eklWdNUg5WXOuqq9QDKXw2ZpGbwDwCOh6aHSWVq
+ 98N9AQx0ZMmMWz3qhRyxPfh+GeJ05uj2ohU9FeUJxeqUcgJT/UcMZ3+7KYbwr+Uq
+ /HCoX1BmN6nvzhQGHvJIZ2IcjvOQ0AUrPmpSZN01Zr3ZEpkHM3hJWNLu3ntJLGBQ
+ 0aT5kG3iqFyr9q3M3c4J8c0AWrnDjvj0qnCyjNwqW+qIpatmCNT43DmgYr9fQLW0
+ UHusburz53AbXs12zu3gZzkb0irlShatkMqqQaqaU0/+zw1LnoZ+rvmn2XV97UuK
+ LFKMKXCnyi2ZG65IZHGkjBVAPuvsX6RgLNyner/QtkDJTbfhktInbG08dCPqv1EF
+ 1OtcYKMTn8I5P2VmMO6SXXDLMSdU8b5DA5EY6Ca6JBB8g06S9sqGqXgQFysAnZs1
+ VFgMopf8WZqj23x+DX+9KKT2pVnjbwRvBAntuCDoO75gWoETDnCQXEei/PbyamPq
+ 9+NjNsTDn67iJTGncZbII+eciY2YiFHm6GMzBPsUYlQcxiuO4X36jW6m2rwuw37K
+ oFDbGI3uY4LnhwmDFLbjtk8CAwEAAQ==
+ -----END PUBLIC KEY-----
+ \
+ build-bot:\
+ -----BEGIN PUBLIC KEY-----
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw5liP5pyU9ebC/nD3djZ
+ 1H2dlKmUyiX0Z8POvKhLREd0B3rM59bPcnbRB4HMIhj0J0hUBvS8xb4u5udCPToa
+ x0A/LMWZ6claiivNtJ3CdLV98eklWdNUg5WXOuqq9QDKXw2ZpGbwDwCOh6aHSWVq
+ 98N9AQx0ZMmMWz3qhRyxPfh+GeJ05uj2ohU9FeUJxeqUcgJT/UcMZ3+7KYbwr+Uq
+ /HCoX1BmN6nvzhQGHvJIZ2IcjvOQ0AUrPmpSZN01Zr3ZEpkHM3hJWNLu3ntJLGBQ
+ 0aT5kG3iqFyr9q3M3c4J8c0AWrnDjvj0qnCyjNwqW+qIpatmCNT43DmgYr9fQLW0
+ UHusburz53AbXs12zu3gZzkb0irlShatkMqqQaqaU0/+zw1LnoZ+rvmn2XV97UuK
+ LFKMKXCnyi2ZG65IZHGkjBVAPuvsX6RgLNyner/QtkDJTbfhktInbG08dCPqv1EF
+ 1OtcYKMTn8I5P2VmMO6SXXDLMSdU8b5DA5EY6Ca6JBB8g06S9sqGqXgQFysAnZs1
+ VFgMopf8WZqj23x+DX+9KKT2pVnjbwRvBAntuCDoO75gWoETDnCQXEei/PbyamPq
+ 9+NjNsTDn67iJTGncZbII+eciY2YiFHm6GMzBPsUYlQcxiuO4X36jW6m2rwuw37K
+ oFDbGI3uY4LnhwmDFLbjtk8CAwEAAQ==
+ -----END PUBLIC KEY-----
+ \
+ EOI
+ stdin:23:1: error: duplicate custom build bot public key
+ EOE
+ }
+ }
+
: build-config
:
{
@@ -1112,6 +1331,115 @@
EOI
}
+ : auxiliary
+ {
+ : named
+ :
+ {
+ $* <<EOF >>EOF
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ bar-build-auxiliary-pgsql: *-postgresql_*
+ baz-build-auxiliary-mysql: *-mysql_*
+ EOF
+ }
+
+ : unnamed
+ :
+ {
+ $* <<EOF >>EOF
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ bar-build-auxiliary: *-postgresql**
+ EOF
+ }
+
+ : empty-config-pattern
+ :
+ {
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ bar-build-auxiliary:
+ EOI
+ stdin:6:21: error: empty build auxiliary configuration name pattern
+ EOE
+ }
+
+ : mixed
+ :
+ {
+ : named-unnamed
+ :
+ {
+ $* <<EOF >>EOF
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ bar-build-auxiliary-pgsql: *-postgresql**
+ bar-build-auxiliary: *-mysql**
+ EOF
+ }
+
+ : unnamed-named
+ :
+ {
+ $* <<EOF >>EOF
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ bar-build-auxiliary: *-mysql**
+ bar-build-auxiliary-pgsql: *-postgresql**
+ EOF
+ }
+
+ : unnamed-unnamed
+ :
+ {
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ bar-build-auxiliary: *-mysql**
+ bar-build-auxiliary: *-postgresql**
+ EOI
+ stdin:7:1: error: build auxiliary environment redefinition
+ EOE
+ }
+
+ : redefinition
+ :
+ {
+ $* <<EOI 2>>EOE != 0
+ : 1
+ name: foo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ bar-build-auxiliary-pgsql: *-postgresql**
+ bar-build-auxiliary-pgsql: *-postgresql**
+ EOI
+ stdin:7:1: error: build auxiliary environment redefinition
+ EOE
+ }
+ }
+ }
+
: email
:
{
diff --git a/tests/overrides/testscript b/tests/overrides/testscript
index ba66b7f..a903d05 100644
--- a/tests/overrides/testscript
+++ b/tests/overrides/testscript
@@ -254,6 +254,153 @@
license: LGPLv2
build-email: foo@example.com
EOO
+
+ : build-auxiliary
+ :
+ {
+ : named
+ :
+ $* 'build-auxiliary-pgsql: *-postgresql**' \
+ 'foo-build-auxiliary-oracle: *-oracle**' <<EOI >>EOO
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary-pgsql: *-postgresql_*
+ build-auxiliary-mysql: *-mysql_*
+ foo-build-auxiliary-mssql: *-mssql_*
+ foo-build-auxiliary-oracle: *-oracle_*
+ EOI
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary-pgsql: *-postgresql**
+ build-auxiliary-mysql: *-mysql_*
+ foo-build-auxiliary-mssql: *-mssql_*
+ foo-build-auxiliary-oracle: *-oracle**
+ EOO
+
+ : unnamed
+ :
+ $* 'build-auxiliary: *-postgresql**' \
+ 'foo-build-auxiliary: *-oracle**' <<EOI >>EOO
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary: *-postgresql_*
+ foo-build-auxiliary: *-oracle_*
+ EOI
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary: *-postgresql**
+ foo-build-auxiliary: *-oracle**
+ EOO
+
+ : new-config
+ :
+ $* 'bar-build-config:' \
+ 'bar-build-auxiliary-mysql: *-mysql_8' \
+ 'bar-build-auxiliary-pgsql: *-postgresql_16' <<EOI >>EOO
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary-pgsql: *-postgresql_*
+ build-auxiliary-mssql: *-mssql_*
+ foo-build-auxiliary-mysql: *-mysql_*
+ foo-build-auxiliary-oracle: *-oracle_*
+ EOI
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary-pgsql: *-postgresql_*
+ build-auxiliary-mssql: *-mssql_*
+ foo-build-auxiliary-mysql: *-mysql_*
+ foo-build-auxiliary-oracle: *-oracle_*
+ bar-build-auxiliary-mysql: *-mysql_8
+ bar-build-auxiliary-pgsql: *-postgresql_16
+ EOO
+ }
+
+ : build-bot
+ :
+ {
+ : common
+ :
+ $* 'build-bot: key3' 'build-bot: key4' <<EOI >>EOO
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-bot: key1
+ foo-build-bot: key2
+ EOI
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-bot: key3
+ build-bot: key4
+ EOO
+
+ : config
+ :
+ $* 'foo-build-bot: key3' 'foo-build-bot: key4' <<EOI >>EOO
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-bot: key1
+ foo-build-bot: key2
+ EOI
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-bot: key1
+ foo-build-bot: key3
+ foo-build-bot: key4
+ EOO
+
+ : new-config
+ :
+ $* 'bar-build-config:' \
+ 'bar-build-bot: key1' \
+ 'bar-build-bot: key2' <<EOI >>EOO
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-bot: key1
+ foo-build-bot: key2
+ EOI
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-bot: key1
+ foo-build-bot: key2
+ bar-build-bot: key1
+ bar-build-bot: key2
+ EOO
+ }
}
: invalid
@@ -370,6 +517,44 @@
cannot override 'deprecated-api-builds' value: no build package configuration 'deprecated-api'
EOE
+ : config-bot-after-built-bot
+ :
+ $* 'build-bot: key1' 'foo-build-bot: key2' <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ foo-build-config:
+ EOI
+ 'foo-build-bot' override specified together with 'build-bot' override
+ EOE
+
+ : built-bot-after-config-bot
+ :
+ $* 'foo-build-bot: key1' 'build-bot: key2' <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ foo-build-config:
+ EOI
+ 'build-bot' override specified together with 'foo-build-bot' override
+ EOE
+
+ : no-build-bot-config
+ :
+ $* 'foo-build-bot: key1' <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ EOI
+ cannot override 'foo-build-bot' value: no build package configuration 'foo'
+ EOE
+
: config-email-after-email
:
$* 'build-email: foo@example.com' 'network-build-warning-email: warning@example.com' <<EOI 2>>EOE != 0
@@ -395,4 +580,95 @@
EOI
'build-email' override specified together with 'network-build-warning-email' override
EOE
+
+ : build-auxiliary
+ :
+ {
+ : named-common
+ :
+ $* 'build-auxiliary-mysql: *-mysql_*' <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary-pgsql: *-postgresql_*
+ foo-build-auxiliary-mssql: *-mssql_*
+ foo-build-auxiliary-oracle: *-oracle_*
+ EOI
+ no match for 'build-auxiliary-mysql' value override
+ EOE
+
+ : named-config1
+ :
+ $* 'foo-build-auxiliary-mysql: *-mysql_*' <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary-pgsql: *-postgresql_*
+ foo-build-auxiliary-mssql: *-mssql_*
+ foo-build-auxiliary-oracle: *-oracle_*
+ EOI
+ no match for 'foo-build-auxiliary-mysql' value override
+ EOE
+
+ : named-config2
+ :
+ $* 'bar-build-auxiliary-oracle: *-oracle**' <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary-pgsql: *-postgresql_*
+ foo-build-auxiliary-mssql: *-mssql_*
+ foo-build-auxiliary-oracle: *-oracle_*
+ EOI
+ cannot override 'bar-build-auxiliary-oracle' value: no build package configuration 'bar'
+ EOE
+
+ : unnamed-common
+ :
+ $* 'build-auxiliary-mysql: *-mysql_*' <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary: *-postgresql_*
+ foo-build-auxiliary: *-oracle_*
+ EOI
+ no match for 'build-auxiliary-mysql' value override
+ EOE
+
+ : unnamed-config1
+ :
+ $* 'foo-build-auxiliary-mysql: *-mysql_*' <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary: *-postgresql_*
+ foo-build-auxiliary: *-oracle_*
+ EOI
+ no match for 'foo-build-auxiliary-mysql' value override
+ EOE
+
+ : unnamed-config2
+ :
+ $* 'bar-build-auxiliary: *-mysql_*' <<EOI 2>>EOE != 0
+ : 1
+ name: libfoo
+ version: 2.0.0
+ summary: Modern C++ parser
+ license: LGPLv2
+ build-auxiliary: *-postgresql_*
+ foo-build-auxiliary: *-oracle_*
+ EOI
+ cannot override 'bar-build-auxiliary' value: no build package configuration 'bar'
+ EOE
+ }
}