From fbabb3ddf7f9bee71a6be767cc911b5b3b96333a Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 7 Dec 2018 21:38:00 +0300 Subject: Add support for build configuration class inheritance --- libbpkg/manifest.cxx | 43 ++++++++++++++++++++++++++++++++------- libbpkg/manifest.hxx | 27 +++++++++++++++++------- tests/build-class-expr/driver.cxx | 25 ++++++++++++++++++----- tests/build-class-expr/testscript | 17 ++++++++++++++++ 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& 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 #include #include #include @@ -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; + // 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] [] +// argv[0] [[:]]* // // 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 + } } -- cgit v1.1