diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2018-12-07 23:12:05 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2018-12-11 14:05:48 +0300 |
commit | 294c558d577cd4acb2ee8e94e0dfd6acdb946c6c (patch) | |
tree | 02742141dad6cf91040eb48eca54b718dee8ad55 | |
parent | 7dabb6e931740b2777be5dca53c3cec0b984f0fb (diff) |
Add support for build configuration class inheritance
28 files changed, 418 insertions, 329 deletions
diff --git a/mod/build-config.cxx b/mod/build-config-module.cxx index 7e1416d..57c035f 100644 --- a/mod/build-config.cxx +++ b/mod/build-config-module.cxx @@ -1,30 +1,31 @@ -// file : mod/build-config.cxx -*- C++ -*- +// file : mod/build-config-module.cxx -*- C++ -*- // copyright : Copyright (c) 2014-2018 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -#include <mod/build-config.hxx> +#include <mod/build-config-module.hxx> + +#include <errno.h> // EIO #include <map> #include <sstream> -#include <algorithm> // replace() #include <libbutl/sha256.mxx> #include <libbutl/utility.mxx> // throw_generic_error(), alpha(), etc. #include <libbutl/openssl.mxx> #include <libbutl/filesystem.mxx> -#include <web/mime-url-encoding.hxx> - -#include <mod/utility.hxx> - namespace brep { using namespace std; - using namespace web; using namespace butl; + using namespace bpkg; using namespace bbot; - shared_ptr<const build_configs> + // 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. + // + static shared_ptr<const build_configs> shared_build_config (const path& p) { static map<path, weak_ptr<build_configs>> configs; @@ -43,19 +44,25 @@ namespace brep return c; } - shared_ptr<const bot_agent_keys> + // Return pointer to the shared build bot agent public keys map, creating + // one on the first call. Throw system_error on the underlying openssl or OS + // error. Note: not thread-safe. + // + using bot_agent_key_map = map<string, path>; + + static shared_ptr<const bot_agent_key_map> shared_bot_agent_keys (const options::openssl_options& o, const dir_path& d) { - static map<dir_path, weak_ptr<bot_agent_keys>> keys; + static map<dir_path, weak_ptr<bot_agent_key_map>> keys; auto i (keys.find (d)); if (i != keys.end ()) { - if (shared_ptr<bot_agent_keys> k = i->second.lock ()) + if (shared_ptr<bot_agent_key_map> k = i->second.lock ()) return k; } - shared_ptr<bot_agent_keys> ak (make_shared<bot_agent_keys> ()); + shared_ptr<bot_agent_key_map> ak (make_shared<bot_agent_key_map> ()); // Intercept exception handling to make error descriptions more // informative. @@ -111,50 +118,55 @@ namespace brep return ak; } - string - build_log_url (const string& host, const dir_path& root, - const build& b, - const string* op) + void build_config_module:: + init (const options::build& bo) { - // Note that '+' is the only package version character that potentially - // needs to be url-encoded, and only in the query part of the URL. We embed - // the package version into the URL path part and so don't encode it. - // - string url (host + tenant_dir (root, b.tenant).representation () + - mime_url_encode (b.package_name.string (), false) + '/' + - b.package_version.string () + "/log/" + - mime_url_encode (b.configuration, false) + '/' + - b.toolchain_version.string ()); + try + { + build_conf_ = shared_build_config (bo.build_config ()); + } + catch (const io_error& e) + { + ostringstream os; + os << "unable to read build configuration '" << bo.build_config () + << "': " << e; + + throw_generic_error (EIO, os.str ().c_str ()); + } - if (op != nullptr) + if (bo.build_bot_agent_keys_specified ()) + 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>; + + conf_map_type conf_map; + + for (const auto& c: *build_conf_) { - url += '/'; - url += *op; + const char* cn (c.name.c_str ()); + conf_map[cn] = &c; + conf_names.push_back (cn); } - return url; + build_conf_names_ = make_shared<cstrings> (move (conf_names)); + build_conf_map_ = make_shared<conf_map_type> (move (conf_map)); } - string - force_rebuild_url (const string& host, const dir_path& root, const build& b) - { - // Note that '+' is the only package version character that potentially - // needs to be url-encoded, and only in the query part of the URL. However - // we embed the package version into the URL query part, where it is not - // encoded by design. - // - return host + tenant_dir (root, b.tenant).string () + - "?build-force&pn=" + mime_url_encode (b.package_name.string ()) + - "&pv=" + b.package_version.string () + - "&cf=" + mime_url_encode (b.configuration) + - "&tc=" + b.toolchain_version.string () + "&reason="; - } + // The default underlying class set expression (see below). + // + static const build_class_expr default_ucs_expr ( + {"default"}, '+', "Default."); - bool - exclude (const build_class_exprs& exprs, - const build_constraints& constrs, + bool build_config_module:: + exclude (const vector<build_class_expr>& exprs, + const vector<build_constraint>& constrs, const build_config& cfg, - string* reason) + 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 @@ -189,50 +201,29 @@ namespace brep return r; }; - bool r (false); - // First, match the configuration against the package underlying build // class set and expressions. // - // Determine the underlying class set. Note that in the future we can - // potentially extend the underlying set with the special classes. - // - build_class_expr ucs ( - !exprs.empty () && !exprs.front ().underlying_classes.empty () - ? exprs.front () - : build_class_expr ("default", "Default")); + bool m (false); - // Transform the combined package build configuration class expression, - // making the underlying class set a starting set for the original - // expression and a restricting set, simultaneously. For example, for the - // expression: - // - // default legacy : -msvc - // - // the resulting expression will be: - // - // +default +legacy -msvc &( +default +legacy ) + // Match the configuration against an expression, updating the match + // result. // - // - build_class_exprs es; - es.emplace_back (ucs.underlying_classes, '+', ucs.comment); - es.insert (es.end (), exprs.begin (), exprs.end ()); - es.emplace_back (ucs.underlying_classes, '&', ucs.comment); - // 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. // - for (const build_class_expr& e: es) + auto match = [&cfg, &m, reason, &sanitize, this] + (const build_class_expr& e) { - bool pr (r); - e.match (cfg.classes, r); + 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 (r) + if (m) { reason->clear (); } @@ -240,7 +231,7 @@ namespace brep // // Exclusion. // - (pr || + (pm || // // Non-inclusion. Make sure that the build class expression // is empty or starts with an addition (+...). @@ -251,9 +242,54 @@ namespace brep *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); } - if (!r) + // 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. @@ -266,6 +302,7 @@ namespace brep // 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)); @@ -298,7 +335,7 @@ namespace brep return false; } - path + path build_config_module:: dash_components_to_path (const string& s) { string r; diff --git a/mod/build-config-module.hxx b/mod/build-config-module.hxx new file mode 100644 index 0000000..bd6e0b0 --- /dev/null +++ b/mod/build-config-module.hxx @@ -0,0 +1,96 @@ +// file : mod/build-config-module.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef MOD_BUILD_CONFIG_MODULE_HXX +#define MOD_BUILD_CONFIG_MODULE_HXX + +#include <map> +#include <algorithm> // find() + +#include <libbutl/utility.mxx> // compare_c_string + +#include <libbpkg/manifest.hxx> + +#include <libbbot/build-config.hxx> + +#include <libbrep/types.hxx> +#include <libbrep/utility.hxx> + +#include <mod/module.hxx> +#include <mod/options.hxx> + +// Base class for modules that utilize the build controller configuration. +// +// Specifically, it loads build controller configuration and provides various +// build configuration-related utilities. Note that the configuration is +// shared across multiple modules once loaded. +// +// Note that the build database is in the database_module. +// +namespace brep +{ + class build_config_module + { + protected: + // Parse build configuration file and establish mapping of build bot agent + // public keys fingerprints to their paths. Throw tab_parsing on parsing + // error, system_error on the underlying OS error. + // + void + init (const options::build&); + + // Return true if the specified build configuration is excluded by a + // package based on its underlying build class set, build class + // expressions, and build constraints, potentially extending the + // underlying set with the special classes. Set the exclusion reason if + // requested. + // + bool + exclude (const vector<bpkg::build_class_expr>&, + const vector<bpkg::build_constraint>&, + const bbot::build_config&, + string* reason = nullptr) const; + + // Check if the configuration belongs to the specified class. + // + // Note that the configuration base classes are not checked. + // + static bool + belongs (const bbot::build_config& cfg, const char* cls) + { + const strings& cs (cfg.classes); + return std::find (cs.begin (), cs.end (), cls) != cs.end (); + } + + // Convert dash-separated components (target, build configuration name, + // machine name) or a pattern thereof into a path, replacing dashes with + // slashes (directory separators), `**` with `*/**/*`, and appending the + // trailing slash for a subsequent match using the path_match() + // functionality (the idea here is for `linux**` to match `linux-gcc` + // which is quite natural to expect). Throw invalid_path if the resulting + // path is invalid. + // + // Note that the match_absent path match flag must be used for the above + // `**` transformation to work. + // + static path + dash_components_to_path (const string&); + + protected: + // Build configurations. + // + shared_ptr<const bbot::build_configs> build_conf_; + shared_ptr<const cstrings> build_conf_names_; + + shared_ptr<const std::map<const char*, + const bbot::build_config*, + butl::compare_c_string>> build_conf_map_; + + // Map of build bot agent public keys fingerprints to the key file paths. + // + shared_ptr<const std::map<string, path>> bot_agent_key_map_; + }; +} + +#endif // MOD_BUILD_CONFIG_MODULE_HXX diff --git a/mod/build-config.hxx b/mod/build-config.hxx deleted file mode 100644 index 6eece1d..0000000 --- a/mod/build-config.hxx +++ /dev/null @@ -1,99 +0,0 @@ -// file : mod/build-config.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef MOD_BUILD_CONFIG_HXX -#define MOD_BUILD_CONFIG_HXX - -#include <map> -#include <algorithm> // find() - -#include <libbbot/build-config.hxx> - -#include <libbrep/types.hxx> -#include <libbrep/utility.hxx> - -#include <libbrep/build.hxx> -#include <libbrep/build-package.hxx> - -#include <mod/options.hxx> - -// Various build-related state and utilities. -// -namespace brep -{ - using bbot::build_config; - - // 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. Is not thread-safe. - // - shared_ptr<const bbot::build_configs> - shared_build_config (const path&); - - // Map of build bot agent public keys fingerprints to the key file paths. - // - using bot_agent_keys = std::map<string, path>; - - // Return pointer to the shared build bot agent public keys map, creating - // one on the first call. Throw system_error on the underlying openssl or OS - // error. Not thread-safe. - // - shared_ptr<const bot_agent_keys> - shared_bot_agent_keys (const options::openssl_options&, const dir_path&); - - // Return the package configuration build log url. By default the url is to - // the operations combined log. - // - string - build_log_url (const string& host, const dir_path& root, - const build&, - const string* operation = nullptr); - - // Return the package configuration forced rebuild url. - // - string - force_rebuild_url (const string& host, const dir_path& root, const build&); - - // Check if the configuration belongs to the specified class. - // - inline bool - belongs (const build_config& cfg, const char* cls) - { - const strings& cs (cfg.classes); - return find (cs.begin (), cs.end (), cls) != cs.end (); - } - - // Return true if the specified build configuration is excluded by a package - // based on its underlying build class set, build class expressions, and - // build constraints, potentially extending the underlying set with the - // special classes. Set the exclusion reason if requested. - // - bool - exclude (const build_class_exprs&, - const build_constraints&, - const build_config&, - string* reason = nullptr); - - inline bool - exclude (const build_package& p, const build_config& c, string* r = nullptr) - { - return exclude (p.builds, p.constraints, c, r); - } - - // Convert dash-separated components (target, build configuration name, - // machine name) or a pattern thereof into a path, replacing dashes with - // slashes (directory separators), `**` with `*/**/*`, and appending the - // trailing slash for a subsequent match using the path_match() - // functionality (the idea here is for `linux**` to match `linux-gcc` which - // is quite natural to expect). Throw invalid_path if the resulting path is - // invalid. - // - // Note that the match_absent path match flag must be used for the above - // `**` transformation to work. - // - path - dash_components_to_path (const string&); -} - -#endif // MOD_BUILD_CONFIG_HXX diff --git a/mod/build.cxx b/mod/build.cxx new file mode 100644 index 0000000..6ad2b93 --- /dev/null +++ b/mod/build.cxx @@ -0,0 +1,53 @@ +// file : mod/build.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include <mod/build.hxx> + +#include <web/mime-url-encoding.hxx> + +#include <mod/utility.hxx> + +namespace brep +{ + using namespace web; + + string + build_log_url (const string& host, const dir_path& root, + const build& b, + const string* op) + { + // Note that '+' is the only package version character that potentially + // needs to be url-encoded, and only in the query part of the URL. We embed + // the package version into the URL path part and so don't encode it. + // + string url (host + tenant_dir (root, b.tenant).representation () + + mime_url_encode (b.package_name.string (), false) + '/' + + b.package_version.string () + "/log/" + + mime_url_encode (b.configuration, false) + '/' + + b.toolchain_version.string ()); + + if (op != nullptr) + { + url += '/'; + url += *op; + } + + return url; + } + + string + build_force_url (const string& host, const dir_path& root, const build& b) + { + // Note that '+' is the only package version character that potentially + // needs to be url-encoded, and only in the query part of the URL. However + // we embed the package version into the URL query part, where it is not + // encoded by design. + // + return host + tenant_dir (root, b.tenant).string () + + "?build-force&pn=" + mime_url_encode (b.package_name.string ()) + + "&pv=" + b.package_version.string () + + "&cf=" + mime_url_encode (b.configuration) + + "&tc=" + b.toolchain_version.string () + "&reason="; + } +} diff --git a/mod/build.hxx b/mod/build.hxx new file mode 100644 index 0000000..94c270b --- /dev/null +++ b/mod/build.hxx @@ -0,0 +1,31 @@ +// file : mod/build.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef MOD_BUILD_HXX +#define MOD_BUILD_HXX + +#include <libbrep/types.hxx> +#include <libbrep/utility.hxx> + +#include <libbrep/build.hxx> + +// Various package build-related utilities. +// +namespace brep +{ + // Return the package build log url. By default the url is to the operations + // combined log. + // + string + build_log_url (const string& host, const dir_path& root, + const build&, + const string* operation = nullptr); + + // Return the package build forced rebuild url. + // + string + build_force_url (const string& host, const dir_path& root, const build&); +} + +#endif // MOD_BUILD_HXX diff --git a/mod/database-module.cxx b/mod/database-module.cxx index 137d7ef..07037cd 100644 --- a/mod/database-module.cxx +++ b/mod/database-module.cxx @@ -4,24 +4,13 @@ #include <mod/database-module.hxx> -#include <errno.h> // EIO - -#include <sstream> - #include <odb/exceptions.hxx> -#include <libbutl/utility.mxx> // throw_generic_error() - #include <mod/options.hxx> #include <mod/database.hxx> -#include <mod/build-config.hxx> namespace brep { - using namespace std; - using namespace butl; - using namespace bbot; - // While currently the user-defined copy constructor is not required (we // don't need to deep copy nullptr's), it is a good idea to keep the // placeholder ready for less trivial cases. @@ -31,11 +20,7 @@ namespace brep : handler (r), retry_ (r.retry_), package_db_ (r.initialized_ ? r.package_db_ : nullptr), - build_db_ (r.initialized_ ? r.build_db_ : nullptr), - build_conf_ (r.initialized_ ? r.build_conf_ : nullptr), - build_conf_names_ (r.initialized_ ? r.build_conf_names_ : nullptr), - build_conf_map_ (r.initialized_ ? r.build_conf_map_ : nullptr), - bot_agent_keys_ (r.initialized_ ? r.bot_agent_keys_ : nullptr) + build_db_ (r.initialized_ ? r.build_db_ : nullptr) { } @@ -54,48 +39,15 @@ namespace brep } void database_module:: - init (const options::build& bo, const options::build_db& dbo, size_t retry) + init (const options::build_db& o, size_t retry) { - try - { - build_conf_ = shared_build_config (bo.build_config ()); - } - catch (const io_error& e) - { - ostringstream os; - os << "unable to read build configuration '" << bo.build_config () - << "': " << e; - - throw_generic_error (EIO, os.str ().c_str ()); - } - - if (bo.build_bot_agent_keys_specified ()) - bot_agent_keys_ = 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>; - 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)); - - build_db_ = shared_database (dbo.build_db_user (), - dbo.build_db_role (), - dbo.build_db_password (), - dbo.build_db_name (), - dbo.build_db_host (), - dbo.build_db_port (), - dbo.build_db_max_connections ()); + build_db_ = shared_database (o.build_db_user (), + o.build_db_role (), + o.build_db_password (), + o.build_db_name (), + o.build_db_host (), + o.build_db_port (), + o.build_db_max_connections ()); retry_ = retry_ < retry ? retry : retry_; } diff --git a/mod/database-module.hxx b/mod/database-module.hxx index 70ae004..9791ece 100644 --- a/mod/database-module.hxx +++ b/mod/database-module.hxx @@ -5,20 +5,13 @@ #ifndef MOD_DATABASE_MODULE_HXX #define MOD_DATABASE_MODULE_HXX -#include <map> - #include <odb/forward.hxx> // database -#include <libbutl/utility.mxx> // compare_c_string - #include <libbrep/types.hxx> #include <libbrep/utility.hxx> -#include <libbbot/build-config.hxx> - #include <mod/module.hxx> #include <mod/options.hxx> -#include <mod/build-config.hxx> namespace brep { @@ -49,12 +42,11 @@ namespace brep void init (const options::package_db&, size_t retry); - // Initialize the build database instance and parse build configuration - // file. Throw odb::exception on database failure, tab_parsing on parsing - // error, system_error on the underlying OS error. + // Initialize the build database instance. Throw odb::exception on + // database failure. // void - init (const options::build&, const options::build_db&, size_t retry); + init (const options::build_db&, size_t retry); virtual bool handle (request&, response&) = 0; @@ -63,19 +55,7 @@ namespace brep size_t retry_ = 0; // Max of all retries. shared_ptr<odb::core::database> package_db_; - - // These are NULL if not building. - // - shared_ptr<odb::core::database> build_db_; - shared_ptr<const bbot::build_configs> build_conf_; - shared_ptr<const cstrings> build_conf_names_; - - shared_ptr<const std::map<const char*, - const bbot::build_config*, - butl::compare_c_string>> - build_conf_map_; - - shared_ptr<const bot_agent_keys> bot_agent_keys_; + shared_ptr<odb::core::database> build_db_; // NULL if not building. private: virtual bool diff --git a/mod/mod-build-configs.cxx b/mod/mod-build-configs.cxx index 99a092d..826bb87 100644 --- a/mod/mod-build-configs.cxx +++ b/mod/mod-build-configs.cxx @@ -11,7 +11,6 @@ #include <mod/page.hxx> #include <mod/options.hxx> -#include <mod/build-config.hxx> using namespace std; using namespace bbot; @@ -24,8 +23,8 @@ using namespace brep::cli; brep::build_configs:: build_configs (const build_configs& r) : handler (r), - options_ (r.initialized_ ? r.options_ : nullptr), - build_conf_ (r.initialized_ ? r.build_conf_ : nullptr) + build_config_module (r), + options_ (r.initialized_ ? r.options_ : nullptr) { } @@ -38,15 +37,7 @@ init (scanner& s) s, unknown_mode::fail, unknown_mode::fail); if (options_->build_config_specified ()) - try - { - build_conf_ = shared_build_config (options_->build_config ()); - } - catch (const io_error& e) - { - fail << "unable to read build configuration '" - << options_->build_config () << "': " << e; - } + build_config_module::init (static_cast<options::build> (*options_)); } bool brep::build_configs:: @@ -133,7 +124,17 @@ handle (request& rq, response& rs) { if (!classes.empty ()) classes += ' '; + classes += cls; + + // Append the base class, if present. + // + auto i (build_conf_->class_inheritance_map.find (cls)); + if (i != build_conf_->class_inheritance_map.end ()) + { + classes += ':'; + classes += i->second; + } } s << TABLE(CLASS="proplist config") diff --git a/mod/mod-build-configs.hxx b/mod/mod-build-configs.hxx index 0c57359..754c596 100644 --- a/mod/mod-build-configs.hxx +++ b/mod/mod-build-configs.hxx @@ -8,14 +8,13 @@ #include <libbrep/types.hxx> #include <libbrep/utility.hxx> -#include <libbbot/build-config.hxx> - #include <mod/module.hxx> #include <mod/options.hxx> +#include <mod/build-config-module.hxx> namespace brep { - class build_configs: public handler + class build_configs: public handler, private build_config_module { public: build_configs () = default; @@ -41,7 +40,6 @@ namespace brep private: shared_ptr<options::build_configs> options_; - shared_ptr<const bbot::build_configs> build_conf_; }; } diff --git a/mod/mod-build-force.cxx b/mod/mod-build-force.cxx index ddc1301..3a92b53 100644 --- a/mod/mod-build-force.cxx +++ b/mod/mod-build-force.cxx @@ -28,6 +28,7 @@ using namespace odb::core; brep::build_force:: build_force (const build_force& r) : database_module (r), + build_config_module (r), options_ (r.initialized_ ? r.options_ : nullptr) { } @@ -41,9 +42,12 @@ init (scanner& s) s, unknown_mode::fail, unknown_mode::fail); if (options_->build_config_specified ()) - database_module::init (static_cast<options::build> (*options_), - static_cast<options::build_db> (*options_), + { + database_module::init (static_cast<options::build_db> (*options_), options_->build_db_retry ()); + + build_config_module::init (static_cast<options::build> (*options_)); + } } bool brep::build_force:: diff --git a/mod/mod-build-force.hxx b/mod/mod-build-force.hxx index 1af7723..5448026 100644 --- a/mod/mod-build-force.hxx +++ b/mod/mod-build-force.hxx @@ -10,10 +10,11 @@ #include <mod/options.hxx> #include <mod/database-module.hxx> +#include <mod/build-config-module.hxx> namespace brep { - class build_force: public database_module + class build_force: public database_module, private build_config_module { public: build_force () = default; diff --git a/mod/mod-build-log.cxx b/mod/mod-build-log.cxx index ee5d1b2..63b2f75 100644 --- a/mod/mod-build-log.cxx +++ b/mod/mod-build-log.cxx @@ -30,6 +30,7 @@ using namespace odb::core; brep::build_log:: build_log (const build_log& r) : database_module (r), + build_config_module (r), options_ (r.initialized_ ? r.options_ : nullptr) { } @@ -43,10 +44,13 @@ init (scanner& s) s, unknown_mode::fail, unknown_mode::fail); if (options_->build_config_specified ()) - database_module::init (static_cast<options::build> (*options_), - static_cast<options::build_db> (*options_), + { + database_module::init (static_cast<options::build_db> (*options_), options_->build_db_retry ()); + build_config_module::init (*options_); + } + if (options_->root ().empty ()) options_->root (dir_path ("/")); } diff --git a/mod/mod-build-log.hxx b/mod/mod-build-log.hxx index 154403e..9c31286 100644 --- a/mod/mod-build-log.hxx +++ b/mod/mod-build-log.hxx @@ -10,10 +10,11 @@ #include <mod/options.hxx> #include <mod/database-module.hxx> +#include <mod/build-config-module.hxx> namespace brep { - class build_log: public database_module + class build_log: public database_module, private build_config_module { public: build_log () = default; diff --git a/mod/mod-build-result.cxx b/mod/mod-build-result.cxx index 177e67f..5f671d3 100644 --- a/mod/mod-build-result.cxx +++ b/mod/mod-build-result.cxx @@ -23,8 +23,8 @@ #include <libbrep/package.hxx> #include <libbrep/package-odb.hxx> +#include <mod/build.hxx> // *_url() #include <mod/options.hxx> -#include <mod/build-config.hxx> // *_url() using namespace std; using namespace butl; @@ -39,6 +39,7 @@ using namespace odb::core; brep::build_result:: build_result (const build_result& r) : database_module (r), + build_config_module (r), options_ (r.initialized_ ? r.options_ : nullptr) { } @@ -55,10 +56,13 @@ init (scanner& s) options_->package_db_retry ()); if (options_->build_config_specified ()) - database_module::init (static_cast<options::build> (*options_), - static_cast<options::build_db> (*options_), + { + database_module::init (static_cast<options::build_db> (*options_), options_->build_db_retry ()); + build_config_module::init (static_cast<options::build> (*options_)); + } + if (options_->root ().empty ()) options_->root (dir_path ("/")); } @@ -312,18 +316,18 @@ handle (request& rq, response&) warn_auth (rqm.challenge ? "unexpected challenge" : "challenge is expected"); - else if (bot_agent_keys_ == nullptr) // Authentication is disabled. + else if (bot_agent_key_map_ == nullptr) // Authentication is disabled. auth = true; else if (!b->agent_challenge) // Authentication is recently enabled. warn_auth ("challenge is required now"); else { assert (b->agent_fingerprint && rqm.challenge); - auto i (bot_agent_keys_->find (*b->agent_fingerprint)); + auto i (bot_agent_key_map_->find (*b->agent_fingerprint)); // The agent's key is recently replaced. // - if (i == bot_agent_keys_->end ()) + if (i == bot_agent_key_map_->end ()) warn_auth ("agent's public key not found"); else { @@ -400,7 +404,8 @@ handle (request& rq, response&) shared_ptr<build_package> p ( build_db_->load<build_package> (b->id.package)); - if (belongs (*cfg, "all") && !exclude (*p, *cfg)) + if (belongs (*cfg, "all") && + !exclude (p->builds, p->constraints, *cfg)) bld = move (b); } } @@ -458,7 +463,7 @@ handle (request& rq, response&) os << "Force rebuild (enter the reason, use '+' instead of spaces):" << endl << endl - << " " << force_rebuild_url (host, root, *bld) << endl; + << " " << build_force_url (host, root, *bld) << endl; } sm.out.close (); diff --git a/mod/mod-build-result.hxx b/mod/mod-build-result.hxx index 2c24436..86542e7 100644 --- a/mod/mod-build-result.hxx +++ b/mod/mod-build-result.hxx @@ -10,10 +10,11 @@ #include <mod/options.hxx> #include <mod/database-module.hxx> +#include <mod/build-config-module.hxx> namespace brep { - class build_result: public database_module + class build_result: public database_module, private build_config_module { public: build_result () = default; diff --git a/mod/mod-build-task.cxx b/mod/mod-build-task.cxx index 14c72ac..1736869 100644 --- a/mod/mod-build-task.cxx +++ b/mod/mod-build-task.cxx @@ -45,6 +45,7 @@ using namespace odb::core; brep::build_task:: build_task (const build_task& r) : database_module (r), + build_config_module (r), options_ (r.initialized_ ? r.options_ : nullptr) { } @@ -59,8 +60,7 @@ init (scanner& s) if (options_->build_config_specified ()) { - database_module::init (static_cast<options::build> (*options_), - static_cast<options::build_db> (*options_), + database_module::init (static_cast<options::build_db> (*options_), options_->build_db_retry ()); // Check that the database 'build' schema matches the current one. It's @@ -72,6 +72,8 @@ init (scanner& s) build_db_->schema_version (ds)) fail << "database 'build' schema differs from the current one (module " << BREP_VERSION_ID << ")"; + + build_config_module::init (static_cast<options::build> (*options_)); } if (options_->root ().empty ()) @@ -124,10 +126,11 @@ handle (request& rq, response& rs) // optional<string> agent_fp; - if (bot_agent_keys_ != nullptr) + if (bot_agent_key_map_ != nullptr) { if (!tqm.fingerprint || - bot_agent_keys_->find (*tqm.fingerprint) == bot_agent_keys_->end ()) + bot_agent_key_map_->find (*tqm.fingerprint) == + bot_agent_key_map_->end ()) throw invalid_request (401, "unauthorized"); agent_fp = move (tqm.fingerprint); @@ -220,7 +223,7 @@ handle (request& rq, response& rs) move (fp), cm.machine->name, cm.config->target, - cm.config->vars, + cm.config->args, cm.config->warning_regexes); return task_response_manifest (move (session), @@ -476,7 +479,11 @@ handle (request& rq, response& rs) auto i (configs.begin ()); auto e (configs.end ()); - for (; i != e && exclude (*p, *i->second.config); ++i) ; + + for (; + i != e && + exclude (p->builds, p->constraints, *i->second.config); + ++i) ; if (i != e) { @@ -632,7 +639,7 @@ handle (request& rq, response& rs) if (p != nullptr && p->internal_repository != nullptr && - !exclude (*p, *cm.config)) + !exclude (p->builds, p->constraints, *cm.config)) { assert (b->status); diff --git a/mod/mod-build-task.hxx b/mod/mod-build-task.hxx index 75383f0..d907ee7 100644 --- a/mod/mod-build-task.hxx +++ b/mod/mod-build-task.hxx @@ -10,10 +10,11 @@ #include <mod/options.hxx> #include <mod/database-module.hxx> +#include <mod/build-config-module.hxx> namespace brep { - class build_task: public database_module + class build_task: public database_module, private build_config_module { public: build_task () = default; diff --git a/mod/mod-builds.cxx b/mod/mod-builds.cxx index 6ad5a0e..6f027d2 100644 --- a/mod/mod-builds.cxx +++ b/mod/mod-builds.cxx @@ -28,7 +28,6 @@ #include <mod/page.hxx> #include <mod/options.hxx> -#include <mod/build-config.hxx> // *_url() using namespace std; using namespace butl; @@ -44,6 +43,7 @@ using namespace brep::cli; brep::builds:: builds (const builds& r) : database_module (r), + build_config_module (r), options_ (r.initialized_ ? r.options_ : nullptr) { } @@ -57,10 +57,13 @@ init (scanner& s) s, unknown_mode::fail, unknown_mode::fail); if (options_->build_config_specified ()) - database_module::init (static_cast<options::build> (*options_), - static_cast<options::build_db> (*options_), + { + database_module::init (static_cast<options::build_db> (*options_), options_->build_db_retry ()); + build_config_module::init (static_cast<options::build> (*options_)); + } + if (options_->root ().empty ()) options_->root (dir_path ("/")); } @@ -550,7 +553,7 @@ handle (request& rq, response& rs) // Match the configuration against the package build // expressions/constraints. // - if (!exclude (*p, *i->second)) + if (!exclude (p->builds, p->constraints, *i->second)) { if (skip != 0) --skip; @@ -813,7 +816,7 @@ handle (request& rq, response& rs) for (const auto& c: configs) { - if (exclude (*p, *c)) + if (exclude (p->builds, p->constraints, *c)) { nmax -= nt; @@ -942,7 +945,7 @@ handle (request& rq, response& rs) auto i (build_conf_map_->find (ct.configuration.c_str ())); assert (i != build_conf_map_->end ()); - if (!exclude (*p, *i->second)) + if (!exclude (p->builds, p->constraints, *i->second)) unbuilt_configs.insert (ct); } } diff --git a/mod/mod-builds.hxx b/mod/mod-builds.hxx index 4b2441a..cf4020e 100644 --- a/mod/mod-builds.hxx +++ b/mod/mod-builds.hxx @@ -10,10 +10,11 @@ #include <mod/options.hxx> #include <mod/database-module.hxx> +#include <mod/build-config-module.hxx> namespace brep { - class builds: public database_module + class builds: public database_module, private build_config_module { public: builds () = default; diff --git a/mod/mod-package-version-details.cxx b/mod/mod-package-version-details.cxx index 9566c8f..cbe338e 100644 --- a/mod/mod-package-version-details.cxx +++ b/mod/mod-package-version-details.cxx @@ -34,6 +34,7 @@ using namespace brep::cli; brep::package_version_details:: package_version_details (const package_version_details& r) : database_module (r), + build_config_module (r), options_ (r.initialized_ ? r.options_ : nullptr) { } @@ -46,13 +47,17 @@ init (scanner& s) options_ = make_shared<options::package_version_details> ( s, unknown_mode::fail, unknown_mode::fail); - database_module::init (*options_, options_->package_db_retry ()); + database_module::init (static_cast<options::package_db> (*options_), + options_->package_db_retry ()); if (options_->build_config_specified ()) - database_module::init (static_cast<options::build> (*options_), - static_cast<options::build_db> (*options_), + { + database_module::init (static_cast<options::build_db> (*options_), options_->build_db_retry ()); + build_config_module::init (static_cast<options::build> (*options_)); + } + if (options_->root ().empty ()) options_->root (dir_path ("/")); } @@ -393,9 +398,10 @@ handle (request& rq, response& rs) s << H3 << "Builds" << ~H3 << DIV(ID="builds"); - auto exclude = [&pkg] (const build_config& cfg, string* reason = nullptr) + auto exclude = [&pkg, this] (const build_config& cfg, + string* reason = nullptr) { - return brep::exclude (pkg->builds, pkg->build_constraints, cfg, reason); + return this->exclude (pkg->builds, pkg->build_constraints, cfg, reason); }; timestamp now (system_clock::now ()); diff --git a/mod/mod-package-version-details.hxx b/mod/mod-package-version-details.hxx index 0451e99..c15d746 100644 --- a/mod/mod-package-version-details.hxx +++ b/mod/mod-package-version-details.hxx @@ -10,10 +10,12 @@ #include <mod/options.hxx> #include <mod/database-module.hxx> +#include <mod/build-config-module.hxx> namespace brep { - class package_version_details: public database_module + class package_version_details: public database_module, + private build_config_module { public: package_version_details () = default; diff --git a/mod/page.cxx b/mod/page.cxx index eab28c6..7cfce62 100644 --- a/mod/page.cxx +++ b/mod/page.cxx @@ -18,8 +18,8 @@ #include <libbrep/package.hxx> #include <libbrep/package-odb.hxx> +#include <mod/build.hxx> // build_log_url() #include <mod/utility.hxx> -#include <mod/build-config.hxx> // build_log_url() using namespace std; using namespace xml; @@ -718,7 +718,7 @@ namespace brep s << SPAN(CLASS="pending") << "pending" << ~SPAN; else s << A - << HREF << force_rebuild_url (host_, root_, build_) << ~HREF + << HREF << build_force_url (host_, root_, build_) << ~HREF << "rebuild" << ~A; diff --git a/tests/load/1/math/libfoo-1.0.tar.gz b/tests/load/1/math/libfoo-1.0.tar.gz Binary files differindex e951386..2d445ec 100644 --- a/tests/load/1/math/libfoo-1.0.tar.gz +++ b/tests/load/1/math/libfoo-1.0.tar.gz diff --git a/tests/load/1/math/packages.manifest b/tests/load/1/math/packages.manifest index 0bbf6d4..d1c972d 100644 --- a/tests/load/1/math/packages.manifest +++ b/tests/load/1/math/packages.manifest @@ -32,9 +32,11 @@ version: 1.0 summary: The Foo Library license: MIT build-email: foo-builds@example.com -builds: default legacy : -32; 64-bit targets only +builds: default legacy; Stable configurations only. +builds: -32; 64-bit targets only +builds: &msvc_13_up; Not too old MSVC. location: libfoo-1.0.tar.gz -sha256sum: 3d32793e7b800837682ffa1dad794df7c9e2bb7a54504552a5bd261b5ec064e5 +sha256sum: e89c6d746f8b1ea3ec58d294946d2f683d133438d2ac8c88549ba24c19627e76 : name: libfoo version: 1.2.4+1 diff --git a/tests/load/1/stable/libfoo-1.0.tar.gz b/tests/load/1/stable/libfoo-1.0.tar.gz Binary files differindex e951386..2d445ec 100644 --- a/tests/load/1/stable/libfoo-1.0.tar.gz +++ b/tests/load/1/stable/libfoo-1.0.tar.gz diff --git a/tests/load/1/stable/packages.manifest b/tests/load/1/stable/packages.manifest index 797b214..4c83ed5 100644 --- a/tests/load/1/stable/packages.manifest +++ b/tests/load/1/stable/packages.manifest @@ -6,9 +6,11 @@ version: 1.0 summary: The Foo Library license: MIT build-email: foo-builds@example.com -builds: default legacy : -32; 64-bit targets only +builds: default legacy; Stable configurations only. +builds: -32; 64-bit targets only +builds: &msvc_13_up; Not too old MSVC. location: libfoo-1.0.tar.gz -sha256sum: 3d32793e7b800837682ffa1dad794df7c9e2bb7a54504552a5bd261b5ec064e5 +sha256sum: e89c6d746f8b1ea3ec58d294946d2f683d133438d2ac8c88549ba24c19627e76 : name: libfoo version: 1.2.2-alpha.1 diff --git a/tests/load/1/stable/signature.manifest b/tests/load/1/stable/signature.manifest index 2678657..decdf5b 100644 --- a/tests/load/1/stable/signature.manifest +++ b/tests/load/1/stable/signature.manifest @@ -1,13 +1,13 @@ : 1 -sha256sum: 4957fe28799fe3a037c3112c8122d216fb1d25b48c1028979e5a8738683cb1a5 +sha256sum: f48f71ccb83024007dedc63148d4682e7b2a478a3ca78583e3562ea4bcf396a5 signature: \ -Dxc/W3NM0ZZ/Aytrxpptgcg8pg6tteT9rVoFm3mxaXsLMoEzjEEHq1ruI3kbmIVHQIBYymvpj5FS -JUeKdmtkNOZA7DqbdT5njEarKGoLE4awqsZ4yAWMKpmHNxAl/dYNIQ0l5YdsAq7+c3/lCwha9SlB -QcZrKDxZ7DrhcdiI0eQej08n0X45OA1451VLnSkjHsLXXCO0qnj2o+WVKJE/lWz46Z6FCm9wlLQC -cxaamInFeL5s/eZmn7j5Eo+v2y1v/zufeCr5W6feKlFau156G43ZROPUoqVl+ZxuSAR1gKalVjny -jH1adjEkwqtxXN0fvT2pQ0XU/gn/s7PTiGR9PnKytrAFemO3hbd62PAcFRk17NV8qworyBdLMHgA -V4/CyDCItOgAzfenbjPHfxEkm+qKcK4Y6NlUQSqcHDW8kxMv6iuVw8s0o5ij9frY5XLg2h39O/Lw -I4tDO0lg8k2vxKJVxKk85uElJ+kuBG4353PP3G11uzZpah4X9zqh21TBP+rx+L1gefHwjew+ZwQi -qtOedbzrJlgLgTDK3Q+yMN2i9YOIe+D5vB4Gr97y1lL0qVS3zm/4CjLo6kj13ngGXxivGLbtDlX9 -v4COE/+PtwGS2ubmku1QMwZuXyJfjKG9lGgoNoARML17EzzMIFXnzII0uSP+NUKrT3jLdEbOlQs= +K+F80RQE97ZmEVAl2wQwyYaw/SzviqfuR7FBTdF3PtnIorCxeokwvDL0ip7PiEJRp7QF5V0T69F+ +35MqTrRm/cLdKsxk1vsG8KWMuoK3LSXj+jcPkxKGmVoI09MvPxIQNgHKe/gk1f7uBExnpeOdfHyV +2zP6GMOhZIY4SScNeFr5lo/4bpEEtLNH1TbiYHaaGlBQDmzGzY+kdCrzZ/nWEBaWIHdT8GcqQF1D +P+KWYFoOoT5DnZtfk3ohTI1YHdDQWyWq8vFqkfpRDwxqtHltGeNLjmlwxF6gPJq9H6UZMZfEHGvs +qAScoiA5ozdPt1UXiYtPXpDoweHKcoVPHyqMxcciMTx8BYXDqY8V9EKwd/F3rD0ITzXW3eaRNygo +Jh6w6tjhZjFQ+NJ9GgsxE7NNU1dYhXuzKyBwus0GkGHriGTU7L0t2MoY/1GXihexwz3fHAmkOYxe +Iz4Xt+SZeRSLa5VFFjyEOtbtvbVv8R2WngG4xwNH0b3nMJ8Baa87rajSIfIoXJaeNFWhpEBwCToz +59aJXl76+0kQL40+wSO7+/o8LnLS2sW6+ooMjM8RLRBLTzNqSsVH5kA+W0qF8e0j7AJ0qcqU5HKZ +MzhB7jPyQ82LBq/eU29bgM9hLkOiJpqwplmiRyby98jBz4ppnIytfQeD52PtDCf4yWT9p3PsKmg= \ diff --git a/tests/load/driver.cxx b/tests/load/driver.cxx index a36416b..17da60e 100644 --- a/tests/load/driver.cxx +++ b/tests/load/driver.cxx @@ -405,7 +405,7 @@ test_pkg_repos (const cstrings& loader_args, assert (check_location (fpv1)); assert (fpv1->sha256sum && *fpv1->sha256sum == - "3d32793e7b800837682ffa1dad794df7c9e2bb7a54504552a5bd261b5ec064e5"); + "e89c6d746f8b1ea3ec58d294946d2f683d133438d2ac8c88549ba24c19627e76"); // libfoo-1.2.2 // |