diff options
Diffstat (limited to 'mod/build-config-module.cxx')
-rw-r--r-- | mod/build-config-module.cxx | 288 |
1 files changed, 22 insertions, 266 deletions
diff --git a/mod/build-config-module.cxx b/mod/build-config-module.cxx index 13f61b7..97c9f9e 100644 --- a/mod/build-config-module.cxx +++ b/mod/build-config-module.cxx @@ -1,5 +1,4 @@ // file : mod/build-config-module.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #include <mod/build-config-module.hxx> @@ -9,37 +8,35 @@ #include <map> #include <sstream> -#include <libbutl/sha256.mxx> -#include <libbutl/utility.mxx> // throw_generic_error(), alpha(), etc. -#include <libbutl/openssl.mxx> -#include <libbutl/filesystem.mxx> // dir_iterator, dir_entry -#include <libbutl/path-pattern.mxx> +#include <libbutl/sha256.hxx> +#include <libbutl/utility.hxx> // throw_generic_error() +#include <libbutl/openssl.hxx> +#include <libbutl/filesystem.hxx> // dir_iterator, dir_entry namespace brep { using namespace std; using namespace butl; using namespace bpkg; - using namespace bbot; - // Return pointer to the shared build configurations instance, creating one - // on the first call. Throw tab_parsing on parsing error, io_error on the - // underlying OS error. Note: not thread-safe. + // Return pointer to the shared build target configurations instance, + // creating one on the first call. Throw tab_parsing on parsing error, + // io_error on the underlying OS error. Note: not thread-safe. // - static shared_ptr<const build_configs> + static shared_ptr<const build_target_configs> shared_build_config (const path& p) { - static map<path, weak_ptr<build_configs>> configs; + static map<path, weak_ptr<build_target_configs>> configs; auto i (configs.find (p)); if (i != configs.end ()) { - if (shared_ptr<build_configs> c = i->second.lock ()) + if (shared_ptr<build_target_configs> c = i->second.lock ()) return c; } - shared_ptr<build_configs> c ( - make_shared<build_configs> (parse_buildtab (p))); + shared_ptr<build_target_configs> c ( + make_shared<build_target_configs> (bbot::parse_buildtab (p))); configs[p] = c; return c; @@ -74,7 +71,7 @@ namespace brep try { - for (const dir_entry& de: dir_iterator (d, false /* ignore_dangling */)) + for (const dir_entry& de: dir_iterator (d, dir_iterator::no_follow)) { if (de.path ().extension () == "pem" && de.type () == entry_type::regular) @@ -111,7 +108,7 @@ namespace brep catch (const system_error& e) { ostringstream os; - os<< "unable to iterate over agents keys directory '" << d << "'"; + os << "unable to iterate over agents keys directory '" << d << "'"; throw_generic_error (e.code ().value (), os.str ().c_str ()); } @@ -124,7 +121,7 @@ namespace brep { try { - build_conf_ = shared_build_config (bo.build_config ()); + target_conf_ = shared_build_config (bo.build_config ()); } catch (const io_error& e) { @@ -139,207 +136,21 @@ namespace brep bot_agent_key_map_ = shared_bot_agent_keys (bo, bo.build_bot_agent_keys ()); - cstrings conf_names; - - using conf_map_type = map<const char*, - const build_config*, - compare_c_string>; + using conf_map_type = map<build_target_config_id, + const build_target_config*>; conf_map_type conf_map; - for (const auto& c: *build_conf_) - { - const char* cn (c.name.c_str ()); - conf_map[cn] = &c; - conf_names.push_back (cn); - } - - build_conf_names_ = make_shared<cstrings> (move (conf_names)); - build_conf_map_ = make_shared<conf_map_type> (move (conf_map)); - } - - // The default underlying class set expression (see below). - // - static const build_class_expr default_ucs_expr ( - {"default"}, '+', "Default."); - - bool build_config_module:: - exclude (const small_vector<build_class_expr, 1>& exprs, - const vector<build_constraint>& constrs, - const build_config& cfg, - string* reason) const - { - // Save the first sentence of the reason, lower-case the first letter if - // the beginning looks like a word (all subsequent characters until a - // whitespace are lower-case letters). - // - auto sanitize = [] (const string& reason) - { - string r (reason.substr (0, reason.find ('.'))); - - char c (r[0]); // Can be '\0'. - if (alpha (c) && c == ucase (c)) - { - bool word (true); - - for (size_t i (1); - i != r.size () && (c = r[i]) != ' ' && c != '\t' && c != '\n'; - ++i) - { - // Is not a word if contains a non-letter or an upper-case letter. - // - if (!alpha (c) || c == ucase (c)) - { - word = false; - break; - } - } - - if (word) - r[0] = lcase (r[0]); - } - - return r; - }; - - // First, match the configuration against the package underlying build - // class set and expressions. - // - bool m (false); - - // Match the configuration against an expression, updating the match - // result. - // - // We will use a comment of the first encountered excluding expression - // (changing the result from true to false) or non-including one (leaving - // the false result) as an exclusion reason. - // - auto match = [&cfg, &m, reason, &sanitize, this] - (const build_class_expr& e) - { - bool pm (m); - e.match (cfg.classes, build_conf_->class_inheritance_map, m); - - if (reason != nullptr) - { - // Reset the reason which, if saved, makes no sense anymore. - // - if (m) - { - reason->clear (); - } - else if (reason->empty () && - // - // Exclusion. - // - (pm || - // - // Non-inclusion. Make sure that the build class expression - // is empty or starts with an addition (+...). - // - e.expr.empty () || - e.expr.front ().operation == '+')) - { - *reason = sanitize (e.comment); - } - } - }; - - // Determine the underlying class set. Note that in the future we can - // potentially extend the underlying set with special classes. - // - const build_class_expr* ucs ( - !exprs.empty () && !exprs.front ().underlying_classes.empty () - ? &exprs.front () - : nullptr); - - // Note that the combined package build configuration class expression can - // be represented as the underlying class set used as a starting set for - // the original expressions and a restricting set, simultaneously. For - // example, for the expression: - // - // default legacy : -msvc - // - // the resulting expression will be: - // - // +( +default +legacy ) -msvc &( +default +legacy ) - // - // Let's, however, optimize it a bit based on the following facts: - // - // - If the underlying class set expression (+default +legacy in the above - // example) evaluates to false, then the resulting expression also - // evaluates to false due to the trailing '&' operation. Thus, we don't - // need to evaluate further if that's the case. - // - // - On the other hand, if the underlying class set expression evaluates - // to true, then we don't need to apply the trailing '&' operation as it - // cannot affect the result. - // - const build_class_expr& ucs_expr ( - ucs != nullptr - ? build_class_expr (ucs->underlying_classes, '+', ucs->comment) - : default_ucs_expr); - - match (ucs_expr); - - if (m) - { - for (const build_class_expr& e: exprs) - match (e); - } + for (const auto& c: *target_conf_) + conf_map[build_target_config_id {c.target, c.name}] = &c; - // Exclude the configuration if it doesn't match the compound expression. - // - if (!m) - return true; - - // Now check if the configuration is excluded/included via the patterns. - // - // To implement matching of absent name components with wildcard-only - // pattern components we are going to convert names to paths (see - // dash_components_to_path() for details). - // - // And if any of the build-{include,exclude} values (which is legal) or - // the build configuration name/target (illegal) are invalid paths, then - // we assume no match. - // - if (!constrs.empty ()) - try - { - path cn (dash_components_to_path (cfg.name)); - path tg (dash_components_to_path (cfg.target.string ())); - - for (const build_constraint& c: constrs) - { - if (path_match (cn, - dash_components_to_path (c.config), - dir_path () /* start */, - path_match_flags::match_absent) && - (!c.target || - path_match (tg, - dash_components_to_path (*c.target), - dir_path () /* start */, - path_match_flags::match_absent))) - { - if (!c.exclusion) - return false; - - if (reason != nullptr) - *reason = sanitize (c.comment); - - return true; - } - } - } - catch (const invalid_path&) {} - - return false; + target_conf_map_ = make_shared<conf_map_type> (move (conf_map)); } bool build_config_module:: - belongs (const bbot::build_config& cfg, const char* cls) const + belongs (const build_target_config& cfg, const char* cls) const { - const map<string, string>& im (build_conf_->class_inheritance_map); + const map<string, string>& im (target_conf_->class_inheritance_map); for (const string& c: cfg.classes) { @@ -361,59 +172,4 @@ namespace brep return false; } - - path build_config_module:: - dash_components_to_path (const string& pattern) - { - string r; - size_t nstar (0); - for (const path_pattern_term& pt: path_pattern_iterator (pattern)) - { - switch (pt.type) - { - case path_pattern_term_type::star: - { - // Replace ** with */**/* and skip all the remaining stars that may - // follow in this sequence. - // - if (nstar == 0) - r += "*"; - else if (nstar == 1) - r += "/**/*"; // The first star is already copied. - - break; - } - case path_pattern_term_type::literal: - { - // Replace '-' with '/' and fall through otherwise. - // - if (get_literal (pt) == '-') - { - r += '/'; - break; - } - } - // Fall through. - default: - { - r.append (pt.begin, pt.end); // Copy the pattern term as is. - } - } - - nstar = pt.star () ? nstar + 1 : 0; - } - - // Append the trailing slash to match the resulting paths as directories. - // This is required for the trailing /* we could append to match absent - // directory path components (see path_match_flags::match_absent for - // details). - // - // Note that valid dash components may not contain a trailing dash. - // Anyway, any extra trailing slashes will be ignored by the path - // constructor. - // - r += '/'; - - return path (move (r)); - } } |