aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2018-12-07 21:38:00 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2018-12-11 13:59:03 +0300
commitfbabb3ddf7f9bee71a6be767cc911b5b3b96333a (patch)
treeaa3b31024f2fb0c6b53961afbfe9de2a6ba29cb8
parentb05ca3928c826b46a087f3e1f8ff24069c65ff0b (diff)
Add support for build configuration class inheritance
-rw-r--r--libbpkg/manifest.cxx43
-rw-r--r--libbpkg/manifest.hxx27
-rw-r--r--tests/build-class-expr/driver.cxx25
-rw-r--r--tests/build-class-expr/testscript17
4 files changed, 93 insertions, 19 deletions
diff --git a/libbpkg/manifest.cxx b/libbpkg/manifest.cxx
index 73d2311..8782409 100644
--- a/libbpkg/manifest.cxx
+++ b/libbpkg/manifest.cxx
@@ -1179,6 +1179,7 @@ namespace bpkg
//
static void
match_classes (const strings& cs,
+ const build_class_inheritance_map& im,
const vector<build_class_term>& expr,
bool& r)
{
@@ -1191,18 +1192,44 @@ namespace bpkg
if ((t.operation == '+') == r)
continue;
- bool m;
+ bool m (false);
// We don't expect the class list to be long, so the linear search should
// be fine.
//
if (t.simple)
- m = find (cs.begin (), cs.end (), t.name) != cs.end ();
- else
{
- m = false;
- match_classes (cs, t.expr, m);
+ // Check if any of the classes or their bases match the term name.
+ //
+ for (const string& c: cs)
+ {
+ m = (c == t.name);
+
+ if (!m)
+ {
+ // Go through base classes.
+ //
+ for (auto i (im.find (c)); i != im.end (); )
+ {
+ const string& base (i->second);
+
+ // Bail out if the base class matches.
+ //
+ m = (base == t.name);
+
+ if (m)
+ break;
+
+ i = im.find (base);
+ }
+ }
+
+ if (m)
+ break;
+ }
}
+ else
+ match_classes (cs, im, t.expr, m);
if (t.inverted)
m = !m;
@@ -1218,9 +1245,11 @@ namespace bpkg
}
void build_class_expr::
- match (const strings& cs, bool& r) const
+ match (const strings& cs,
+ const build_class_inheritance_map& im,
+ bool& r) const
{
- match_classes (cs, expr, r);
+ match_classes (cs, im, expr, r);
}
// pkg_package_manifest
diff --git a/libbpkg/manifest.hxx b/libbpkg/manifest.hxx
index 55e9d15..fc61511 100644
--- a/libbpkg/manifest.hxx
+++ b/libbpkg/manifest.hxx
@@ -5,6 +5,7 @@
#ifndef LIBBPKG_MANIFEST_HXX
#define LIBBPKG_MANIFEST_HXX
+#include <map>
#include <string>
#include <vector>
#include <cassert>
@@ -476,6 +477,10 @@ namespace bpkg
validate_name (const std::string&);
};
+ // Map of derived build classes to their bases.
+ //
+ using build_class_inheritance_map = std::map<std::string, std::string>;
+
// Build configuration class expression. Includes comment and optional
// underlying set.
//
@@ -527,20 +532,28 @@ namespace bpkg
string () const;
// Match a build configuration that belongs to the specified list of
- // classes against the expression. Either return or update the result (the
- // latter allows to sequentially matching against a list of expressions).
+ // classes (and recursively to their bases) against the expression. Either
+ // return or update the result (the latter allows to sequentially matching
+ // against a list of expressions).
+ //
+ // Notes:
+ //
+ // - The derived-to-base map is not verified (that there are no
+ // inheritance cycles, etc.).
//
- // Note: the underlying class set doesn't affect the match in any way (it
- // should have been used to pre-filter the set of build configurations).
+ // - The underlying class set doesn't affect the match in any way (it
+ // should have been used to pre-filter the set of build configurations).
//
void
- match (const strings&, bool& result) const;
+ match (const strings&,
+ const build_class_inheritance_map&,
+ bool& result) const;
bool
- match (const strings& cs) const
+ match (const strings& cs, const build_class_inheritance_map& bs) const
{
bool r (false);
- match (cs, r);
+ match (cs, bs, r);
return r;
}
};
diff --git a/tests/build-class-expr/driver.cxx b/tests/build-class-expr/driver.cxx
index 343c3b5..586d459 100644
--- a/tests/build-class-expr/driver.cxx
+++ b/tests/build-class-expr/driver.cxx
@@ -14,7 +14,7 @@
// Usages:
//
// argv[0] -p
-// argv[0] [<classes>]
+// argv[0] [<class>[:<base>]]*
//
// Parse stdin lines as build configuration class expressions and print them
// or evaluate.
@@ -47,13 +47,28 @@ main (int argc, char* argv[])
cin.exceptions (ios::badbit);
strings cs;
+ build_class_inheritance_map im;
if (print)
cout.exceptions (ios::failbit | ios::badbit);
else
{
for (int i (1); i != argc; ++i)
- cs.push_back (argv[i]);
+ {
+ string c (argv[i]);
+
+ string base;
+ size_t p (c.find (':'));
+
+ if (p != string::npos)
+ {
+ base = string (c, p + 1);
+ c.resize (p);
+ }
+
+ im[c] = move (base);
+ cs.emplace_back (move (c));
+ }
}
try
@@ -77,18 +92,18 @@ main (int argc, char* argv[])
if (!underlying_cls->empty ())
{
build_class_expr expr (*underlying_cls, '+', "" /* comment */);
- expr.match (cs, r);
+ expr.match (cs, im, r);
}
}
- expr.match (cs, r);
+ expr.match (cs, im, r);
}
}
if (underlying_cls && !underlying_cls->empty ())
{
build_class_expr expr (*underlying_cls, '&', "" /* comment */);
- expr.match (cs, r);
+ expr.match (cs, im, r);
}
return print || r ? 0 : 1;
diff --git a/tests/build-class-expr/testscript b/tests/build-class-expr/testscript
index cfa1400..006d12d 100644
--- a/tests/build-class-expr/testscript
+++ b/tests/build-class-expr/testscript
@@ -88,6 +88,14 @@
{
$* <'+!x'
}
+
+ : base
+ :
+ {
+ test.arguments += a:x b:y c
+
+ $* <'+y'
+ }
}
: mismatch
@@ -122,4 +130,13 @@
{
$* <'+a' == 1
}
+
+
+ : base
+ :
+ {
+ test.arguments += a:x b:y c
+
+ $* <'+z' == 1
+ }
}