diff options
Diffstat (limited to 'libbrep')
-rw-r--r-- | libbrep/build-extra.sql | 249 | ||||
-rw-r--r-- | libbrep/build-package.hxx | 270 | ||||
-rw-r--r-- | libbrep/build.cxx | 192 | ||||
-rw-r--r-- | libbrep/build.hxx | 355 | ||||
-rw-r--r-- | libbrep/build.xml | 159 | ||||
-rw-r--r-- | libbrep/buildfile | 1 | ||||
-rw-r--r-- | libbrep/common-traits.hxx | 39 | ||||
-rw-r--r-- | libbrep/common.cxx | 27 | ||||
-rw-r--r-- | libbrep/common.hxx | 457 | ||||
-rw-r--r-- | libbrep/database-lock.cxx | 1 | ||||
-rw-r--r-- | libbrep/database-lock.hxx | 1 | ||||
-rwxr-xr-x | libbrep/odb.sh | 6 | ||||
-rw-r--r-- | libbrep/package-extra.sql | 39 | ||||
-rw-r--r-- | libbrep/package-traits.cxx | 1 | ||||
-rw-r--r-- | libbrep/package-traits.hxx | 1 | ||||
-rw-r--r-- | libbrep/package.cxx | 125 | ||||
-rw-r--r-- | libbrep/package.hxx | 508 | ||||
-rw-r--r-- | libbrep/package.xml | 578 | ||||
-rw-r--r-- | libbrep/types.hxx | 25 | ||||
-rw-r--r-- | libbrep/utility.hxx | 17 | ||||
-rw-r--r-- | libbrep/version.hxx.in | 1 | ||||
-rw-r--r-- | libbrep/wrapper-traits.hxx | 3 |
22 files changed, 2645 insertions, 410 deletions
diff --git a/libbrep/build-extra.sql b/libbrep/build-extra.sql index 9ecbcb1..9e51a51 100644 --- a/libbrep/build-extra.sql +++ b/libbrep/build-extra.sql @@ -6,27 +6,62 @@ -- package-extra.sql file for details. -- +DROP FOREIGN TABLE IF EXISTS build_package_config_bot_keys; + +DROP FOREIGN TABLE IF EXISTS build_package_config_auxiliaries; + +DROP FOREIGN TABLE IF EXISTS build_package_config_constraints; + +DROP FOREIGN TABLE IF EXISTS build_package_config_builds; + +DROP FOREIGN TABLE IF EXISTS build_package_configs; + +DROP FOREIGN TABLE IF EXISTS build_package_bot_keys; + +DROP FOREIGN TABLE IF EXISTS build_package_auxiliaries; + DROP FOREIGN TABLE IF EXISTS build_package_constraints; DROP FOREIGN TABLE IF EXISTS build_package_builds; +DROP FOREIGN TABLE IF EXISTS build_package_tests; + +DROP FOREIGN TABLE IF EXISTS build_package_requirement_alternative_requirements; + +DROP FOREIGN TABLE IF EXISTS build_package_requirement_alternatives; + +DROP FOREIGN TABLE IF EXISTS build_package_requirements; + DROP FOREIGN TABLE IF EXISTS build_package; +DROP FOREIGN TABLE IF EXISTS build_public_key; + DROP FOREIGN TABLE IF EXISTS build_repository; DROP FOREIGN TABLE IF EXISTS build_tenant; -- The foreign table for build_tenant object. -- --- CREATE FOREIGN TABLE build_tenant ( id TEXT NOT NULL, - archived BOOLEAN NOT NULL) + private BOOLEAN NOT NULL, + interactive TEXT NULL, + archived BOOLEAN NOT NULL, + service_id TEXT NULL, + service_type TEXT NULL, + service_data TEXT NULL, + queued_timestamp BIGINT NULL, + toolchain_name TEXT OPTIONS (column_name 'build_toolchain_name') NULL, + toolchain_version_epoch INTEGER OPTIONS (column_name 'build_toolchain_version_epoch') NULL, + toolchain_version_canonical_upstream TEXT OPTIONS (column_name 'build_toolchain_version_canonical_upstream') NULL, + toolchain_version_canonical_release TEXT OPTIONS (column_name 'build_toolchain_version_canonical_release') NULL, + toolchain_version_revision INTEGER OPTIONS (column_name 'build_toolchain_version_revision') NULL, + toolchain_version_upstream TEXT OPTIONS (column_name 'build_toolchain_version_upstream') NULL, + toolchain_version_release TEXT OPTIONS (column_name 'build_toolchain_version_release') NULL) SERVER package_server OPTIONS (table_name 'tenant'); -- The foreign table for build_repository object. -- --- CREATE FOREIGN TABLE build_repository ( tenant TEXT NOT NULL, canonical_name TEXT NOT NULL, @@ -35,8 +70,15 @@ CREATE FOREIGN TABLE build_repository ( certificate_fingerprint TEXT NULL) SERVER package_server OPTIONS (table_name 'repository'); --- The foreign table for build_package object. +-- The foreign table for build_public_key object. -- +CREATE FOREIGN TABLE build_public_key ( + tenant TEXT NOT NULL, + fingerprint TEXT NOT NULL, + "data" TEXT NOT NULL) +SERVER package_server OPTIONS (table_name 'public_key'); + +-- The foreign table for build_package object. -- CREATE FOREIGN TABLE build_package ( tenant TEXT NOT NULL, @@ -47,14 +89,100 @@ CREATE FOREIGN TABLE build_package ( version_revision INTEGER NOT NULL, version_upstream TEXT NOT NULL, version_release TEXT NULL, + project CITEXT NOT NULL, + build_email TEXT NULL, + build_email_comment TEXT NULL, + build_warning_email TEXT NULL, + build_warning_email_comment TEXT NULL, + build_error_email TEXT NULL, + build_error_email_comment TEXT NULL, internal_repository_tenant TEXT NULL, internal_repository_canonical_name TEXT NULL, - buildable BOOLEAN NOT NULL) + buildable BOOLEAN NOT NULL, + custom_bot BOOLEAN NULL) SERVER package_server OPTIONS (table_name 'package'); --- The foreign table for the build_package object builds member (that is of a +-- The foreign tables for the build_package object requirements member (that +-- is of a 3-dimensional container type). +-- +CREATE FOREIGN TABLE build_package_requirements ( + tenant TEXT NOT NULL, + name CITEXT NOT NULL, + version_epoch INTEGER NOT NULL, + version_canonical_upstream TEXT NOT NULL, + version_canonical_release TEXT NOT NULL COLLATE "C", + version_revision INTEGER NOT NULL, + index BIGINT NOT NULL, + buildtime BOOLEAN NOT NULL, + comment TEXT NOT NULL) +SERVER package_server OPTIONS (table_name 'package_requirements'); + +CREATE FOREIGN TABLE build_package_requirement_alternatives ( + tenant TEXT NOT NULL, + name CITEXT NOT NULL, + version_epoch INTEGER NOT NULL, + version_canonical_upstream TEXT NOT NULL, + version_canonical_release TEXT NOT NULL COLLATE "C", + version_revision INTEGER NOT NULL, + requirement_index BIGINT NOT NULL, + index BIGINT NOT NULL, + enable TEXT NULL, + reflect TEXT NULL) +SERVER package_server OPTIONS (table_name 'package_requirement_alternatives'); + +CREATE FOREIGN TABLE build_package_requirement_alternative_requirements ( + tenant TEXT NOT NULL, + name CITEXT NOT NULL, + version_epoch INTEGER NOT NULL, + version_canonical_upstream TEXT NOT NULL, + version_canonical_release TEXT NOT NULL COLLATE "C", + version_revision INTEGER NOT NULL, + requirement_index BIGINT NOT NULL, + alternative_index BIGINT NOT NULL, + index BIGINT NOT NULL, + id TEXT NOT NULL) +SERVER package_server OPTIONS (table_name 'package_requirement_alternative_requirements'); + +-- The foreign table for the build_package object tests member (that is of a -- container type). -- +CREATE FOREIGN TABLE build_package_tests ( + tenant TEXT NOT NULL, + name CITEXT NOT NULL, + version_epoch INTEGER NOT NULL, + version_canonical_upstream TEXT NOT NULL, + version_canonical_release TEXT NOT NULL COLLATE "C", + version_revision INTEGER NOT NULL, + index BIGINT NOT NULL, + test_name CITEXT NOT NULL, + test_min_version_epoch INTEGER NULL, + test_min_version_canonical_upstream TEXT NULL, + test_min_version_canonical_release TEXT NULL, + test_min_version_revision INTEGER NULL, + test_min_version_upstream TEXT NULL, + test_min_version_release TEXT NULL, + test_max_version_epoch INTEGER NULL, + test_max_version_canonical_upstream TEXT NULL, + test_max_version_canonical_release TEXT NULL, + test_max_version_revision INTEGER NULL, + test_max_version_upstream TEXT NULL, + test_max_version_release TEXT NULL, + test_min_open BOOLEAN NULL, + test_max_open BOOLEAN NULL, + test_package_tenant TEXT NULL, + test_package_name CITEXT NULL, + test_package_version_epoch INTEGER NULL, + test_package_version_canonical_upstream TEXT NULL, + test_package_version_canonical_release TEXT NULL COLLATE "C", + test_package_version_revision INTEGER NULL, + test_type TEXT NOT NULL, + test_buildtime BOOLEAN NOT NULL, + test_enable TEXT NULL, + test_reflect TEXT NULL) +SERVER package_server OPTIONS (table_name 'package_tests'); + +-- The foreign table for the build_package object builds member (that is of a +-- container type). -- CREATE FOREIGN TABLE build_package_builds ( tenant TEXT NOT NULL, @@ -71,7 +199,6 @@ SERVER package_server OPTIONS (table_name 'package_builds'); -- The foreign table for the build_package object constraints member (that is -- of a container type). -- --- CREATE FOREIGN TABLE build_package_constraints ( tenant TEXT NOT NULL, name CITEXT NOT NULL, @@ -85,3 +212,111 @@ CREATE FOREIGN TABLE build_package_constraints ( target TEXT NULL, comment TEXT NOT NULL) SERVER package_server OPTIONS (table_name 'package_build_constraints'); + +-- The foreign table for the build_package object auxiliaries member (that is +-- of a container type). +-- +CREATE FOREIGN TABLE build_package_auxiliaries ( + tenant TEXT NOT NULL, + name CITEXT NOT NULL, + version_epoch INTEGER NOT NULL, + version_canonical_upstream TEXT NOT NULL, + version_canonical_release TEXT NOT NULL COLLATE "C", + version_revision INTEGER NOT NULL, + index BIGINT NOT NULL, + environment_name TEXT NOT NULL, + config TEXT NOT NULL, + comment TEXT NOT NULL) +SERVER package_server OPTIONS (table_name 'package_build_auxiliaries'); + +-- The foreign table for the build_package object bot_keys member (that is +-- of a container type). +-- +CREATE FOREIGN TABLE build_package_bot_keys ( + tenant TEXT NOT NULL, + name CITEXT NOT NULL, + version_epoch INTEGER NOT NULL, + version_canonical_upstream TEXT NOT NULL, + version_canonical_release TEXT NOT NULL COLLATE "C", + version_revision INTEGER NOT NULL, + index BIGINT NOT NULL, + key_tenant TEXT NOT NULL, + key_fingerprint TEXT NOT NULL) +SERVER package_server OPTIONS (table_name 'package_build_bot_keys'); + +-- The foreign tables for the build_package object configs member (that is a +-- container of values containing containers. +-- +CREATE FOREIGN TABLE build_package_configs ( + tenant TEXT NOT NULL, + name CITEXT NOT NULL, + version_epoch INTEGER NOT NULL, + version_canonical_upstream TEXT NOT NULL, + version_canonical_release TEXT NOT NULL COLLATE "C", + version_revision INTEGER NOT NULL, + index BIGINT NOT NULL, + config_name TEXT NOT NULL, + config_arguments TEXT NULL, + config_comment TEXT NOT NULL, + config_email TEXT NULL, + config_email_comment TEXT NULL, + config_warning_email TEXT NULL, + config_warning_email_comment TEXT NULL, + config_error_email TEXT NULL, + config_error_email_comment TEXT NULL) +SERVER package_server OPTIONS (table_name 'package_build_configs'); + +CREATE FOREIGN TABLE build_package_config_builds ( + tenant TEXT NOT NULL, + name CITEXT NOT NULL, + version_epoch INTEGER NOT NULL, + version_canonical_upstream TEXT NOT NULL, + version_canonical_release TEXT NOT NULL COLLATE "C", + version_revision INTEGER NOT NULL, + config_index BIGINT NOT NULL, + index BIGINT NOT NULL, + expression TEXT NOT NULL, + comment TEXT NOT NULL) +SERVER package_server OPTIONS (table_name 'package_build_config_builds'); + +CREATE FOREIGN TABLE build_package_config_constraints ( + tenant TEXT NOT NULL, + name CITEXT NOT NULL, + version_epoch INTEGER NOT NULL, + version_canonical_upstream TEXT NOT NULL, + version_canonical_release TEXT NOT NULL COLLATE "C", + version_revision INTEGER NOT NULL, + config_index BIGINT NOT NULL, + index BIGINT NOT NULL, + exclusion BOOLEAN NOT NULL, + config TEXT NOT NULL, + target TEXT NULL, + comment TEXT NOT NULL) +SERVER package_server OPTIONS (table_name 'package_build_config_constraints'); + +CREATE FOREIGN TABLE build_package_config_auxiliaries ( + tenant TEXT NOT NULL, + name CITEXT NOT NULL, + version_epoch INTEGER NOT NULL, + version_canonical_upstream TEXT NOT NULL, + version_canonical_release TEXT NOT NULL COLLATE "C", + version_revision INTEGER NOT NULL, + config_index BIGINT NOT NULL, + index BIGINT NOT NULL, + environment_name TEXT NOT NULL, + config TEXT NOT NULL, + comment TEXT NOT NULL) +SERVER package_server OPTIONS (table_name 'package_build_config_auxiliaries'); + +CREATE FOREIGN TABLE build_package_config_bot_keys ( + tenant TEXT NOT NULL, + name CITEXT NOT NULL, + version_epoch INTEGER NOT NULL, + version_canonical_upstream TEXT NOT NULL, + version_canonical_release TEXT NOT NULL COLLATE "C", + version_revision INTEGER NOT NULL, + config_index BIGINT NOT NULL, + index BIGINT NOT NULL, + key_tenant TEXT NOT NULL, + key_fingerprint TEXT NOT NULL) +SERVER package_server OPTIONS (table_name 'package_build_config_bot_keys'); diff --git a/libbrep/build-package.hxx b/libbrep/build-package.hxx index c288f07..9a9c277 100644 --- a/libbrep/build-package.hxx +++ b/libbrep/build-package.hxx @@ -1,11 +1,12 @@ // file : libbrep/build-package.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef LIBBREP_BUILD_PACKAGE_HXX #define LIBBREP_BUILD_PACKAGE_HXX #include <odb/core.hxx> +#include <odb/section.hxx> +#include <odb/nested-container.hxx> #include <libbrep/types.hxx> #include <libbrep/utility.hxx> @@ -22,16 +23,23 @@ namespace brep // // The mapping is established in build-extra.sql. We also explicitly mark // non-primary key foreign-mapped members in the source object. - // + // Foreign object that is mapped to a subset of the tenant object. // - #pragma db object table("build_tenant") pointer(shared_ptr) readonly + // Note: table created manually thus assign table name explicitly. + // + #pragma db object table("build_tenant") pointer(shared_ptr) class build_tenant { public: string id; + bool private_; + optional<string> interactive; bool archived; + optional<tenant_service> service; + optional<timestamp> queued_timestamp; + optional<build_toolchain> toolchain; // Database mapping. // @@ -44,6 +52,8 @@ namespace brep // Foreign object that is mapped to a subset of the repository object. // + // Note: table created manually thus assign table name explicitly. + // #pragma db object table("build_repository") pointer(shared_ptr) readonly class build_repository { @@ -69,39 +79,268 @@ namespace brep build_repository (): canonical_name (id.canonical_name) {} }; + // Foreign object that is mapped to a subset of the public key object. + // + // Note: table created manually thus assign table name explicitly. + // + #pragma db object table("build_public_key") pointer(shared_ptr) readonly + class build_public_key: public string + { + public: + public_key_id id; + + // Database mapping. + // + #pragma db member(id) id column("") + + #pragma db member(data) virtual(string) access(this) + + private: + friend class odb::access; + build_public_key () = default; + }; + + // build_package_config + // + using build_package_config = + build_package_config_template<lazy_shared_ptr<build_public_key>>; + + using build_package_configs = + build_package_configs_template<lazy_shared_ptr<build_public_key>>; + + #pragma db value(build_package_config) definition + + #pragma db member(build_package_config::builds) transient + #pragma db member(build_package_config::constraints) transient + #pragma db member(build_package_config::auxiliaries) transient + #pragma db member(build_package_config::bot_keys) transient + + // build_package_bot_keys + // + using build_package_bot_keys = vector<lazy_shared_ptr<build_public_key>>; + using build_package_bot_key_key = odb::nested_key<build_package_bot_keys>; + + using build_package_bot_keys_map = + std::map<build_package_bot_key_key, lazy_shared_ptr<build_public_key>>; + + #pragma db value(build_package_bot_key_key) + #pragma db member(build_package_bot_key_key::outer) column("config_index") + #pragma db member(build_package_bot_key_key::inner) column("index") + + // Forward declarations. + // + class build_package; + + // Build package dependency. + // + #pragma db value + struct build_dependency + { + package_name name; + optional<version_constraint> constraint; + + lazy_shared_ptr<build_package> package; + + // Database mapping. + // + #pragma db member(constraint) column("") + }; + + // Build package external test dependency. + // + #pragma db value + struct build_test_dependency: build_dependency + { + test_dependency_type type; + bool buildtime; + optional<string> enable; + optional<string> reflect; + }; + // Foreign object that is mapped to a subset of the package object. // + // Note: table created manually thus assign table name explicitly. + // #pragma db object table("build_package") pointer(shared_ptr) readonly session class build_package { public: + using requirements_type = brep::requirements; + package_id id; upstream_version version; + + package_name project; + + optional<email> build_email; + optional<email> build_warning_email; + optional<email> build_error_email; + + // Mapped to the package object requirements and tests members using the + // PostgreSQL foreign table mechanism. + // + requirements_type requirements; + small_vector<build_test_dependency, 1> tests; + + odb::section requirements_tests_section; + lazy_shared_ptr<build_repository> internal_repository; bool buildable; + optional<bool> custom_bot; - // Mapped to the package object builds member using the PostgreSQL foreign - // table mechanism. + // Mapped to the package object builds, build_constraints, + // build_auxiliaries, bot_keys, and build_configs members using the + // PostgreSQL foreign table mechanism. // - build_class_exprs builds; + build_class_exprs builds; + build_constraints constraints; + build_auxiliaries auxiliaries; + build_package_bot_keys bot_keys; + build_package_configs configs; - // Mapped to the package object build_constraints member using the - // PostgreSQL foreign table mechanism. + // Group the builds/constraints, auxiliaries, and bot_keys members of this + // object together with their respective nested configs entries into the + // separate sections for an explicit load. Note that the configs top-level + // members are loaded implicitly. // - build_constraints constraints; + odb::section constraints_section; + odb::section auxiliaries_section; + odb::section bot_keys_section; + + bool + internal () const noexcept {return internal_repository != nullptr;} // Database mapping. // #pragma db member(id) id column("") #pragma db member(version) set(this.version.init (this.id.version, (?))) - #pragma db member(builds) id_column("") value_column("") - #pragma db member(constraints) id_column("") value_column("") + + // requirements + // + // Note that this is a 2-level nested container (see package.hxx for + // details). + // + + // Container of the requirement_alternatives values. + // + #pragma db member(requirements) id_column("") value_column("") \ + section(requirements_tests_section) + + // Container of the requirement_alternative values. + // + #pragma db member(requirement_alternatives) \ + virtual(requirement_alternatives_map) \ + after(requirements) \ + get(odb::nested_get (this.requirements)) \ + set(odb::nested_set (this.requirements, std::move (?))) \ + id_column("") key_column("") value_column("") \ + section(requirements_tests_section) + + // Container of the requirement (string) values. + // + #pragma db member(requirement_alternative_requirements) \ + virtual(requirement_alternative_requirements_map) \ + after(requirement_alternatives) \ + get(odb::nested2_get (this.requirements)) \ + set(odb::nested2_set (this.requirements, std::move (?))) \ + id_column("") key_column("") value_column("id") \ + section(requirements_tests_section) + + // tests + // + #pragma db member(tests) id_column("") value_column("test_") \ + section(requirements_tests_section) + + #pragma db member(requirements_tests_section) load(lazy) update(always) + + // builds, constraints, auxiliaries, and bot_keys + // + #pragma db member(builds) id_column("") value_column("") \ + section(constraints_section) + + #pragma db member(constraints) id_column("") value_column("") \ + section(constraints_section) + + #pragma db member(auxiliaries) id_column("") value_column("") \ + section(auxiliaries_section) + + #pragma db member(bot_keys) id_column("") value_column("key_") \ + section(bot_keys_section) + + // configs + // + // Note that build_package_config::{builds,constraints,auxiliaries,bot_keys} + // are persisted/loaded via the separate nested containers (see + // commons.hxx for details). + // + #pragma db member(configs) id_column("") value_column("config_") + + #pragma db member(config_builds) \ + virtual(build_class_exprs_map) \ + after(configs) \ + get(odb::nested_get ( \ + brep::build_package_config_builds (this.configs))) \ + set(brep::build_package_config_builds bs; \ + odb::nested_set (bs, std::move (?)); \ + move (bs).to_configs (this.configs)) \ + id_column("") key_column("") value_column("") \ + section(constraints_section) + + #pragma db member(config_constraints) \ + virtual(build_constraints_map) \ + after(config_builds) \ + get(odb::nested_get ( \ + brep::build_package_config_constraints (this.configs))) \ + set(brep::build_package_config_constraints cs; \ + odb::nested_set (cs, std::move (?)); \ + move (cs).to_configs (this.configs)) \ + id_column("") key_column("") value_column("") \ + section(constraints_section) + + #pragma db member(config_auxiliaries) \ + virtual(build_auxiliaries_map) \ + after(config_constraints) \ + get(odb::nested_get ( \ + brep::build_package_config_auxiliaries (this.configs))) \ + set(brep::build_package_config_auxiliaries as; \ + odb::nested_set (as, std::move (?)); \ + move (as).to_configs (this.configs)) \ + id_column("") key_column("") value_column("") \ + section(auxiliaries_section) + + #pragma db member(config_bot_keys) \ + virtual(build_package_bot_keys_map) \ + after(config_auxiliaries) \ + get(odb::nested_get ( \ + brep::build_package_config_bot_keys< \ + lazy_shared_ptr<brep::build_public_key>> (this.configs))) \ + set(brep::build_package_config_bot_keys< \ + lazy_shared_ptr<brep::build_public_key>> bks; \ + odb::nested_set (bks, std::move (?)); \ + move (bks).to_configs (this.configs)) \ + id_column("") key_column("") value_column("key_") \ + section(bot_keys_section) + + #pragma db member(constraints_section) load(lazy) update(always) + #pragma db member(auxiliaries_section) load(lazy) update(always) + #pragma db member(bot_keys_section) load(lazy) update(always) private: friend class odb::access; build_package () = default; }; + #pragma db view object(build_package) + struct build_package_version + { + package_id id; + upstream_version version; + + // Database mapping. + // + #pragma db member(version) set(this.version.init (this.id.version, (?))) + }; + // Packages that can potentially be built. // // Note that ADL can't find the equal operator, so we use the function call @@ -116,12 +355,13 @@ namespace brep object(build_tenant: build_package::id.tenant == build_tenant::id) struct buildable_package { - package_id id; - upstream_version version; + shared_ptr<build_package> package; - // Database mapping. + bool archived; // True if the tenant the package belongs to is archived. + + // Present if the tenant the package belongs to is interactive. // - #pragma db member(version) set(this.version.init (this.id.version, (?))) + optional<string> interactive; }; #pragma db view \ diff --git a/libbrep/build.cxx b/libbrep/build.cxx index 45ef678..13f0818 100644 --- a/libbrep/build.cxx +++ b/libbrep/build.cxx @@ -1,5 +1,4 @@ // file : libbrep/build.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #include <libbrep/build.hxx> @@ -13,6 +12,7 @@ namespace brep { switch (s) { + case build_state::queued: return "queued"; case build_state::building: return "building"; case build_state::built: return "built"; } @@ -23,9 +23,10 @@ namespace brep build_state to_build_state (const string& s) { - if (s == "building") return build_state::building; + if (s == "queued") return build_state::queued; + else if (s == "building") return build_state::building; else if (s == "built") return build_state::built; - else throw invalid_argument ("invalid build state '" + s + "'"); + else throw invalid_argument ("invalid build state '" + s + '\''); } // force_state @@ -49,7 +50,7 @@ namespace brep if (s == "unforced") return force_state::unforced; else if (s == "forcing") return force_state::forcing; else if (s == "forced") return force_state::forced; - else throw invalid_argument ("invalid force state '" + s + "'"); + else throw invalid_argument ("invalid force state '" + s + '\''); } // build @@ -58,27 +59,194 @@ namespace brep build (string tnt, package_name_type pnm, version pvr, - string cfg, + target_triplet trg, + string tcf, + string pcf, string tnm, version tvr, + optional<string> inr, optional<string> afp, optional<string> ach, - string mnm, string msm, - butl::target_triplet trg) + build_machine mcn, + vector<build_machine> ams, + string ccs, + string mcs) : id (package_id (move (tnt), move (pnm), pvr), - move (cfg), + move (trg), + move (tcf), + move (pcf), move (tnm), tvr), tenant (id.package.tenant), package_name (id.package.name), package_version (move (pvr)), - configuration (id.configuration), + target (id.target), + target_config_name (id.target_config_name), + package_config_name (id.package_config_name), toolchain_name (id.toolchain_name), toolchain_version (move (tvr)), state (build_state::building), + interactive (move (inr)), timestamp (timestamp_type::clock::now ()), force (force_state::unforced), agent_fingerprint (move (afp)), agent_challenge (move (ach)), - machine (move (mnm)), - machine_summary (move (msm)), - target (move (trg)) + machine (move (mcn)), + auxiliary_machines (move (ams)), + controller_checksum (move (ccs)), + machine_checksum (move (mcs)) + { + } + + build:: + build (string tnt, + package_name_type pnm, + version pvr, + target_triplet trg, + string tcf, + string pcf, + string tnm, version tvr) + : id (package_id (move (tnt), move (pnm), pvr), + move (trg), + move (tcf), + move (pcf), + move (tnm), tvr), + tenant (id.package.tenant), + package_name (id.package.name), + package_version (move (pvr)), + target (id.target), + target_config_name (id.target_config_name), + package_config_name (id.package_config_name), + toolchain_name (id.toolchain_name), + toolchain_version (move (tvr)), + state (build_state::queued), + timestamp (timestamp_type::clock::now ()), + force (force_state::unforced) + { + } + + build:: + build (string tnt, + package_name_type pnm, + version pvr, + target_triplet trg, + string tcf, + string pcf, + string tnm, version tvr, + result_status rst, + operation_results ors, + build_machine mcn, + vector<build_machine> ams) + : id (package_id (move (tnt), move (pnm), pvr), + move (trg), + move (tcf), + move (pcf), + move (tnm), tvr), + tenant (id.package.tenant), + package_name (id.package.name), + package_version (move (pvr)), + target (id.target), + target_config_name (id.target_config_name), + package_config_name (id.package_config_name), + toolchain_name (id.toolchain_name), + toolchain_version (move (tvr)), + state (build_state::built), + timestamp (timestamp_type::clock::now ()), + force (force_state::unforced), + status (rst), + soft_timestamp (timestamp), + hard_timestamp (timestamp), + machine (move (mcn)), + auxiliary_machines (move (ams)), + results (move (ors)) + { + } + + build:: + build (build&& b) + : id (move (b.id)), + tenant (id.package.tenant), + package_name (id.package.name), + package_version (move (b.package_version)), + target (id.target), + target_config_name (id.target_config_name), + package_config_name (id.package_config_name), + toolchain_name (id.toolchain_name), + toolchain_version (move (b.toolchain_version)), + state (b.state), + interactive (move (b.interactive)), + timestamp (b.timestamp), + force (b.force), + status (b.status), + soft_timestamp (b.soft_timestamp), + hard_timestamp (b.hard_timestamp), + agent_fingerprint (move (b.agent_fingerprint)), + agent_challenge (move (b.agent_challenge)), + machine (move (b.machine)), + auxiliary_machines (move (b.auxiliary_machines)), + auxiliary_machines_section (move (b.auxiliary_machines_section)), + results (move (b.results)), + results_section (move (b.results_section)), + controller_checksum (move (b.controller_checksum)), + machine_checksum (move (b.machine_checksum)), + agent_checksum (move (b.agent_checksum)), + worker_checksum (move (b.worker_checksum)), + dependency_checksum (move (b.dependency_checksum)) + { + } + + build& build:: + operator= (build&& b) + { + if (this != &b) + { + id = move (b.id); + package_version = move (b.package_version); + toolchain_version = move (b.toolchain_version); + state = b.state; + interactive = move (b.interactive); + timestamp = b.timestamp; + force = b.force; + status = b.status; + soft_timestamp = b.soft_timestamp; + hard_timestamp = b.hard_timestamp; + agent_fingerprint = move (b.agent_fingerprint); + agent_challenge = move (b.agent_challenge); + machine = move (b.machine); + auxiliary_machines = move (b.auxiliary_machines); + auxiliary_machines_section = move (b.auxiliary_machines_section); + results = move (b.results); + results_section = move (b.results_section); + controller_checksum = move (b.controller_checksum); + machine_checksum = move (b.machine_checksum); + agent_checksum = move (b.agent_checksum); + worker_checksum = move (b.worker_checksum); + dependency_checksum = move (b.dependency_checksum); + } + + return *this; + } + + // build_delay + // + build_delay:: + build_delay (string tnt, + package_name_type pnm, version pvr, + target_triplet trg, + string tcf, + string pcf, + string tnm, version tvr, + timestamp ptm) + : id (package_id (move (tnt), move (pnm), pvr), + move (trg), + move (tcf), + move (pcf), + move (tnm), tvr), + tenant (id.package.tenant), + package_name (id.package.name), + package_version (move (pvr)), + target (id.target), + target_config_name (id.target_config_name), + package_config_name (id.package_config_name), + toolchain_name (id.toolchain_name), + toolchain_version (move (tvr)), + package_timestamp (ptm) { } } diff --git a/libbrep/build.hxx b/libbrep/build.hxx index fc9f675..af49c03 100644 --- a/libbrep/build.hxx +++ b/libbrep/build.hxx @@ -1,5 +1,4 @@ // file : libbrep/build.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef LIBBREP_BUILD_HXX @@ -10,28 +9,30 @@ #include <odb/core.hxx> #include <odb/section.hxx> -#include <libbutl/target-triplet.mxx> - -#include <libbbot/manifest.hxx> - #include <libbrep/types.hxx> #include <libbrep/utility.hxx> -// Must be included last (see assert in libbrep/common.hxx). -// #include <libbrep/common.hxx> #include <libbrep/build-package.hxx> +// Must be included after libbrep/common.hxx, so that the _version structure +// get defined before libbpkg/manifest.hxx inclusion. +// +// Note that if we start using assert() in get/set expressions in this header, +// we will have to redefine it for ODB compiler after all include directives +// (see libbrep/common.hxx for details). +// +#include <libbbot/manifest.hxx> + // Used by the data migration entries. // -#define LIBBREP_BUILD_SCHEMA_VERSION_BASE 9 +#define LIBBREP_BUILD_SCHEMA_VERSION_BASE 20 -#pragma db model version(LIBBREP_BUILD_SCHEMA_VERSION_BASE, 9, closed) +#pragma db model version(LIBBREP_BUILD_SCHEMA_VERSION_BASE, 27, closed) -// We have to keep these mappings at the global scope instead of inside -// the brep namespace because they need to be also effective in the -// bbot namespace from which we "borrow" types (and some of them use the mapped -// types). +// We have to keep these mappings at the global scope instead of inside the +// brep namespace because they need to be also effective in the bbot namespace +// from which we "borrow" types (and some of them use the mapped types). // #pragma db map type(bbot::result_status) as(std::string) \ to(to_string (?)) \ @@ -43,14 +44,23 @@ namespace brep struct build_id { package_id package; - string configuration; + target_triplet target; + string target_config_name; + string package_config_name; string toolchain_name; canonical_version toolchain_version; build_id () = default; - build_id (package_id p, string c, string n, const brep::version& v) + build_id (package_id p, + target_triplet t, + string tc, + string pc, + string n, + const brep::version& v) : package (move (p)), - configuration (move (c)), + target (move (t)), + target_config_name (move (tc)), + package_config_name (move (pc)), toolchain_name (move (n)), toolchain_version (v) {} }; @@ -61,7 +71,13 @@ namespace brep if (x.package != y.package) return x.package < y.package; - if (int r = x.configuration.compare (y.configuration)) + if (int r = x.target.compare (y.target)) + return r < 0; + + if (int r = x.target_config_name.compare (y.target_config_name)) + return r < 0; + + if (int r = x.package_config_name.compare (y.package_config_name)) return r < 0; if (int r = x.toolchain_name.compare (y.toolchain_name)) @@ -70,7 +86,7 @@ namespace brep return compare_version_lt (x.toolchain_version, y.toolchain_version, true); } - // These allow comparing objects that have package, configuration, + // These allow comparing objects that have package, configuration, target, // toolchain_name, and toolchain_version data members to build_id values. // The idea is that this works for both query members of build id types as // well as for values of the build_id type. @@ -78,35 +94,84 @@ namespace brep template <typename T> inline auto operator== (const T& x, const build_id& y) - -> decltype (x.package == y.package && - x.configuration == y.configuration && - x.toolchain_name == y.toolchain_name && + -> decltype (x.package == y.package && + x.target == y.target && + x.target_config_name == y.target_config_name && + x.package_config_name == y.package_config_name && + x.toolchain_name == y.toolchain_name && x.toolchain_version.epoch == y.toolchain_version.epoch) { - return x.package == y.package && - x.configuration == y.configuration && - x.toolchain_name == y.toolchain_name && + return x.package == y.package && + x.target == y.target && + x.target_config_name == y.target_config_name && + x.package_config_name == y.package_config_name && + x.toolchain_name == y.toolchain_name && compare_version_eq (x.toolchain_version, y.toolchain_version, true); } template <typename T> inline auto operator!= (const T& x, const build_id& y) - -> decltype (x.package == y.package && - x.configuration == y.configuration && - x.toolchain_name == y.toolchain_name && + -> decltype (x.package == y.package && + x.target == y.target && + x.target_config_name == y.target_config_name && + x.package_config_name == y.package_config_name && + x.toolchain_name == y.toolchain_name && x.toolchain_version.epoch == y.toolchain_version.epoch) { - return x.package != y.package || - x.configuration != y.configuration || - x.toolchain_name != y.toolchain_name || + return x.package != y.package || + x.target != y.target || + x.target_config_name != y.target_config_name || + x.package_config_name != y.package_config_name || + x.toolchain_name != y.toolchain_name || compare_version_ne (x.toolchain_version, y.toolchain_version, true); } + // Allow comparing the query members with the query parameters bound by + // reference to variables of the build id type (in particular in the + // prepared queries). + // + // Note that it is not operator==() since the query template parameter type + // can not be deduced from the function parameter types and needs to be + // specified explicitly. + // + template <typename T, typename ID> + inline auto + equal (const ID& x, const build_id& y, bool toolchain_version = true) + -> decltype (x.package.tenant == odb::query<T>::_ref (y.package.tenant) && + x.package.name == odb::query<T>::_ref (y.package.name) && + x.package.version.epoch == + odb::query<T>::_ref (y.package.version.epoch) && + x.target_config_name == + odb::query<T>::_ref (y.target_config_name) && + x.toolchain_name == odb::query<T>::_ref (y.toolchain_name) && + x.toolchain_version.epoch == + odb::query<T>::_ref (y.toolchain_version.epoch)) + { + using query = odb::query<T>; + + query r (equal<T> (x.package, y.package) && + x.target == query::_ref (y.target) && + x.target_config_name == query::_ref (y.target_config_name) && + x.package_config_name == query::_ref (y.package_config_name) && + x.toolchain_name == query::_ref (y.toolchain_name)); + + if (toolchain_version) + r = r && equal<T> (x.toolchain_version, y.toolchain_version); + + return r; + } + // build_state // + // The queued build state is semantically equivalent to a non-existent + // build. It is only used for those tenants, which have a third-party + // service associated that requires the `queued` notifications (see + // mod/tenant-service.hxx for background). + // enum class build_state: std::uint8_t { + queued, building, built }; @@ -158,12 +223,6 @@ namespace brep ? bbot::to_result_status (*(?)) \ : brep::optional_result_status ()) - // target_triplet - // - #pragma db map type(butl::target_triplet) as(string) \ - to((?).string ()) \ - from(butl::target_triplet (?)) - // operation_results // using bbot::operation_result; @@ -171,6 +230,13 @@ namespace brep using bbot::operation_results; + #pragma db value + struct build_machine + { + string name; + string summary; + }; + #pragma db object pointer(shared_ptr) session class build { @@ -179,29 +245,72 @@ namespace brep using package_name_type = brep::package_name; // Create the build object with the building state, non-existent status, - // the timestamp set to now and the force state set to unforced. + // the timestamp set to now, and the force state set to unforced. // build (string tenant, - package_name_type, - version, - string configuration, + package_name_type, version, + target_triplet, + string target_config_name, + string package_config_name, string toolchain_name, version toolchain_version, + optional<string> interactive, optional<string> agent_fingerprint, optional<string> agent_challenge, - string machine, string machine_summary, - butl::target_triplet); + build_machine, + vector<build_machine> auxiliary_machines, + string controller_checksum, + string machine_checksum); + + // Create the build object with the queued state. + // + build (string tenant, + package_name_type, version, + target_triplet, + string target_config_name, + string package_config_name, + string toolchain_name, version toolchain_version); + + // Create the build object with the built state, the specified status and + // operation results, all the timestamps set to now, and the force state + // set to unforced. + // + build (string tenant, + package_name_type, version, + target_triplet, + string target_config_name, + string package_config_name, + string toolchain_name, version toolchain_version, + result_status, + operation_results, + build_machine, + vector<build_machine> auxiliary_machines = {}); + + // Move-only type. + // + build (build&&); + build& operator= (build&&); + + build (const build&) = delete; + build& operator= (const build&) = delete; build_id id; string& tenant; // Tracks id.package.tenant. package_name_type& package_name; // Tracks id.package.name. upstream_version package_version; // Original of id.package.version. - string& configuration; // Tracks id.configuration. + target_triplet& target; // Tracks id.target. + string& target_config_name; // Tracks id.target_config_name. + string& package_config_name; // Tracks id.package_config_name. string& toolchain_name; // Tracks id.toolchain_name. upstream_version toolchain_version; // Original of id.toolchain_version. build_state state; + // If present, the login information for the interactive build. May be + // present only in the building state. + // + optional<string> interactive; + // Time of the last state change (the creation time initially). // timestamp_type timestamp; @@ -213,14 +322,35 @@ namespace brep // optional<result_status> status; + // Times of the last soft/hard completed (re)builds. Used to decide when + // to perform soft and hard rebuilds, respectively. + // + // The soft timestamp is updated whenever we receive a task result. + // + // The hard timestamp is updated whenever we receive a task result with + // a status other than skip. + // + // Also note that whenever hard_timestamp is updated, soft_timestamp is + // updated as well and whenever soft_timestamp is updated, timestamp is + // updated as well. Thus the following condition is always true: + // + // hard_timestamp <= soft_timestamp <= timestamp + // + // Note that the "completed" above means that we may analyze the task + // result/log and deem it as not completed and proceed with automatic + // rebuild (the flake monitor idea). + // + timestamp_type soft_timestamp; + timestamp_type hard_timestamp; + // May be present only for the building state. // optional<string> agent_fingerprint; optional<string> agent_challenge; - string machine; - string machine_summary; - butl::target_triplet target; + build_machine machine; + vector<build_machine> auxiliary_machines; + odb::section auxiliary_machines_section; // Note that the logs are stored as std::string/TEXT which is Ok since // they are UTF-8 and our database is UTF-8. @@ -228,6 +358,21 @@ namespace brep operation_results results; odb::section results_section; + // Checksums of entities involved in the build. + // + // Optional checksums are provided by the external entities (agent and + // worker). All are absent initially. + // + // Note that the agent checksum can also be absent after the hard rebuild + // task is issued and the worker and dependency checksums - after a failed + // rebuild (error result status or worse). + // + string controller_checksum; + string machine_checksum; + optional<string> agent_checksum; + optional<string> worker_checksum; + optional<string> dependency_checksum; + // Database mapping. // #pragma db member(id) id column("") @@ -236,7 +381,9 @@ namespace brep #pragma db member(package_name) transient #pragma db member(package_version) \ set(this.package_version.init (this.id.package.version, (?))) - #pragma db member(configuration) transient + #pragma db member(target) transient + #pragma db member(target_config_name) transient + #pragma db member(package_config_name) transient #pragma db member(toolchain_name) transient #pragma db member(toolchain_version) \ set(this.toolchain_version.init (this.id.toolchain_version, (?))) @@ -245,24 +392,34 @@ namespace brep // #pragma db member(timestamp) index + #pragma db member(machine) transient + + #pragma db member(machine_name) virtual(std::string) \ + access(machine.name) column("machine") + + #pragma db member(machine_summary) virtual(std::string) \ + access(machine.summary) + + #pragma db member(auxiliary_machines) id_column("") value_column("") \ + section(auxiliary_machines_section) + + #pragma db member(auxiliary_machines_section) load(lazy) update(always) + #pragma db member(results) id_column("") value_column("") \ section(results_section) #pragma db member(results_section) load(lazy) update(always) - build (const build&) = delete; - build& operator= (const build&) = delete; - private: friend class odb::access; build () : tenant (id.package.tenant), package_name (id.package.name), - configuration (id.configuration), - toolchain_name (id.toolchain_name) - { - } + target (id.target), + target_config_name (id.target_config_name), + package_config_name (id.package_config_name), + toolchain_name (id.toolchain_name) {} }; // Note that ADL can't find the equal operator in join conditions, so we use @@ -312,7 +469,7 @@ namespace brep canonical_version version_; }; - // Build of an existing buildable package. + // Builds of existing buildable packages. // #pragma db view \ object(build) \ @@ -323,6 +480,7 @@ namespace brep struct package_build { shared_ptr<brep::build> build; + bool archived; // True if the tenant the build belongs to is archived. }; #pragma db view \ @@ -341,6 +499,93 @@ namespace brep // #pragma db member(result) column("count(" + build::id.package.name + ")") }; + + // Ids of existing buildable package builds. + // + #pragma db view object(build) \ + object(build_package inner: \ + brep::operator== (build::id.package, build_package::id) && \ + build_package::buildable) + struct package_build_id + { + build_id id; + + operator build_id& () {return id;} + }; + + // Used to track the package build delays since the last build or, if not + // present, since the first opportunity to build the package. + // + #pragma db object pointer(shared_ptr) session + class build_delay + { + public: + using package_name_type = brep::package_name; + + // If toolchain version is empty, then the object represents a minimum + // delay across all versions of the toolchain. + // + build_delay (string tenant, + package_name_type, version, + target_triplet, + string target_config_name, + string package_config_name, + string toolchain_name, version toolchain_version, + timestamp package_timestamp); + + build_id id; + + string& tenant; // Tracks id.package.tenant. + package_name_type& package_name; // Tracks id.package.name. + upstream_version package_version; // Original of id.package.version. + target_triplet& target; // Tracks id.target. + string& target_config_name; // Tracks id.target_config_name. + string& package_config_name; // Tracks id.package_config_name. + string& toolchain_name; // Tracks id.toolchain_name. + upstream_version toolchain_version; // Original of id.toolchain_version. + + // Times of the latest soft and hard rebuild delay reports. Initialized + // with timestamp_nonexistent by default. + // + // Note that both reports notify about initial build delays (at their + // respective time intervals). + // + timestamp report_soft_timestamp; + timestamp report_hard_timestamp; + + // Time when the package is initially considered as buildable for this + // configuration and toolchain. It is used to track the build delay if the + // build object is absent (the first build task is not yet issued, the + // build is removed by brep-clean, etc). + // + timestamp package_timestamp; + + // Database mapping. + // + #pragma db member(id) id column("") + + #pragma db member(tenant) transient + #pragma db member(package_name) transient + #pragma db member(package_version) \ + set(this.package_version.init (this.id.package.version, (?))) + #pragma db member(target) transient + #pragma db member(target_config_name) transient + #pragma db member(package_config_name) transient + #pragma db member(toolchain_name) transient + #pragma db member(toolchain_version) \ + set(this.toolchain_version.init (this.id.toolchain_version, (?))) + + private: + friend class odb::access; + + build_delay () + : tenant (id.package.tenant), + package_name (id.package.name), + target (id.target), + target_config_name (id.target_config_name), + package_config_name (id.package_config_name), + toolchain_name (id.toolchain_name) {} + }; } #endif // LIBBREP_BUILD_HXX diff --git a/libbrep/build.xml b/libbrep/build.xml index 3ade7c8..1eba85a 100644 --- a/libbrep/build.xml +++ b/libbrep/build.xml @@ -1,5 +1,90 @@ <changelog xmlns="http://www.codesynthesis.com/xmlns/odb/changelog" database="pgsql" schema-name="build" version="1"> - <model version="9"> + <changeset version="27"/> + + <changeset version="26"/> + + <changeset version="25"> + <add-table name="build_auxiliary_machines" kind="container"> + <column name="package_tenant" type="TEXT" null="false"/> + <column name="package_name" type="CITEXT" null="false"/> + <column name="package_version_epoch" type="INTEGER" null="false"/> + <column name="package_version_canonical_upstream" type="TEXT" null="false"/> + <column name="package_version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> + <column name="package_version_revision" type="INTEGER" null="false"/> + <column name="target" type="TEXT" null="false"/> + <column name="target_config_name" type="TEXT" null="false"/> + <column name="package_config_name" type="TEXT" null="false"/> + <column name="toolchain_name" type="TEXT" null="false"/> + <column name="toolchain_version_epoch" type="INTEGER" null="false"/> + <column name="toolchain_version_canonical_upstream" type="TEXT" null="false"/> + <column name="toolchain_version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> + <column name="toolchain_version_revision" type="INTEGER" null="false"/> + <column name="index" type="BIGINT" null="false"/> + <column name="name" type="TEXT" null="false"/> + <column name="summary" type="TEXT" null="false"/> + <foreign-key name="object_id_fk" on-delete="CASCADE"> + <column name="package_tenant"/> + <column name="package_name"/> + <column name="package_version_epoch"/> + <column name="package_version_canonical_upstream"/> + <column name="package_version_canonical_release"/> + <column name="package_version_revision"/> + <column name="target"/> + <column name="target_config_name"/> + <column name="package_config_name"/> + <column name="toolchain_name"/> + <column name="toolchain_version_epoch"/> + <column name="toolchain_version_canonical_upstream"/> + <column name="toolchain_version_canonical_release"/> + <column name="toolchain_version_revision"/> + <references table="build"> + <column name="package_tenant"/> + <column name="package_name"/> + <column name="package_version_epoch"/> + <column name="package_version_canonical_upstream"/> + <column name="package_version_canonical_release"/> + <column name="package_version_revision"/> + <column name="target"/> + <column name="target_config_name"/> + <column name="package_config_name"/> + <column name="toolchain_name"/> + <column name="toolchain_version_epoch"/> + <column name="toolchain_version_canonical_upstream"/> + <column name="toolchain_version_canonical_release"/> + <column name="toolchain_version_revision"/> + </references> + </foreign-key> + <index name="build_auxiliary_machines_object_id_i"> + <column name="package_tenant"/> + <column name="package_name"/> + <column name="package_version_epoch"/> + <column name="package_version_canonical_upstream"/> + <column name="package_version_canonical_release"/> + <column name="package_version_revision"/> + <column name="target"/> + <column name="target_config_name"/> + <column name="package_config_name"/> + <column name="toolchain_name"/> + <column name="toolchain_version_epoch"/> + <column name="toolchain_version_canonical_upstream"/> + <column name="toolchain_version_canonical_release"/> + <column name="toolchain_version_revision"/> + </index> + <index name="build_auxiliary_machines_index_i"> + <column name="index"/> + </index> + </add-table> + </changeset> + + <changeset version="24"/> + + <changeset version="23"/> + + <changeset version="22"/> + + <changeset version="21"/> + + <model version="20"> <table name="build" kind="object"> <column name="package_tenant" type="TEXT" null="false"/> <column name="package_name" type="CITEXT" null="false"/> @@ -7,7 +92,9 @@ <column name="package_version_canonical_upstream" type="TEXT" null="false"/> <column name="package_version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> <column name="package_version_revision" type="INTEGER" null="false"/> - <column name="configuration" type="TEXT" null="false"/> + <column name="target" type="TEXT" null="false"/> + <column name="target_config_name" type="TEXT" null="false"/> + <column name="package_config_name" type="TEXT" null="false"/> <column name="toolchain_name" type="TEXT" null="false"/> <column name="toolchain_version_epoch" type="INTEGER" null="false"/> <column name="toolchain_version_canonical_upstream" type="TEXT" null="false"/> @@ -18,14 +105,21 @@ <column name="toolchain_version_upstream" type="TEXT" null="false"/> <column name="toolchain_version_release" type="TEXT" null="true"/> <column name="state" type="TEXT" null="false"/> + <column name="interactive" type="TEXT" null="true"/> <column name="timestamp" type="BIGINT" null="false"/> <column name="force" type="TEXT" null="false"/> <column name="status" type="TEXT" null="true"/> + <column name="soft_timestamp" type="BIGINT" null="false"/> + <column name="hard_timestamp" type="BIGINT" null="false"/> <column name="agent_fingerprint" type="TEXT" null="true"/> <column name="agent_challenge" type="TEXT" null="true"/> <column name="machine" type="TEXT" null="false"/> <column name="machine_summary" type="TEXT" null="false"/> - <column name="target" type="TEXT" null="false"/> + <column name="controller_checksum" type="TEXT" null="false"/> + <column name="machine_checksum" type="TEXT" null="false"/> + <column name="agent_checksum" type="TEXT" null="true"/> + <column name="worker_checksum" type="TEXT" null="true"/> + <column name="dependency_checksum" type="TEXT" null="true"/> <primary-key> <column name="package_tenant"/> <column name="package_name"/> @@ -33,7 +127,9 @@ <column name="package_version_canonical_upstream"/> <column name="package_version_canonical_release"/> <column name="package_version_revision"/> - <column name="configuration"/> + <column name="target"/> + <column name="target_config_name"/> + <column name="package_config_name"/> <column name="toolchain_name"/> <column name="toolchain_version_epoch"/> <column name="toolchain_version_canonical_upstream"/> @@ -51,7 +147,9 @@ <column name="package_version_canonical_upstream" type="TEXT" null="false"/> <column name="package_version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> <column name="package_version_revision" type="INTEGER" null="false"/> - <column name="configuration" type="TEXT" null="false"/> + <column name="target" type="TEXT" null="false"/> + <column name="target_config_name" type="TEXT" null="false"/> + <column name="package_config_name" type="TEXT" null="false"/> <column name="toolchain_name" type="TEXT" null="false"/> <column name="toolchain_version_epoch" type="INTEGER" null="false"/> <column name="toolchain_version_canonical_upstream" type="TEXT" null="false"/> @@ -68,7 +166,9 @@ <column name="package_version_canonical_upstream"/> <column name="package_version_canonical_release"/> <column name="package_version_revision"/> - <column name="configuration"/> + <column name="target"/> + <column name="target_config_name"/> + <column name="package_config_name"/> <column name="toolchain_name"/> <column name="toolchain_version_epoch"/> <column name="toolchain_version_canonical_upstream"/> @@ -81,7 +181,9 @@ <column name="package_version_canonical_upstream"/> <column name="package_version_canonical_release"/> <column name="package_version_revision"/> - <column name="configuration"/> + <column name="target"/> + <column name="target_config_name"/> + <column name="package_config_name"/> <column name="toolchain_name"/> <column name="toolchain_version_epoch"/> <column name="toolchain_version_canonical_upstream"/> @@ -96,7 +198,9 @@ <column name="package_version_canonical_upstream"/> <column name="package_version_canonical_release"/> <column name="package_version_revision"/> - <column name="configuration"/> + <column name="target"/> + <column name="target_config_name"/> + <column name="package_config_name"/> <column name="toolchain_name"/> <column name="toolchain_version_epoch"/> <column name="toolchain_version_canonical_upstream"/> @@ -107,5 +211,44 @@ <column name="index"/> </index> </table> + <table name="build_delay" kind="object"> + <column name="package_tenant" type="TEXT" null="false"/> + <column name="package_name" type="CITEXT" null="false"/> + <column name="package_version_epoch" type="INTEGER" null="false"/> + <column name="package_version_canonical_upstream" type="TEXT" null="false"/> + <column name="package_version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> + <column name="package_version_revision" type="INTEGER" null="false"/> + <column name="target" type="TEXT" null="false"/> + <column name="target_config_name" type="TEXT" null="false"/> + <column name="package_config_name" type="TEXT" null="false"/> + <column name="toolchain_name" type="TEXT" null="false"/> + <column name="toolchain_version_epoch" type="INTEGER" null="false"/> + <column name="toolchain_version_canonical_upstream" type="TEXT" null="false"/> + <column name="toolchain_version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> + <column name="toolchain_version_revision" type="INTEGER" null="false"/> + <column name="package_version_upstream" type="TEXT" null="false"/> + <column name="package_version_release" type="TEXT" null="true"/> + <column name="toolchain_version_upstream" type="TEXT" null="false"/> + <column name="toolchain_version_release" type="TEXT" null="true"/> + <column name="report_soft_timestamp" type="BIGINT" null="false"/> + <column name="report_hard_timestamp" type="BIGINT" null="false"/> + <column name="package_timestamp" type="BIGINT" null="false"/> + <primary-key> + <column name="package_tenant"/> + <column name="package_name"/> + <column name="package_version_epoch"/> + <column name="package_version_canonical_upstream"/> + <column name="package_version_canonical_release"/> + <column name="package_version_revision"/> + <column name="target"/> + <column name="target_config_name"/> + <column name="package_config_name"/> + <column name="toolchain_name"/> + <column name="toolchain_version_epoch"/> + <column name="toolchain_version_canonical_upstream"/> + <column name="toolchain_version_canonical_release"/> + <column name="toolchain_version_revision"/> + </primary-key> + </table> </model> </changelog> diff --git a/libbrep/buildfile b/libbrep/buildfile index e649351..9a35a28 100644 --- a/libbrep/buildfile +++ b/libbrep/buildfile @@ -1,5 +1,4 @@ # file : libbrep/buildfile -# copyright : Copyright (c) 2014-2019 Code Synthesis Ltd # license : MIT; see accompanying LICENSE file define sql: file diff --git a/libbrep/common-traits.hxx b/libbrep/common-traits.hxx index 99002a2..141a738 100644 --- a/libbrep/common-traits.hxx +++ b/libbrep/common-traits.hxx @@ -1,5 +1,4 @@ // file : libbrep/common-traits.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef LIBBREP_COMMON_TRAITS_HXX @@ -11,12 +10,50 @@ #include <odb/pgsql/traits.hxx> +#include <libbutl/target-triplet.hxx> + #include <libbpkg/package-name.hxx> namespace odb { namespace pgsql { + // target_triplet + // + template <> + class value_traits<butl::target_triplet, id_string>: + value_traits<std::string, id_string> + { + public: + using value_type = butl::target_triplet; + using query_type = butl::target_triplet; + using image_type = details::buffer; + + using base_type = value_traits<std::string, id_string>; + + static void + set_value (value_type& v, + const details::buffer& b, + std::size_t n, + bool is_null) + { + std::string s; + base_type::set_value (s, b, n, is_null); + v = !s.empty () ? value_type (s) : value_type (); + } + + static void + set_image (details::buffer& b, + std::size_t& n, + bool& is_null, + const value_type& v) + { + base_type::set_image (b, n, is_null, v.string ()); + } + }; + + // package_name + // template <> class value_traits<bpkg::package_name, id_string>: value_traits<std::string, id_string> diff --git a/libbrep/common.cxx b/libbrep/common.cxx index b2429a6..4f729a3 100644 --- a/libbrep/common.cxx +++ b/libbrep/common.cxx @@ -1,5 +1,4 @@ // file : libbrep/common.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #include <libbrep/common.hxx> @@ -7,4 +6,30 @@ namespace brep { const version wildcard_version (0, "0", nullopt, nullopt, 0); + + // unbuildable_reason + // + string + to_string (unbuildable_reason r) + { + switch (r) + { + case unbuildable_reason::stub: return "stub"; + case unbuildable_reason::test: return "test"; + case unbuildable_reason::external: return "external"; + case unbuildable_reason::unbuildable: return "unbuildable"; + } + + return string (); // Should never reach. + } + + unbuildable_reason + to_unbuildable_reason (const string& r) + { + if (r == "stub") return unbuildable_reason::stub; + else if (r == "test") return unbuildable_reason::test; + else if (r == "external") return unbuildable_reason::external; + else if (r == "unbuildable") return unbuildable_reason::unbuildable; + else throw invalid_argument ("invalid unbuildable reason '" + r + '\''); + } } diff --git a/libbrep/common.hxx b/libbrep/common.hxx index 6dc4870..1433c8c 100644 --- a/libbrep/common.hxx +++ b/libbrep/common.hxx @@ -1,14 +1,19 @@ // file : libbrep/common.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef LIBBREP_COMMON_HXX #define LIBBREP_COMMON_HXX +#include <map> #include <ratio> #include <chrono> #include <type_traits> // static_assert +#include <odb/query.hxx> +#include <odb/nested-container.hxx> + +#include <libbutl/target-triplet.hxx> + #include <libbpkg/package-name.hxx> #include <libbrep/types.hxx> @@ -112,7 +117,7 @@ namespace brep std::chrono::nanoseconds::period>::value, "The following timestamp ODB mapping is invalid"); - // As it pointed out in libbutl/timestamp.mxx we will overflow in year 2262, + // As it pointed out in libbutl/timestamp.hxx we will overflow in year 2262, // but by that time some larger basic type will be available for mapping. // #pragma db map type(timestamp) as(uint64_t) \ @@ -122,6 +127,20 @@ namespace brep std::chrono::duration_cast<brep::timestamp::duration> ( \ std::chrono::nanoseconds (?)))) + using optional_timestamp = optional<timestamp>; + using optional_uint64 = optional<uint64_t>; + + #pragma db map type(optional_timestamp) as(brep::optional_uint64) \ + to((?) \ + ? std::chrono::duration_cast<std::chrono::nanoseconds> ( \ + (?)->time_since_epoch ()).count () \ + : brep::optional_uint64 ()) \ + from((?) \ + ? brep::timestamp ( \ + std::chrono::duration_cast<brep::timestamp::duration> ( \ + std::chrono::nanoseconds (*(?)))) \ + : brep::optional_timestamp ()) + // version // using bpkg::version; @@ -227,6 +246,12 @@ namespace brep // extern const version wildcard_version; + // target_triplet + // + using butl::target_triplet; + + #pragma db value(target_triplet) type("TEXT") + // package_name // using bpkg::package_name; @@ -301,6 +326,19 @@ namespace brep : tenant (move (t)), canonical_name (move (n)) {} }; + // public_key_id + // + #pragma db value + struct public_key_id + { + string tenant; + string fingerprint; + + public_key_id () = default; + public_key_id (string t, string f) + : tenant (move (t)), fingerprint (move (f)) {} + }; + // build_class_expr // using bpkg::build_class_expr; @@ -322,15 +360,326 @@ namespace brep #pragma db value(build_constraint) definition + // build_auxiliaries + // + using bpkg::build_auxiliary; + using build_auxiliaries = vector<build_auxiliary>; + + #pragma db value(build_auxiliary) definition + + // build_toolchain + // + #pragma db value + struct build_toolchain + { + string name; + brep::version version; + }; + + // email + // + using bpkg::email; + + #pragma db value(email) definition + #pragma db member(email::value) virtual(string) before access(this) column("") + + // build_package_config_template + // + using bpkg::build_package_config_template; + + // 1 for the default configuration which is always present. + // + template <typename K> + using build_package_configs_template = + small_vector<build_package_config_template<K>, 1>; + + // Return the address of the configuration object with the specified name, + // if present, and NULL otherwise. + // + template <typename K> + inline build_package_config_template<K>* + find (const string& name, build_package_configs_template<K>& cs) + { + auto i (find_if (cs.begin (), cs.end (), + [&name] (const build_package_config_template<K>& c) + {return c.name == name;})); + + return i != cs.end () ? &*i : nullptr; + } + + // Note that ODB doesn't support containers of value types which contain + // containers. Thus, we will persist/load + // build_package_config_template<K>::{builds,constraint,auxiliaries,bot_keys} + // via the separate nested containers using the adapter classes. + // + + // build_package_config_template<K>::builds + // + using build_class_expr_key = odb::nested_key<build_class_exprs>; + using build_class_exprs_map = std::map<build_class_expr_key, build_class_expr>; + + #pragma db value(build_class_expr_key) + #pragma db member(build_class_expr_key::outer) column("config_index") + #pragma db member(build_class_expr_key::inner) column("index") + + // Adapter for build_package_config_template<K>::builds. + // + // Note: 1 as for build_package_configs_template. + // + class build_package_config_builds: public small_vector<build_class_exprs, 1> + { + public: + build_package_config_builds () = default; + + template <typename K> + explicit + build_package_config_builds (const build_package_configs_template<K>& cs) + { + reserve (cs.size ()); + for (const build_package_config_template<K>& c: cs) + push_back (c.builds); + } + + template <typename K> + void + to_configs (build_package_configs_template<K>& cs) && + { + // Note that the empty trailing entries will be missing (see ODB's + // nested-container.hxx for details). + // + assert (size () <= cs.size ()); + + auto i (cs.begin ()); + for (build_class_exprs& ces: *this) + i++->builds = move (ces); + } + }; + + // build_package_config_template<K>::constraints + // + using build_constraint_key = odb::nested_key<build_constraints>; + using build_constraints_map = std::map<build_constraint_key, build_constraint>; + + #pragma db value(build_constraint_key) + #pragma db member(build_constraint_key::outer) column("config_index") + #pragma db member(build_constraint_key::inner) column("index") + + // Adapter for build_package_config_template<K>::constraints. + // + // Note: 1 as for build_package_configs_template. + // + class build_package_config_constraints: + public small_vector<build_constraints, 1> + { + public: + build_package_config_constraints () = default; + + template <typename K> + explicit + build_package_config_constraints ( + const build_package_configs_template<K>& cs) + { + reserve (cs.size ()); + for (const build_package_config_template<K>& c: cs) + push_back (c.constraints); + } + + template <typename K> + void + to_configs (build_package_configs_template<K>& cs) && + { + // Note that the empty trailing entries will be missing (see ODB's + // nested-container.hxx for details). + // + assert (size () <= cs.size ()); + + auto i (cs.begin ()); + for (build_constraints& bcs: *this) + i++->constraints = move (bcs); + } + }; + + // build_package_config_template<K>::auxiliaries + // + using build_auxiliary_key = odb::nested_key<build_auxiliaries>; + using build_auxiliaries_map = std::map<build_auxiliary_key, build_auxiliary>; + + #pragma db value(build_auxiliary_key) + #pragma db member(build_auxiliary_key::outer) column("config_index") + #pragma db member(build_auxiliary_key::inner) column("index") + + // Adapter for build_package_config_template<K>::auxiliaries. + // + // Note: 1 as for build_package_configs_template. + // + class build_package_config_auxiliaries: + public small_vector<build_auxiliaries, 1> + { + public: + build_package_config_auxiliaries () = default; + + template <typename K> + explicit + build_package_config_auxiliaries ( + const build_package_configs_template<K>& cs) + { + reserve (cs.size ()); + for (const build_package_config_template<K>& c: cs) + push_back (c.auxiliaries); + } + + template <typename K> + void + to_configs (build_package_configs_template<K>& cs) && + { + // Note that the empty trailing entries will be missing (see ODB's + // nested-container.hxx for details). + // + assert (size () <= cs.size ()); + + auto i (cs.begin ()); + for (build_auxiliaries& bas: *this) + i++->auxiliaries = move (bas); + } + }; + + // build_package_config_template<K>::bot_keys + // + // Adapter for build_package_config_template<K>::bot_keys. + // + // Note: 1 as for build_package_configs_template. + // + template <typename K> + class build_package_config_bot_keys: public small_vector<vector<K>, 1> + { + public: + build_package_config_bot_keys () = default; + + explicit + build_package_config_bot_keys (const build_package_configs_template<K>& cs) + { + this->reserve (cs.size ()); + for (const build_package_config_template<K>& c: cs) + this->push_back (c.bot_keys); + } + + void + to_configs (build_package_configs_template<K>& cs) && + { + // Note that the empty trailing entries will be missing (see ODB's + // nested-container.hxx for details). + // + assert (this->size () <= cs.size ()); + + auto i (cs.begin ()); + for (vector<K>& bks: *this) + i++->bot_keys = move (bks); + } + }; + + // The primary reason why a package is unbuildable by the build bot + // controller service. + // + enum class unbuildable_reason: std::uint8_t + { + stub, // A stub, otherwise + test, // A separate test (built as part of primary), otherwise + external, // From an external repository, otherwise + unbuildable // From an internal unbuildable repository. + }; + + string + to_string (unbuildable_reason); + + unbuildable_reason + to_unbuildable_reason (const string&); // May throw invalid_argument. + + inline ostream& + operator<< (ostream& os, unbuildable_reason r) {return os << to_string (r);} + + using optional_unbuildable_reason = optional<unbuildable_reason>; + + #pragma db map type(unbuildable_reason) as(string) \ + to(to_string (?)) \ + from(brep::to_unbuildable_reason (?)) + + #pragma db map type(optional_unbuildable_reason) as(brep::optional_string) \ + to((?) ? to_string (*(?)) : brep::optional_string ()) \ + from((?) \ + ? brep::to_unbuildable_reason (*(?)) \ + : brep::optional_unbuildable_reason ()) \ + + // version_constraint + // + using bpkg::version_constraint; + + #pragma db value(version_constraint) definition + + // test_dependency_type + // + using bpkg::test_dependency_type; + using bpkg::to_test_dependency_type; + + #pragma db map type(test_dependency_type) as(string) \ + to(to_string (?)) \ + from(brep::to_test_dependency_type (?)) + + // requirements + // + // Note that this is a 2-level nested container (see package.hxx for + // details). + // + using bpkg::requirement_alternative; + using bpkg::requirement_alternatives; + using requirements = vector<requirement_alternatives>; + + #pragma db value(requirement_alternative) definition + #pragma db value(requirement_alternatives) definition + + using requirement_alternative_key = + odb::nested_key<requirement_alternatives>; + + using requirement_alternatives_map = + std::map<requirement_alternative_key, requirement_alternative>; + + #pragma db value(requirement_alternative_key) + #pragma db member(requirement_alternative_key::outer) column("requirement_index") + #pragma db member(requirement_alternative_key::inner) column("index") + + using requirement_key = odb::nested2_key<requirement_alternatives>; + + using requirement_alternative_requirements_map = + std::map<requirement_key, string>; + + #pragma db value(requirement_key) + #pragma db member(requirement_key::outer) column("requirement_index") + #pragma db member(requirement_key::middle) column("alternative_index") + #pragma db member(requirement_key::inner) column("index") + + // Third-party service state which may optionally be associated with a + // tenant (see also mod/tenant-service.hxx for background). + // + #pragma db value + struct tenant_service + { + string id; + string type; + optional<string> data; + + tenant_service () = default; + + tenant_service (string i, string t, optional<string> d = nullopt) + : id (move (i)), type (move (t)), data (move (d)) {} + }; + // Version comparison operators. // - // They allow comparing objects that have epoch, canonical_upstream, - // canonical_release, and revision data members. The idea is that this - // works for both query members of types version and canonical_version. - // Note, though, that the object revisions should be comparable (both - // optional, numeric, etc), so to compare version to query member or - // canonical_version you may need to explicitly convert the version object - // to canonical_version. + // Compare objects that have epoch, canonical_upstream, canonical_release, + // and revision data members. The idea is that this works for both query + // members of types version and canonical_version. Note, though, that the + // object revisions should be comparable (both optional, numeric, etc), so + // to compare version to query member or canonical_version you may need to + // explicitly convert the version object to canonical_version. // template <typename T1, typename T2> inline auto @@ -482,10 +831,9 @@ namespace brep return compare_version_lt (x.version, y.version, true); } - // They allow comparing objects that have tenant, name, and version data - // members. The idea is that this works for both query members of package id - // types (in particular in join conditions) as well as for values of - // package_id type. + // Compare objects that have tenant, name, and version data members. The + // idea is that this works for both query members of package id types (in + // particular in join conditions) as well as for values of package_id type. // template <typename T1, typename T2> inline auto @@ -511,6 +859,49 @@ namespace brep compare_version_ne (x.version, y.version, true); } + // Allow comparing the query members with the query parameters bound by + // reference to variables of the canonical version type (in particular in + // the prepared queries). + // + // Note that it is not operator==() since the query template parameter type + // can not be deduced from the function parameter types and needs to be + // specified explicitly. + // + template <typename T, typename V> + inline auto + equal (const V& x, const canonical_version& y) + -> decltype (x.epoch == odb::query<T>::_ref (y.epoch)) + { + using query = odb::query<T>; + + return x.epoch == query::_ref (y.epoch) && + x.canonical_upstream == query::_ref (y.canonical_upstream) && + x.canonical_release == query::_ref (y.canonical_release) && + x.revision == query::_ref (y.revision); + } + + // Allow comparing the query members with the query parameters bound by + // reference to variables of the package id type (in particular in the + // prepared queries). + // + // Note that it is not operator==() since the query template parameter type + // can not be deduced from the function parameter types and needs to be + // specified explicitly. + // + template <typename T, typename ID> + inline auto + equal (const ID& x, const package_id& y) + -> decltype (x.tenant == odb::query<T>::_ref (y.tenant) && + x.name == odb::query<T>::_ref (y.name) && + x.version.epoch == odb::query<T>::_ref (y.version.epoch)) + { + using query = odb::query<T>; + + return x.tenant == query::_ref (y.tenant) && + x.name == query::_ref (y.name) && + equal<T> (x.version, y.version); + } + // Repository id comparison operators. // inline bool @@ -522,10 +913,10 @@ namespace brep return x.canonical_name.compare (y.canonical_name) < 0; } - // They allow comparing objects that have tenant and canonical_name data - // members. The idea is that this works for both query members of repository - // id types (in particular in join conditions) as well as for values of - // repository_id type. + // Compare objects that have tenant and canonical_name data members. The + // idea is that this works for both query members of repository id types (in + // particular in join conditions) as well as for values of repository_id + // type. // template <typename T1, typename T2> inline auto @@ -542,6 +933,38 @@ namespace brep { return x.tenant != y.tenant || x.canonical_name != y.canonical_name; } + + // Public key id comparison operators. + // + inline bool + operator< (const public_key_id& x, const public_key_id& y) + { + if (int r = x.tenant.compare (y.tenant)) + return r < 0; + + return x.fingerprint.compare (y.fingerprint) < 0; + } + + // Compare objects that have tenant and fingerprint data members. The idea + // is that this works for both query members of public key id types (in + // particular in join conditions) as well as for values of public_key_id + // type. + // + template <typename T1, typename T2> + inline auto + operator== (const T1& x, const T2& y) + -> decltype (x.tenant == y.tenant && x.fingerprint == y.fingerprint) + { + return x.tenant == y.tenant && x.fingerprint == y.fingerprint; + } + + template <typename T1, typename T2> + inline auto + operator!= (const T1& x, const T2& y) + -> decltype (x.tenant == y.tenant && x.fingerprint == y.fingerprint) + { + return x.tenant != y.tenant || x.fingerprint != y.fingerprint; + } } #endif // LIBBREP_COMMON_HXX diff --git a/libbrep/database-lock.cxx b/libbrep/database-lock.cxx index b295472..1b7f730 100644 --- a/libbrep/database-lock.cxx +++ b/libbrep/database-lock.cxx @@ -1,5 +1,4 @@ // file : libbrep/database-lock.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #include <libbrep/database-lock.hxx> diff --git a/libbrep/database-lock.hxx b/libbrep/database-lock.hxx index 832010f..ab5441d 100644 --- a/libbrep/database-lock.hxx +++ b/libbrep/database-lock.hxx @@ -1,5 +1,4 @@ // file : libbrep/database-lock.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef LIBBREP_DATABASE_LOCK_HXX diff --git a/libbrep/odb.sh b/libbrep/odb.sh index 4172e67..608ca41 100755 --- a/libbrep/odb.sh +++ b/libbrep/odb.sh @@ -43,6 +43,8 @@ else fi +rm -f {package,build}-???-{pre,post}.sql + $odb "${inc[@]}" -d pgsql --std c++14 --generate-query \ --odb-epilogue '#include <libbutl/small-vector-odb.hxx>' \ --odb-epilogue '#include <libbrep/wrapper-traits.hxx>' \ @@ -51,7 +53,7 @@ $odb "${inc[@]}" -d pgsql --std c++14 --generate-query \ --hxx-prologue '#include <libbrep/common-traits.hxx>' \ -DLIBODB_BUILD2 -DLIBODB_PGSQL_BUILD2 \ --include-with-brackets --include-prefix libbrep \ - --guard-prefix LIBBREP \ + --guard-prefix LIBBREP \ common.hxx $odb "${inc[@]}" -d pgsql --std c++14 --generate-query --generate-schema \ @@ -72,7 +74,7 @@ $odb "${inc[@]}" -d pgsql --std c++14 --generate-query --generate-schema \ --odb-epilogue '#include <libbrep/wrapper-traits.hxx>' \ --generate-prepared -DLIBODB_BUILD2 -DLIBODB_PGSQL_BUILD2 \ --include-with-brackets --include-prefix libbrep \ - --guard-prefix LIBBREP \ + --guard-prefix LIBBREP \ build.hxx $odb "${inc[@]}" -d pgsql --std c++14 --generate-query \ diff --git a/libbrep/package-extra.sql b/libbrep/package-extra.sql index fe936ff..5c04147 100644 --- a/libbrep/package-extra.sql +++ b/libbrep/package-extra.sql @@ -38,16 +38,17 @@ DROP TYPE IF EXISTS weighted_text CASCADE; CREATE TYPE weighted_text AS (a TEXT, b TEXT, c TEXT, d TEXT); -- Return the latest versions of matching a tenant internal packages as a set --- of package rows. If tenant is NULL, then match all tenants. +-- of package rows. If tenant is NULL, then match all public tenants. -- CREATE FUNCTION latest_packages(IN tenant TEXT) RETURNS SETOF package AS $$ SELECT p1.* - FROM package p1 LEFT JOIN package p2 ON ( + FROM package p1 + LEFT JOIN package p2 ON ( p1.internal_repository_canonical_name IS NOT NULL AND - p1.tenant = p2.tenant AND - p1.name = p2.name AND + p1.tenant = p2.tenant AND + p1.name = p2.name AND p2.internal_repository_canonical_name IS NOT NULL AND (p1.version_epoch < p2.version_epoch OR p1.version_epoch = p2.version_epoch AND @@ -56,8 +57,12 @@ RETURNS SETOF package AS $$ (p1.version_canonical_release < p2.version_canonical_release OR p1.version_canonical_release = p2.version_canonical_release AND p1.version_revision < p2.version_revision)))) + JOIN tenant t ON (p1.tenant = t.id) WHERE - (latest_packages.tenant IS NULL OR p1.tenant = latest_packages.tenant) AND + CASE + WHEN latest_packages.tenant IS NULL THEN NOT t.private + ELSE p1.tenant = latest_packages.tenant + END AND p1.internal_repository_canonical_name IS NOT NULL AND p2.name IS NULL; $$ LANGUAGE SQL STABLE; @@ -83,7 +88,8 @@ $$ LANGUAGE SQL STABLE; -- Search for the latest version of an internal packages matching the -- specified search query and tenant. Return a set of rows containing the -- package id and search rank. If query is NULL, then match all packages and --- return 0 rank for all rows. If tenant is NULL, then match all tenants. +-- return 0 rank for all rows. If tenant is NULL, then match all public +-- tenants. -- CREATE FUNCTION search_latest_packages(IN query tsquery, @@ -107,9 +113,9 @@ RETURNS SETOF record AS $$ $$ LANGUAGE SQL STABLE; -- Search for packages matching the search query and tenant and having the --- specified name. Return a set of rows containing the package id and search +-- specified name. Return a set of rows containing the package id and search -- rank. If query is NULL, then match all packages and return 0 rank for all --- rows. If tenant is NULL, then match all tenants. +-- rows. If tenant is NULL, then match all public tenants. -- CREATE FUNCTION search_packages(IN query tsquery, @@ -121,19 +127,22 @@ search_packages(IN query tsquery, OUT version_revision INTEGER, OUT rank real) RETURNS SETOF record AS $$ - SELECT tenant, name, version_epoch, version_canonical_upstream, - version_canonical_release, version_revision, + SELECT p.tenant, p.name, p.version_epoch, p.version_canonical_upstream, + p.version_canonical_release, p.version_revision, CASE WHEN query IS NULL THEN 0 -- Weight mapping: D C B A ELSE ts_rank_cd('{0.05, 0.2, 0.9, 1.0}', search_index, query) END AS rank - FROM package + FROM package p JOIN tenant t ON (p.tenant = t.id) WHERE - (search_packages.tenant IS NULL OR tenant = search_packages.tenant) AND - name = search_packages.name AND - internal_repository_canonical_name IS NOT NULL AND - (query IS NULL OR search_index @@ query); + CASE + WHEN search_packages.tenant IS NULL THEN NOT t.private + ELSE p.tenant = search_packages.tenant + END AND + name = search_packages.name AND + internal_repository_canonical_name IS NOT NULL AND + (query IS NULL OR search_index @@ query); $$ LANGUAGE SQL STABLE; -- Parse weighted_text to tsvector. diff --git a/libbrep/package-traits.cxx b/libbrep/package-traits.cxx index 1b90483..d6d3525 100644 --- a/libbrep/package-traits.cxx +++ b/libbrep/package-traits.cxx @@ -1,5 +1,4 @@ // file : libbrep/package-traits.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #include <libbrep/package-traits.hxx> diff --git a/libbrep/package-traits.hxx b/libbrep/package-traits.hxx index f30459a..f3efa20 100644 --- a/libbrep/package-traits.hxx +++ b/libbrep/package-traits.hxx @@ -1,5 +1,4 @@ // file : libbrep/package-traits.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef LIBBREP_PACKAGE_TRAITS diff --git a/libbrep/package.cxx b/libbrep/package.cxx index e6c543d..4eb6fe8 100644 --- a/libbrep/package.cxx +++ b/libbrep/package.cxx @@ -1,5 +1,4 @@ // file : libbrep/package.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #include <libbrep/package.hxx> @@ -41,9 +40,15 @@ namespace brep // tenant // tenant:: - tenant (string i) + tenant (string i, + bool p, + optional<string> r, + optional<tenant_service> s) : id (move (i)), - creation_timestamp (timestamp::clock::now ()) + private_ (p), + interactive (move (r)), + creation_timestamp (timestamp::clock::now ()), + service (move (s)) { } @@ -59,13 +64,13 @@ namespace brep license_alternatives_type la, small_vector<string, 5> tp, small_vector<string, 5> kw, - optional<string> ds, - optional<text_type> dt, - string ch, - optional<url_type> ur, - optional<url_type> du, - optional<url_type> su, - optional<url_type> pu, + optional<typed_text> ds, + optional<typed_text> pds, + optional<typed_text> ch, + optional<manifest_url> ur, + optional<manifest_url> du, + optional<manifest_url> su, + optional<manifest_url> pu, optional<email_type> em, optional<email_type> pe, optional<email_type> be, @@ -73,11 +78,12 @@ namespace brep optional<email_type> bee, dependencies_type dp, requirements_type rq, - small_vector<dependency, 1> ts, - small_vector<dependency, 1> es, - small_vector<dependency, 1> bms, + small_vector<test_dependency, 1> ts, build_class_exprs bs, build_constraints_type bc, + build_auxiliaries_type ac, + package_build_bot_keys bk, + package_build_configs bcs, optional<path> lc, optional<string> fr, optional<string> sh, @@ -94,7 +100,7 @@ namespace brep topics (move (tp)), keywords (move (kw)), description (move (ds)), - description_type (move (dt)), + package_description (move (pds)), changes (move (ch)), url (move (ur)), doc_url (move (du)), @@ -108,29 +114,82 @@ namespace brep dependencies (move (dp)), requirements (move (rq)), tests (move (ts)), - examples (move (es)), - benchmarks (move (bms)), builds (move (bs)), - build_constraints (!stub () ? move (bc) : build_constraints_type ()), + build_constraints (move (bc)), + build_auxiliaries (move (ac)), + build_bot_keys (move (bk)), + build_configs (move (bcs)), internal_repository (move (rp)), location (move (lc)), fragment (move (fr)), - sha256sum (move (sh)), - buildable (!stub () && internal_repository->buildable) + sha256sum (move (sh)) { + // The default configuration is always added by the package manifest + // parser (see libbpkg/manifest.cxx for details). + // + assert (find ("default", build_configs) != nullptr); + + if (stub ()) + unbuildable_reason = brep::unbuildable_reason::stub; + else if (!internal_repository->buildable) + unbuildable_reason = brep::unbuildable_reason::unbuildable; + + buildable = !unbuildable_reason; + + // If the package is buildable deduce the custom_bot flag. + // + if (buildable) + { + for (const package_build_config& bc: build_configs) + { + bool custom (!bc.effective_bot_keys (build_bot_keys).empty ()); + + if (!custom_bot) + { + custom_bot = custom; + } + // + // If both the custom and default bots are used by the package, then + // reset the custom_bot flag to nullopt and bail out from the build + // package configurations loop. + // + else if (*custom_bot != custom) + { + custom_bot = nullopt; + break; + } + } + } + assert (internal_repository->internal); } package:: package (package_name nm, version_type vr, + build_class_exprs bs, + build_constraints_type bc, + build_auxiliaries_type ac, + package_build_configs bcs, shared_ptr<repository_type> rp) : id (rp->tenant, move (nm), vr), tenant (id.tenant), name (id.name), version (move (vr)), - buildable (false) + builds (move (bs)), + build_constraints (move (bc)), + build_auxiliaries (move (ac)), + build_configs (move (bcs)), + buildable (false), + unbuildable_reason (stub () + ? brep::unbuildable_reason::stub + : brep::unbuildable_reason::external) { + // The default configuration is always added by the package manifest + // parser (see libbpkg/manifest.cxx for details). + // + assert (find ("default", build_configs) != nullptr); + assert (!rp->internal); other_repositories.emplace_back (move (rp)); } @@ -151,11 +210,11 @@ namespace brep // Probably drop-box would be better as also tells what are // the available internal repositories. // - string k (project.string () + " " + name.string () + " " + - version.string () + " " + version.string (true)); + string k (project.string () + ' ' + name.string () + ' ' + + version.string () + ' ' + version.string (true)); if (upstream_version) - k += " " + *upstream_version; + k += ' ' + *upstream_version; // Add licenses to search keywords. // @@ -163,13 +222,13 @@ namespace brep { for (const auto& l: la) { - k += " " + l; + k += ' ' + l; // If license is say LGPLv2 then LGPL is also a search keyword. // size_t n (l.size ()); if (n > 2 && l[n - 2] == 'v' && l[n - 1] >= '0' && l[n - 1] <= '9') - k += " " + string (l, 0, n - 2); + k += ' ' + string (l, 0, n - 2); } } @@ -180,14 +239,24 @@ namespace brep // Add topics to the second-strongest search keywords. // for (const auto& t: topics) - k2 += " " + t; + k2 += ' ' + t; // Add keywords to the second-strongest search keywords. // for (const auto& k: keywords) - k2 += " " + k; + k2 += ' ' + k; + + string d (description ? description->text : ""); + + if (package_description) + { + if (description) + d += ' '; + + d += package_description->text; + } - return {move (k), move (k2), description ? *description : "", changes}; + return {move (k), move (k2), move (d), changes ? changes->text : ""}; } // repository diff --git a/libbrep/package.hxx b/libbrep/package.hxx index 47f0ebe..45008d4 100644 --- a/libbrep/package.hxx +++ b/libbrep/package.hxx @@ -1,5 +1,4 @@ // file : libbrep/package.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef LIBBREP_PACKAGE_HXX @@ -19,9 +18,9 @@ // Used by the data migration entries. // -#define LIBBREP_PACKAGE_SCHEMA_VERSION_BASE 17 +#define LIBBREP_PACKAGE_SCHEMA_VERSION_BASE 27 -#pragma db model version(LIBBREP_PACKAGE_SCHEMA_VERSION_BASE, 17, closed) +#pragma db model version(LIBBREP_PACKAGE_SCHEMA_VERSION_BASE, 33, closed) namespace brep { @@ -50,9 +49,12 @@ namespace brep using bpkg::text_type; using bpkg::to_text_type; + // Note that here we assume that the saved string representation of a type + // is always recognized later. + // #pragma db map type(text_type) as(string) \ to(to_string (?)) \ - from(brep::to_text_type (?)) + from(*brep::to_text_type (?)) using optional_text_type = optional<text_type>; @@ -60,36 +62,25 @@ namespace brep to((?) ? to_string (*(?)) : brep::optional_string ()) \ from((?) ? brep::to_text_type (*(?)) : brep::optional_text_type ()) - // url + // manifest_url // - using bpkg::url; + using bpkg::manifest_url; - #pragma db value(url) definition - #pragma db member(url::value) virtual(string) before \ - get(this.string ()) \ - set(this = brep::url ((?), "" /* comment */)) \ + #pragma db value(manifest_url) definition + #pragma db member(manifest_url::value) virtual(string) before \ + get(this.string ()) \ + set(this = brep::manifest_url ((?), "" /* comment */)) \ column("") - // email - // - using bpkg::email; - - #pragma db value(email) definition - #pragma db member(email::value) virtual(string) before access(this) column("") - // licenses // using bpkg::licenses; - using license_alternatives = vector<licenses>; + using license_alternatives = small_vector<licenses, 1>; #pragma db value(licenses) definition // dependencies // - using bpkg::version_constraint; - - #pragma db value(version_constraint) definition - // Notes: // // 1. Will the package be always resolvable? What if it is in @@ -141,8 +132,8 @@ namespace brep package_name name; optional<version_constraint> constraint; - // Resolved dependency package. NULL if the repository load was shallow - // and so the package dependencies are not resolved. + // Resolved dependency package. Can be NULL if the repository load was + // shallow and the package dependency could not be resolved. // lazy_shared_ptr<package_type> package; @@ -161,26 +152,74 @@ namespace brep operator!= (const dependency&, const dependency&); #pragma db value - class dependency_alternatives: public vector<dependency> + class dependency_alternative: public small_vector<dependency, 1> + { + public: + // While we currently don't use the reflect, prefer, accept, and require + // values, let's save them for completeness. + // + optional<string> enable; + optional<string> reflect; + optional<string> prefer; + optional<string> accept; + optional<string> require; + + dependency_alternative () = default; + dependency_alternative (optional<string> e, + optional<string> r, + optional<string> p, + optional<string> a, + optional<string> q) + : enable (move (e)), + reflect (move (r)), + prefer (move (p)), + accept (move (a)), + require (move (q)) {} + }; + + #pragma db value + class dependency_alternatives: public small_vector<dependency_alternative, 1> { public: - bool conditional; bool buildtime; string comment; dependency_alternatives () = default; - dependency_alternatives (bool d, bool b, string c) - : conditional (d), buildtime (b), comment (move (c)) {} + dependency_alternatives (bool b, string c) + : buildtime (b), comment (move (c)) {} }; using dependencies = vector<dependency_alternatives>; - // requirements + // tests // - using bpkg::requirement_alternatives; - using requirements = vector<requirement_alternatives>; + #pragma db value + struct test_dependency: dependency + { + test_dependency_type type; + bool buildtime; + optional<string> enable; + optional<string> reflect; + + test_dependency () = default; + test_dependency (package_name n, + test_dependency_type t, + bool b, + optional<version_constraint> c, + optional<string> e, + optional<string> r) + : dependency {move (n), move (c), nullptr /* package */}, + type (t), + buildtime (b), + enable (move (e)), + reflect (move (r)) + { + } - #pragma db value(requirement_alternatives) definition + // Database mapping. + // + #pragma db member(buildtime) + }; // certificate // @@ -202,17 +241,82 @@ namespace brep // Create the tenant object with the timestamp set to now and the archived // flag set to false. // - explicit - tenant (string id); + tenant (string id, + bool private_, + optional<string> interactive, + optional<tenant_service>); string id; + // If this flag is true, then display the packages in the web interface + // only in the tenant view mode. + // + bool private_; // Note: foreign-mapped in build. + + // Interactive package build breakpoint. + // + // If present, then packages from this tenant will only be built + // interactively and only non-interactively otherwise. + // + optional<string> interactive; // Note: foreign-mapped in build. + timestamp creation_timestamp; - bool archived = false; // Note: foreign-mapped in build. + bool archived = false; // Note: foreign-mapped in build. + + optional<tenant_service> service; // Note: foreign-mapped in build. + + // Note that due to the implementation complexity and performance + // considerations, the service notifications are not synchronized. This + // leads to a potential race, so that before we have sent the `queued` + // notification for a package build, some other thread (potentially in a + // different process) could have already sent the `building` notification + // for it. It feels like there is no easy way to reliably fix that. + // Instead, we just decrease the probability of such a notifications + // sequence failure by delaying builds of the freshly queued packages for + // some time. Specifically, whenever the `queued` notification is ought + // to be sent (normally out of the database transaction, since it likely + // sends an HTTP request, etc) the tenant's queued_timestamp member is set + // to the current time. During the configured time interval since that + // time point the build tasks may not be issued for the tenant's packages. + // + // Also note that while there are similar potential races for other + // notification sequences, their probability is rather low due to the + // natural reasons (non-zero build task execution time, etc) and thus we + // just ignore them. + // + optional<timestamp> queued_timestamp; // Note: foreign-mapped in build. + + // Note that after the package tenant is created but before the first + // build object is created, there is no easy way to produce a list of + // unbuilt package configurations. That would require to know the build + // toolchain(s), which are normally extracted from the build objects. + // Thus, the empty unbuilt package configurations list is ambiguous and + // can either mean that no more package configurations can be built or + // that we have not enough information to produce the list. To + // disambiguate the empty list in the interface, in the latter case we + // want to display the question mark instead of 0 as an unbuilt package + // configurations count. To achieve this we will stash the build toolchain + // in the tenant when a package from this tenant is considered for a build + // for the first time but no configuration is picked for the build (the + // target configurations are excluded, an auxiliary machine is not + // available, etc). We will also use the stashed toolchain as a fallback + // until we are able to retrieve the toolchain(s) from the tenant builds + // to produce the unbuilt package configurations list. + // + // Note: foreign-mapped in build. + // + optional<brep::build_toolchain> build_toolchain; // Database mapping. // #pragma db member(id) id + #pragma db member(private_) + + #pragma db index("tenant_service_i") \ + unique \ + members(service.id, service.type) + + #pragma db index member(service.id) private: friend class odb::access; @@ -343,6 +447,67 @@ namespace brep string d; }; + #pragma db value + struct typed_text + { + string text; + text_type type; + + #pragma db member(text) column("") + }; + + // Tweak public_key_id mapping to include a constraint (this only affects the + // database schema). + // + #pragma db member(public_key_id::tenant) points_to(tenant) + + #pragma db object pointer(shared_ptr) session + class public_key: public string + { + public: + public_key (string tenant, string fingerprint, string key) + : string (move (key)), id (move (tenant), move (fingerprint)) {} + + public_key_id id; + + // Database mapping. + // + #pragma db member(id) id column("") + + #pragma db member(data) virtual(string) access(this) + + private: + friend class odb::access; + public_key () = default; + }; + + // package_build_config + // + using package_build_config = + build_package_config_template<lazy_shared_ptr<public_key>>; + + using package_build_configs = + build_package_configs_template<lazy_shared_ptr<public_key>>; + + #pragma db value(package_build_config) definition + + #pragma db member(package_build_config::builds) transient + #pragma db member(package_build_config::constraints) transient + #pragma db member(package_build_config::auxiliaries) transient + #pragma db member(package_build_config::bot_keys) transient + + // package_build_bot_keys + // + using package_build_bot_keys = vector<lazy_shared_ptr<public_key>>; + using package_build_bot_key_key = odb::nested_key<package_build_bot_keys>; + + using package_build_bot_keys_map = std::map<package_build_bot_key_key, + lazy_shared_ptr<public_key>>; + + #pragma db value(package_build_bot_key_key) + #pragma db member(package_build_bot_key_key::outer) column("config_index") + #pragma db member(package_build_bot_key_key::inner) column("index") + // Tweak package_id mapping to include a constraint (this only affects the // database schema). // @@ -357,14 +522,15 @@ namespace brep using upstream_version_type = brep::upstream_version; using priority_type = brep::priority; using license_alternatives_type = brep::license_alternatives; - using url_type = brep::url; using email_type = brep::email; using dependencies_type = brep::dependencies; using requirements_type = brep::requirements; using build_constraints_type = brep::build_constraints; + using build_auxiliaries_type = brep::build_auxiliaries; - // Create internal package object. Note that for stubs the build - // constraints are meaningless, and so not saved. + // Create internal package object. + // + // Note: the default build package config is expected to always be present. // package (package_name, version_type, @@ -375,13 +541,13 @@ namespace brep license_alternatives_type, small_vector<string, 5> topics, small_vector<string, 5> keywords, - optional<string> description, - optional<text_type> description_type, - string changes, - optional<url_type>, - optional<url_type> doc_url, - optional<url_type> src_url, - optional<url_type> package_url, + optional<typed_text> description, + optional<typed_text> package_description, + optional<typed_text> changes, + optional<manifest_url> url, + optional<manifest_url> doc_url, + optional<manifest_url> src_url, + optional<manifest_url> package_url, optional<email_type>, optional<email_type> package_email, optional<email_type> build_email, @@ -389,11 +555,12 @@ namespace brep optional<email_type> build_error_email, dependencies_type, requirements_type, - small_vector<dependency, 1> tests, - small_vector<dependency, 1> examples, - small_vector<dependency, 1> benchmarks, + small_vector<test_dependency, 1> tests, build_class_exprs, build_constraints_type, + build_auxiliaries_type, + package_build_bot_keys, + package_build_configs, optional<path> location, optional<string> fragment, optional<string> sha256sum, @@ -401,12 +568,28 @@ namespace brep // Create external package object. // - // External repository packages can appear on the WEB interface only in - // dependency list in the form of a link to the corresponding WEB page. - // The only package information required to compose such a link is the - // package name, version, and repository location. + // External package can appear on the WEB interface only in dependency + // list in the form of a link to the corresponding WEB page. The only + // package information required to compose such a link is the package name, + // version, and repository location. + // + // External package can also be a separate test for some primary package + // (and belong to a complement but yet external repository), and so we may + // need its build class expressions, constraints, and configurations to + // decide if to build it together with the primary package or not (see + // test-exclude task manifest value for details). Additionally, when the + // test package is being built the auxiliary machines may also be + // required. // - package (package_name name, version_type, shared_ptr<repository_type>); + // Note: the default build package config is expected to always be present. + // + package (package_name name, + version_type, + build_class_exprs, + build_constraints_type, + build_auxiliaries_type, + package_build_configs, + shared_ptr<repository_type>); bool internal () const noexcept {return internal_repository != nullptr;} @@ -431,33 +614,53 @@ namespace brep // Matches the package name if the project name is not specified in // the manifest. // - package_name project; + package_name project; // Note: foreign-mapped in build. priority_type priority; string summary; license_alternatives_type license_alternatives; small_vector<string, 5> topics; small_vector<string, 5> keywords; - optional<string> description; // Absent if type is unknown. - optional<text_type> description_type; // Present if description is present. - string changes; - optional<url_type> url; - optional<url_type> doc_url; - optional<url_type> src_url; - optional<url_type> package_url; + + // Note that the descriptions and changes are absent if the respective + // type is unknown. + // + optional<typed_text> description; + optional<typed_text> package_description; + optional<typed_text> changes; + + optional<manifest_url> url; + optional<manifest_url> doc_url; + optional<manifest_url> src_url; + optional<manifest_url> package_url; optional<email_type> email; optional<email_type> package_email; - optional<email_type> build_email; - optional<email_type> build_warning_email; - optional<email_type> build_error_email; + optional<email_type> build_email; // Note: foreign-mapped in build. + optional<email_type> build_warning_email; // Note: foreign-mapped in build. + optional<email_type> build_error_email; // Note: foreign-mapped in build. dependencies_type dependencies; - requirements_type requirements; - small_vector<dependency, 1> tests; - small_vector<dependency, 1> examples; - small_vector<dependency, 1> benchmarks; + requirements_type requirements; // Note: foreign-mapped in build. + small_vector<test_dependency, 1> tests; // Note: foreign-mapped in build. + // Common build classes, constraints, auxiliaries, and bot keys that apply + // to all configurations unless overridden. + // build_class_exprs builds; // Note: foreign-mapped in build. build_constraints_type build_constraints; // Note: foreign-mapped in build. + build_auxiliaries_type build_auxiliaries; // Note: foreign-mapped in build. + package_build_bot_keys build_bot_keys; // Note: foreign-mapped in build. + package_build_configs build_configs; // Note: foreign-mapped in build. + + // Group the build_configs, builds, and build_constraints members of this + // object together with their respective nested configs entries into the + // separate section for an explicit load. + // + // Note that while the build auxiliaries and bot keys are persisted via + // the newly created package objects, they are only used via the + // foreign-mapped build_package objects (see build-package.hxx for + // details). Thus, we add them to the never-loaded unused_section (see + // below). + // odb::section build_section; // Note that it is foreign-mapped in build. @@ -479,16 +682,26 @@ namespace brep vector<lazy_shared_ptr<repository_type>> other_repositories; - // Whether the package is buildable by the build bot controller service. - // Can only be true for non-stubs that belong to at least one buildable - // (internal) repository. + // Whether the package is buildable by the build bot controller service + // and the reason if it's not. // // While we could potentially calculate this flag on the fly, that would // complicate the database queries significantly. // - // Note: foreign-mapped in build. + bool buildable; // Note: foreign-mapped in build. + optional<brep::unbuildable_reason> unbuildable_reason; + + // If this flag is true, then all the package configurations are buildable + // with the custom build bots. If false, then all configurations are + // buildable with the default bots. If nullopt, then some configurations + // are buildable with the custom and some with the default build bots. // - bool buildable; + // Note: meaningless if buildable is false. + // + optional<bool> custom_bot; // Note: foreign-mapped in build. + + private: + odb::section unused_section; // Database mapping. // @@ -524,48 +737,80 @@ namespace brep // dependencies // - using _dependency_key = odb::nested_key<dependency_alternatives>; + // Note that this is a 2-level nested container which is mapped to three + // container tables each containing data of each dimension. + + // Container of the dependency_alternatives values. + // + #pragma db member(dependencies) id_column("") value_column("") + + // Container of the dependency_alternative values. + // + using _dependency_alternative_key = + odb::nested_key<dependency_alternatives>; + using _dependency_alternatives_type = - std::map<_dependency_key, dependency>; + std::map<_dependency_alternative_key, dependency_alternative>; - #pragma db value(_dependency_key) - #pragma db member(_dependency_key::outer) column("dependency_index") - #pragma db member(_dependency_key::inner) column("index") + #pragma db value(_dependency_alternative_key) + #pragma db member(_dependency_alternative_key::outer) column("dependency_index") + #pragma db member(_dependency_alternative_key::inner) column("index") - #pragma db member(dependencies) id_column("") value_column("") #pragma db member(dependency_alternatives) \ virtual(_dependency_alternatives_type) \ after(dependencies) \ get(odb::nested_get (this.dependencies)) \ set(odb::nested_set (this.dependencies, std::move (?))) \ + id_column("") key_column("") value_column("") + + // Container of the dependency values. + // + using _dependency_key = odb::nested2_key<dependency_alternatives>; + using _dependency_alternative_dependencies_type = + std::map<_dependency_key, dependency>; + + #pragma db value(_dependency_key) + #pragma db member(_dependency_key::outer) column("dependency_index") + #pragma db member(_dependency_key::middle) column("alternative_index") + #pragma db member(_dependency_key::inner) column("index") + + #pragma db member(dependency_alternative_dependencies) \ + virtual(_dependency_alternative_dependencies_type) \ + after(dependency_alternatives) \ + get(odb::nested2_get (this.dependencies)) \ + set(odb::nested2_set (this.dependencies, std::move (?))) \ id_column("") key_column("") value_column("dep_") // requirements // - using _requirement_key = odb::nested_key<requirement_alternatives>; - using _requirement_alternatives_type = - std::map<_requirement_key, string>; - - #pragma db value(_requirement_key) - #pragma db member(_requirement_key::outer) column("requirement_index") - #pragma db member(_requirement_key::inner) column("index") + // Note that this is a 2-level nested container which is mapped to three + // container tables each containing data of each dimension. + // Container of the requirement_alternatives values. + // #pragma db member(requirements) id_column("") value_column("") + + // Container of the requirement_alternative values. + // #pragma db member(requirement_alternatives) \ - virtual(_requirement_alternatives_type) \ + virtual(requirement_alternatives_map) \ after(requirements) \ get(odb::nested_get (this.requirements)) \ set(odb::nested_set (this.requirements, std::move (?))) \ - id_column("") key_column("") value_column("id") + id_column("") key_column("") value_column("") - // tests, examples, benchmarks + // Container of the requirement (string) values. // - // Seeing that these reuse the dependency types, we are also going to - // have identical database mapping. + #pragma db member(requirement_alternative_requirements) \ + virtual(requirement_alternative_requirements_map) \ + after(requirement_alternatives) \ + get(odb::nested2_get (this.requirements)) \ + set(odb::nested2_set (this.requirements, std::move (?))) \ + id_column("") key_column("") value_column("id") + + // tests // - #pragma db member(tests) id_column("") value_column("dep_") - #pragma db member(examples) id_column("") value_column("dep_") - #pragma db member(benchmarks) id_column("") value_column("dep_") + #pragma db member(tests) id_column("") value_column("test_") // builds // @@ -577,7 +822,74 @@ namespace brep #pragma db member(build_constraints) id_column("") value_column("") \ section(build_section) - #pragma db member(build_section) load(lazy) update(always) + // build_auxiliaries + // + #pragma db member(build_auxiliaries) id_column("") value_column("") \ + section(unused_section) + + // build_bot_keys + // + #pragma db member(build_bot_keys) \ + id_column("") value_column("key_") value_not_null \ + section(unused_section) + + // build_configs + // + // Note that package_build_config::{builds,constraints,auxiliaries, + // bot_keys} are persisted/loaded via the separate nested containers (see + // commons.hxx for details). + // + #pragma db member(build_configs) id_column("") value_column("config_") \ + section(build_section) + + #pragma db member(build_config_builds) \ + virtual(build_class_exprs_map) \ + after(build_configs) \ + get(odb::nested_get ( \ + brep::build_package_config_builds (this.build_configs))) \ + set(brep::build_package_config_builds bs; \ + odb::nested_set (bs, std::move (?)); \ + move (bs).to_configs (this.build_configs)) \ + id_column("") key_column("") value_column("") \ + section(build_section) + + #pragma db member(build_config_constraints) \ + virtual(build_constraints_map) \ + after(build_config_builds) \ + get(odb::nested_get ( \ + brep::build_package_config_constraints (this.build_configs))) \ + set(brep::build_package_config_constraints cs; \ + odb::nested_set (cs, std::move (?)); \ + move (cs).to_configs (this.build_configs)) \ + id_column("") key_column("") value_column("") \ + section(build_section) + + #pragma db member(build_config_auxiliaries) \ + virtual(build_auxiliaries_map) \ + after(build_config_constraints) \ + get(odb::nested_get ( \ + brep::build_package_config_auxiliaries (this.build_configs))) \ + set(brep::build_package_config_auxiliaries as; \ + odb::nested_set (as, std::move (?)); \ + move (as).to_configs (this.build_configs)) \ + id_column("") key_column("") value_column("") \ + section(unused_section) + + #pragma db member(build_config_bot_keys) \ + virtual(package_build_bot_keys_map) \ + after(build_config_auxiliaries) \ + get(odb::nested_get ( \ + brep::build_package_config_bot_keys< \ + lazy_shared_ptr<brep::public_key>> (this.build_configs))) \ + set(brep::build_package_config_bot_keys< \ + lazy_shared_ptr<brep::public_key>> bks; \ + odb::nested_set (bks, std::move (?)); \ + move (bks).to_configs (this.build_configs)) \ + id_column("") key_column("") value_column("key_") value_not_null \ + section(unused_section) + + #pragma db member(build_section) load(lazy) update(always) + #pragma db member(unused_section) load(lazy) update(manual) // other_repositories // @@ -595,9 +907,9 @@ namespace brep friend class odb::access; package (): tenant (id.tenant), name (id.name) {} - // Save keywords, summary, description, and changes to weighted_text - // a, b, c, d members, respectively. So a word found in keywords will - // have a higher weight than if it's found in the summary. + // Save keywords, summary, descriptions, and changes to weighted_text a, + // b, c, d members, respectively. So a word found in keywords will have a + // higher weight than if it's found in the summary. // weighted_text search_text () const; diff --git a/libbrep/package.xml b/libbrep/package.xml index 785ae0f..96e93a7 100644 --- a/libbrep/package.xml +++ b/libbrep/package.xml @@ -1,7 +1,280 @@ <changelog xmlns="http://www.codesynthesis.com/xmlns/odb/changelog" database="pgsql" schema-name="package" version="1"> - <model version="17"> + <changeset version="33"> + <add-table name="public_key" kind="object"> + <column name="tenant" type="TEXT" null="false"/> + <column name="fingerprint" type="TEXT" null="false"/> + <column name="data" type="TEXT" null="false"/> + <primary-key> + <column name="tenant"/> + <column name="fingerprint"/> + </primary-key> + <foreign-key name="tenant_fk" deferrable="DEFERRED"> + <column name="tenant"/> + <references table="tenant"> + <column name="id"/> + </references> + </foreign-key> + </add-table> + <alter-table name="package"> + <add-column name="custom_bot" type="BOOLEAN" null="true"/> + </alter-table> + <add-table name="package_build_bot_keys" kind="container"> + <column name="tenant" type="TEXT" null="false"/> + <column name="name" type="CITEXT" null="false"/> + <column name="version_epoch" type="INTEGER" null="false"/> + <column name="version_canonical_upstream" type="TEXT" null="false"/> + <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> + <column name="version_revision" type="INTEGER" null="false"/> + <column name="index" type="BIGINT" null="false"/> + <column name="key_tenant" type="TEXT" null="false"/> + <column name="key_fingerprint" type="TEXT" null="false"/> + <foreign-key name="tenant_fk" deferrable="DEFERRED"> + <column name="tenant"/> + <references table="tenant"> + <column name="id"/> + </references> + </foreign-key> + <foreign-key name="object_id_fk" on-delete="CASCADE"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + <references table="package"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + </references> + </foreign-key> + <index name="package_build_bot_keys_object_id_i"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + </index> + <index name="package_build_bot_keys_index_i"> + <column name="index"/> + </index> + <foreign-key name="key_tenant_fk" deferrable="DEFERRED"> + <column name="key_tenant"/> + <references table="tenant"> + <column name="id"/> + </references> + </foreign-key> + <foreign-key name="key_fk" deferrable="DEFERRED"> + <column name="key_tenant"/> + <column name="key_fingerprint"/> + <references table="public_key"> + <column name="tenant"/> + <column name="fingerprint"/> + </references> + </foreign-key> + </add-table> + <add-table name="package_build_config_bot_keys" kind="container"> + <column name="tenant" type="TEXT" null="false"/> + <column name="name" type="CITEXT" null="false"/> + <column name="version_epoch" type="INTEGER" null="false"/> + <column name="version_canonical_upstream" type="TEXT" null="false"/> + <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> + <column name="version_revision" type="INTEGER" null="false"/> + <column name="config_index" type="BIGINT" null="false"/> + <column name="index" type="BIGINT" null="false"/> + <column name="key_tenant" type="TEXT" null="false"/> + <column name="key_fingerprint" type="TEXT" null="false"/> + <foreign-key name="tenant_fk" deferrable="DEFERRED"> + <column name="tenant"/> + <references table="tenant"> + <column name="id"/> + </references> + </foreign-key> + <foreign-key name="object_id_fk" on-delete="CASCADE"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + <references table="package"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + </references> + </foreign-key> + <index name="package_build_config_bot_keys_object_id_i"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + </index> + <foreign-key name="key_tenant_fk" deferrable="DEFERRED"> + <column name="key_tenant"/> + <references table="tenant"> + <column name="id"/> + </references> + </foreign-key> + <foreign-key name="key_fk" deferrable="DEFERRED"> + <column name="key_tenant"/> + <column name="key_fingerprint"/> + <references table="public_key"> + <column name="tenant"/> + <column name="fingerprint"/> + </references> + </foreign-key> + </add-table> + </changeset> + + <changeset version="32"> + <alter-table name="tenant"> + <add-column name="build_toolchain_name" type="TEXT" null="true"/> + <add-column name="build_toolchain_version_epoch" type="INTEGER" null="true"/> + <add-column name="build_toolchain_version_canonical_upstream" type="TEXT" null="true"/> + <add-column name="build_toolchain_version_canonical_release" type="TEXT" null="true"/> + <add-column name="build_toolchain_version_revision" type="INTEGER" null="true"/> + <add-column name="build_toolchain_version_upstream" type="TEXT" null="true"/> + <add-column name="build_toolchain_version_release" type="TEXT" null="true"/> + </alter-table> + </changeset> + + <changeset version="31"> + <add-table name="package_build_auxiliaries" kind="container"> + <column name="tenant" type="TEXT" null="false"/> + <column name="name" type="CITEXT" null="false"/> + <column name="version_epoch" type="INTEGER" null="false"/> + <column name="version_canonical_upstream" type="TEXT" null="false"/> + <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> + <column name="version_revision" type="INTEGER" null="false"/> + <column name="index" type="BIGINT" null="false"/> + <column name="environment_name" type="TEXT" null="false"/> + <column name="config" type="TEXT" null="false"/> + <column name="comment" type="TEXT" null="false"/> + <foreign-key name="tenant_fk" deferrable="DEFERRED"> + <column name="tenant"/> + <references table="tenant"> + <column name="id"/> + </references> + </foreign-key> + <foreign-key name="object_id_fk" on-delete="CASCADE"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + <references table="package"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + </references> + </foreign-key> + <index name="package_build_auxiliaries_object_id_i"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + </index> + <index name="package_build_auxiliaries_index_i"> + <column name="index"/> + </index> + </add-table> + <add-table name="package_build_config_auxiliaries" kind="container"> + <column name="tenant" type="TEXT" null="false"/> + <column name="name" type="CITEXT" null="false"/> + <column name="version_epoch" type="INTEGER" null="false"/> + <column name="version_canonical_upstream" type="TEXT" null="false"/> + <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> + <column name="version_revision" type="INTEGER" null="false"/> + <column name="config_index" type="BIGINT" null="false"/> + <column name="index" type="BIGINT" null="false"/> + <column name="environment_name" type="TEXT" null="false"/> + <column name="config" type="TEXT" null="false"/> + <column name="comment" type="TEXT" null="false"/> + <foreign-key name="tenant_fk" deferrable="DEFERRED"> + <column name="tenant"/> + <references table="tenant"> + <column name="id"/> + </references> + </foreign-key> + <foreign-key name="object_id_fk" on-delete="CASCADE"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + <references table="package"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + </references> + </foreign-key> + <index name="package_build_config_auxiliaries_object_id_i"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + </index> + </add-table> + </changeset> + + <changeset version="30"> + <alter-table name="tenant"> + <add-column name="service_id" type="TEXT" null="true"/> + <add-column name="service_type" type="TEXT" null="true"/> + <add-column name="service_data" type="TEXT" null="true"/> + <add-column name="queued_timestamp" type="BIGINT" null="true"/> + <add-index name="tenant_service_i" type="UNIQUE"> + <column name="service_id"/> + <column name="service_type"/> + </add-index> + <add-index name="tenant_service_id_i"> + <column name="service_id"/> + </add-index> + </alter-table> + </changeset> + + <changeset version="29"> + <alter-table name="package_tests"> + <add-column name="test_enable" type="TEXT" null="true"/> + </alter-table> + </changeset> + + <changeset version="28"> + <alter-table name="package_build_configs"> + <add-column name="config_email" type="TEXT" null="true"/> + <add-column name="config_email_comment" type="TEXT" null="true"/> + <add-column name="config_warning_email" type="TEXT" null="true"/> + <add-column name="config_warning_email_comment" type="TEXT" null="true"/> + <add-column name="config_error_email" type="TEXT" null="true"/> + <add-column name="config_error_email_comment" type="TEXT" null="true"/> + </alter-table> + </changeset> + + <model version="27"> <table name="tenant" kind="object"> <column name="id" type="TEXT" null="false"/> + <column name="private" type="BOOLEAN" null="false"/> + <column name="interactive" type="TEXT" null="true"/> <column name="creation_timestamp" type="BIGINT" null="false"/> <column name="archived" type="BOOLEAN" null="false"/> <primary-key> @@ -142,7 +415,10 @@ <column name="summary" type="TEXT" null="false"/> <column name="description" type="TEXT" null="true"/> <column name="description_type" type="TEXT" null="true"/> - <column name="changes" type="TEXT" null="false"/> + <column name="package_description" type="TEXT" null="true"/> + <column name="package_description_type" type="TEXT" null="true"/> + <column name="changes" type="TEXT" null="true"/> + <column name="changes_type" type="TEXT" null="true"/> <column name="url" type="TEXT" null="true"/> <column name="url_comment" type="TEXT" null="true"/> <column name="doc_url" type="TEXT" null="true"/> @@ -167,6 +443,7 @@ <column name="fragment" type="TEXT" null="true"/> <column name="sha256sum" type="TEXT" null="true"/> <column name="buildable" type="BOOLEAN" null="false"/> + <column name="unbuildable_reason" type="TEXT" null="true"/> <column name="search_index" type="tsvector" null="true"/> <primary-key> <column name="tenant"/> @@ -378,7 +655,6 @@ <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> <column name="version_revision" type="INTEGER" null="false"/> <column name="index" type="BIGINT" null="false"/> - <column name="conditional" type="BOOLEAN" null="false"/> <column name="buildtime" type="BOOLEAN" null="false"/> <column name="comment" type="TEXT" null="false"/> <foreign-key name="tenant_fk" deferrable="DEFERRED"> @@ -424,6 +700,52 @@ <column name="version_revision" type="INTEGER" null="false"/> <column name="dependency_index" type="BIGINT" null="false"/> <column name="index" type="BIGINT" null="false"/> + <column name="enable" type="TEXT" null="true"/> + <column name="reflect" type="TEXT" null="true"/> + <column name="prefer" type="TEXT" null="true"/> + <column name="accept" type="TEXT" null="true"/> + <column name="require" type="TEXT" null="true"/> + <foreign-key name="tenant_fk" deferrable="DEFERRED"> + <column name="tenant"/> + <references table="tenant"> + <column name="id"/> + </references> + </foreign-key> + <foreign-key name="object_id_fk" on-delete="CASCADE"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + <references table="package"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + </references> + </foreign-key> + <index name="package_dependency_alternatives_object_id_i"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + </index> + </table> + <table name="package_dependency_alternative_dependencies" kind="container"> + <column name="tenant" type="TEXT" null="false"/> + <column name="name" type="CITEXT" null="false"/> + <column name="version_epoch" type="INTEGER" null="false"/> + <column name="version_canonical_upstream" type="TEXT" null="false"/> + <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> + <column name="version_revision" type="INTEGER" null="false"/> + <column name="dependency_index" type="BIGINT" null="false"/> + <column name="alternative_index" type="BIGINT" null="false"/> + <column name="index" type="BIGINT" null="false"/> <column name="dep_name" type="CITEXT" null="false"/> <column name="dep_min_version_epoch" type="INTEGER" null="true"/> <column name="dep_min_version_canonical_upstream" type="TEXT" null="true"/> @@ -467,7 +789,7 @@ <column name="version_revision"/> </references> </foreign-key> - <index name="package_dependency_alternatives_object_id_i"> + <index name="package_dependency_alternative_dependencies_object_id_i"> <column name="tenant"/> <column name="name"/> <column name="version_epoch"/> @@ -506,7 +828,6 @@ <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> <column name="version_revision" type="INTEGER" null="false"/> <column name="index" type="BIGINT" null="false"/> - <column name="conditional" type="BOOLEAN" null="false"/> <column name="buildtime" type="BOOLEAN" null="false"/> <column name="comment" type="TEXT" null="false"/> <foreign-key name="tenant_fk" deferrable="DEFERRED"> @@ -552,7 +873,8 @@ <column name="version_revision" type="INTEGER" null="false"/> <column name="requirement_index" type="BIGINT" null="false"/> <column name="index" type="BIGINT" null="false"/> - <column name="id" type="TEXT" null="false"/> + <column name="enable" type="TEXT" null="true"/> + <column name="reflect" type="TEXT" null="true"/> <foreign-key name="tenant_fk" deferrable="DEFERRED"> <column name="tenant"/> <references table="tenant"> @@ -584,6 +906,48 @@ <column name="version_revision"/> </index> </table> + <table name="package_requirement_alternative_requirements" kind="container"> + <column name="tenant" type="TEXT" null="false"/> + <column name="name" type="CITEXT" null="false"/> + <column name="version_epoch" type="INTEGER" null="false"/> + <column name="version_canonical_upstream" type="TEXT" null="false"/> + <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> + <column name="version_revision" type="INTEGER" null="false"/> + <column name="requirement_index" type="BIGINT" null="false"/> + <column name="alternative_index" type="BIGINT" null="false"/> + <column name="index" type="BIGINT" null="false"/> + <column name="id" type="TEXT" null="false"/> + <foreign-key name="tenant_fk" deferrable="DEFERRED"> + <column name="tenant"/> + <references table="tenant"> + <column name="id"/> + </references> + </foreign-key> + <foreign-key name="object_id_fk" on-delete="CASCADE"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + <references table="package"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + </references> + </foreign-key> + <index name="package_requirement_alternative_requirements_object_id_i"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + </index> + </table> <table name="package_tests" kind="container"> <column name="tenant" type="TEXT" null="false"/> <column name="name" type="CITEXT" null="false"/> @@ -592,27 +956,30 @@ <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> <column name="version_revision" type="INTEGER" null="false"/> <column name="index" type="BIGINT" null="false"/> - <column name="dep_name" type="CITEXT" null="false"/> - <column name="dep_min_version_epoch" type="INTEGER" null="true"/> - <column name="dep_min_version_canonical_upstream" type="TEXT" null="true"/> - <column name="dep_min_version_canonical_release" type="TEXT" null="true"/> - <column name="dep_min_version_revision" type="INTEGER" null="true"/> - <column name="dep_min_version_upstream" type="TEXT" null="true"/> - <column name="dep_min_version_release" type="TEXT" null="true"/> - <column name="dep_max_version_epoch" type="INTEGER" null="true"/> - <column name="dep_max_version_canonical_upstream" type="TEXT" null="true"/> - <column name="dep_max_version_canonical_release" type="TEXT" null="true"/> - <column name="dep_max_version_revision" type="INTEGER" null="true"/> - <column name="dep_max_version_upstream" type="TEXT" null="true"/> - <column name="dep_max_version_release" type="TEXT" null="true"/> - <column name="dep_min_open" type="BOOLEAN" null="true"/> - <column name="dep_max_open" type="BOOLEAN" null="true"/> - <column name="dep_package_tenant" type="TEXT" null="true"/> - <column name="dep_package_name" type="CITEXT" null="true"/> - <column name="dep_package_version_epoch" type="INTEGER" null="true"/> - <column name="dep_package_version_canonical_upstream" type="TEXT" null="true"/> - <column name="dep_package_version_canonical_release" type="TEXT" null="true" options="COLLATE "C""/> - <column name="dep_package_version_revision" type="INTEGER" null="true"/> + <column name="test_name" type="CITEXT" null="false"/> + <column name="test_min_version_epoch" type="INTEGER" null="true"/> + <column name="test_min_version_canonical_upstream" type="TEXT" null="true"/> + <column name="test_min_version_canonical_release" type="TEXT" null="true"/> + <column name="test_min_version_revision" type="INTEGER" null="true"/> + <column name="test_min_version_upstream" type="TEXT" null="true"/> + <column name="test_min_version_release" type="TEXT" null="true"/> + <column name="test_max_version_epoch" type="INTEGER" null="true"/> + <column name="test_max_version_canonical_upstream" type="TEXT" null="true"/> + <column name="test_max_version_canonical_release" type="TEXT" null="true"/> + <column name="test_max_version_revision" type="INTEGER" null="true"/> + <column name="test_max_version_upstream" type="TEXT" null="true"/> + <column name="test_max_version_release" type="TEXT" null="true"/> + <column name="test_min_open" type="BOOLEAN" null="true"/> + <column name="test_max_open" type="BOOLEAN" null="true"/> + <column name="test_package_tenant" type="TEXT" null="true"/> + <column name="test_package_name" type="CITEXT" null="true"/> + <column name="test_package_version_epoch" type="INTEGER" null="true"/> + <column name="test_package_version_canonical_upstream" type="TEXT" null="true"/> + <column name="test_package_version_canonical_release" type="TEXT" null="true" options="COLLATE "C""/> + <column name="test_package_version_revision" type="INTEGER" null="true"/> + <column name="test_type" type="TEXT" null="false"/> + <column name="test_buildtime" type="BOOLEAN" null="false"/> + <column name="test_reflect" type="TEXT" null="true"/> <foreign-key name="tenant_fk" deferrable="DEFERRED"> <column name="tenant"/> <references table="tenant"> @@ -646,19 +1013,19 @@ <index name="package_tests_index_i"> <column name="index"/> </index> - <foreign-key name="dep_package_tenant_fk" deferrable="DEFERRED"> - <column name="dep_package_tenant"/> + <foreign-key name="test_package_tenant_fk" deferrable="DEFERRED"> + <column name="test_package_tenant"/> <references table="tenant"> <column name="id"/> </references> </foreign-key> - <foreign-key name="dep_package_fk" deferrable="DEFERRED"> - <column name="dep_package_tenant"/> - <column name="dep_package_name"/> - <column name="dep_package_version_epoch"/> - <column name="dep_package_version_canonical_upstream"/> - <column name="dep_package_version_canonical_release"/> - <column name="dep_package_version_revision"/> + <foreign-key name="test_package_fk" deferrable="DEFERRED"> + <column name="test_package_tenant"/> + <column name="test_package_name"/> + <column name="test_package_version_epoch"/> + <column name="test_package_version_canonical_upstream"/> + <column name="test_package_version_canonical_release"/> + <column name="test_package_version_revision"/> <references table="package"> <column name="tenant"/> <column name="name"/> @@ -669,7 +1036,7 @@ </references> </foreign-key> </table> - <table name="package_examples" kind="container"> + <table name="package_builds" kind="container"> <column name="tenant" type="TEXT" null="false"/> <column name="name" type="CITEXT" null="false"/> <column name="version_epoch" type="INTEGER" null="false"/> @@ -677,27 +1044,8 @@ <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> <column name="version_revision" type="INTEGER" null="false"/> <column name="index" type="BIGINT" null="false"/> - <column name="dep_name" type="CITEXT" null="false"/> - <column name="dep_min_version_epoch" type="INTEGER" null="true"/> - <column name="dep_min_version_canonical_upstream" type="TEXT" null="true"/> - <column name="dep_min_version_canonical_release" type="TEXT" null="true"/> - <column name="dep_min_version_revision" type="INTEGER" null="true"/> - <column name="dep_min_version_upstream" type="TEXT" null="true"/> - <column name="dep_min_version_release" type="TEXT" null="true"/> - <column name="dep_max_version_epoch" type="INTEGER" null="true"/> - <column name="dep_max_version_canonical_upstream" type="TEXT" null="true"/> - <column name="dep_max_version_canonical_release" type="TEXT" null="true"/> - <column name="dep_max_version_revision" type="INTEGER" null="true"/> - <column name="dep_max_version_upstream" type="TEXT" null="true"/> - <column name="dep_max_version_release" type="TEXT" null="true"/> - <column name="dep_min_open" type="BOOLEAN" null="true"/> - <column name="dep_max_open" type="BOOLEAN" null="true"/> - <column name="dep_package_tenant" type="TEXT" null="true"/> - <column name="dep_package_name" type="CITEXT" null="true"/> - <column name="dep_package_version_epoch" type="INTEGER" null="true"/> - <column name="dep_package_version_canonical_upstream" type="TEXT" null="true"/> - <column name="dep_package_version_canonical_release" type="TEXT" null="true" options="COLLATE "C""/> - <column name="dep_package_version_revision" type="INTEGER" null="true"/> + <column name="expression" type="TEXT" null="false"/> + <column name="comment" type="TEXT" null="false"/> <foreign-key name="tenant_fk" deferrable="DEFERRED"> <column name="tenant"/> <references table="tenant"> @@ -720,7 +1068,7 @@ <column name="version_revision"/> </references> </foreign-key> - <index name="package_examples_object_id_i"> + <index name="package_builds_object_id_i"> <column name="tenant"/> <column name="name"/> <column name="version_epoch"/> @@ -728,33 +1076,11 @@ <column name="version_canonical_release"/> <column name="version_revision"/> </index> - <index name="package_examples_index_i"> + <index name="package_builds_index_i"> <column name="index"/> </index> - <foreign-key name="dep_package_tenant_fk" deferrable="DEFERRED"> - <column name="dep_package_tenant"/> - <references table="tenant"> - <column name="id"/> - </references> - </foreign-key> - <foreign-key name="dep_package_fk" deferrable="DEFERRED"> - <column name="dep_package_tenant"/> - <column name="dep_package_name"/> - <column name="dep_package_version_epoch"/> - <column name="dep_package_version_canonical_upstream"/> - <column name="dep_package_version_canonical_release"/> - <column name="dep_package_version_revision"/> - <references table="package"> - <column name="tenant"/> - <column name="name"/> - <column name="version_epoch"/> - <column name="version_canonical_upstream"/> - <column name="version_canonical_release"/> - <column name="version_revision"/> - </references> - </foreign-key> </table> - <table name="package_benchmarks" kind="container"> + <table name="package_build_constraints" kind="container"> <column name="tenant" type="TEXT" null="false"/> <column name="name" type="CITEXT" null="false"/> <column name="version_epoch" type="INTEGER" null="false"/> @@ -762,27 +1088,10 @@ <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> <column name="version_revision" type="INTEGER" null="false"/> <column name="index" type="BIGINT" null="false"/> - <column name="dep_name" type="CITEXT" null="false"/> - <column name="dep_min_version_epoch" type="INTEGER" null="true"/> - <column name="dep_min_version_canonical_upstream" type="TEXT" null="true"/> - <column name="dep_min_version_canonical_release" type="TEXT" null="true"/> - <column name="dep_min_version_revision" type="INTEGER" null="true"/> - <column name="dep_min_version_upstream" type="TEXT" null="true"/> - <column name="dep_min_version_release" type="TEXT" null="true"/> - <column name="dep_max_version_epoch" type="INTEGER" null="true"/> - <column name="dep_max_version_canonical_upstream" type="TEXT" null="true"/> - <column name="dep_max_version_canonical_release" type="TEXT" null="true"/> - <column name="dep_max_version_revision" type="INTEGER" null="true"/> - <column name="dep_max_version_upstream" type="TEXT" null="true"/> - <column name="dep_max_version_release" type="TEXT" null="true"/> - <column name="dep_min_open" type="BOOLEAN" null="true"/> - <column name="dep_max_open" type="BOOLEAN" null="true"/> - <column name="dep_package_tenant" type="TEXT" null="true"/> - <column name="dep_package_name" type="CITEXT" null="true"/> - <column name="dep_package_version_epoch" type="INTEGER" null="true"/> - <column name="dep_package_version_canonical_upstream" type="TEXT" null="true"/> - <column name="dep_package_version_canonical_release" type="TEXT" null="true" options="COLLATE "C""/> - <column name="dep_package_version_revision" type="INTEGER" null="true"/> + <column name="exclusion" type="BOOLEAN" null="false"/> + <column name="config" type="TEXT" null="false"/> + <column name="target" type="TEXT" null="true"/> + <column name="comment" type="TEXT" null="false"/> <foreign-key name="tenant_fk" deferrable="DEFERRED"> <column name="tenant"/> <references table="tenant"> @@ -805,7 +1114,7 @@ <column name="version_revision"/> </references> </foreign-key> - <index name="package_benchmarks_object_id_i"> + <index name="package_build_constraints_object_id_i"> <column name="tenant"/> <column name="name"/> <column name="version_epoch"/> @@ -813,22 +1122,34 @@ <column name="version_canonical_release"/> <column name="version_revision"/> </index> - <index name="package_benchmarks_index_i"> + <index name="package_build_constraints_index_i"> <column name="index"/> </index> - <foreign-key name="dep_package_tenant_fk" deferrable="DEFERRED"> - <column name="dep_package_tenant"/> + </table> + <table name="package_build_configs" kind="container"> + <column name="tenant" type="TEXT" null="false"/> + <column name="name" type="CITEXT" null="false"/> + <column name="version_epoch" type="INTEGER" null="false"/> + <column name="version_canonical_upstream" type="TEXT" null="false"/> + <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> + <column name="version_revision" type="INTEGER" null="false"/> + <column name="index" type="BIGINT" null="false"/> + <column name="config_name" type="TEXT" null="false"/> + <column name="config_arguments" type="TEXT" null="false"/> + <column name="config_comment" type="TEXT" null="false"/> + <foreign-key name="tenant_fk" deferrable="DEFERRED"> + <column name="tenant"/> <references table="tenant"> <column name="id"/> </references> </foreign-key> - <foreign-key name="dep_package_fk" deferrable="DEFERRED"> - <column name="dep_package_tenant"/> - <column name="dep_package_name"/> - <column name="dep_package_version_epoch"/> - <column name="dep_package_version_canonical_upstream"/> - <column name="dep_package_version_canonical_release"/> - <column name="dep_package_version_revision"/> + <foreign-key name="object_id_fk" on-delete="CASCADE"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> <references table="package"> <column name="tenant"/> <column name="name"/> @@ -838,14 +1159,26 @@ <column name="version_revision"/> </references> </foreign-key> + <index name="package_build_configs_object_id_i"> + <column name="tenant"/> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + </index> + <index name="package_build_configs_index_i"> + <column name="index"/> + </index> </table> - <table name="package_builds" kind="container"> + <table name="package_build_config_builds" kind="container"> <column name="tenant" type="TEXT" null="false"/> <column name="name" type="CITEXT" null="false"/> <column name="version_epoch" type="INTEGER" null="false"/> <column name="version_canonical_upstream" type="TEXT" null="false"/> <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> <column name="version_revision" type="INTEGER" null="false"/> + <column name="config_index" type="BIGINT" null="false"/> <column name="index" type="BIGINT" null="false"/> <column name="expression" type="TEXT" null="false"/> <column name="comment" type="TEXT" null="false"/> @@ -871,7 +1204,7 @@ <column name="version_revision"/> </references> </foreign-key> - <index name="package_builds_object_id_i"> + <index name="package_build_config_builds_object_id_i"> <column name="tenant"/> <column name="name"/> <column name="version_epoch"/> @@ -879,17 +1212,15 @@ <column name="version_canonical_release"/> <column name="version_revision"/> </index> - <index name="package_builds_index_i"> - <column name="index"/> - </index> </table> - <table name="package_build_constraints" kind="container"> + <table name="package_build_config_constraints" kind="container"> <column name="tenant" type="TEXT" null="false"/> <column name="name" type="CITEXT" null="false"/> <column name="version_epoch" type="INTEGER" null="false"/> <column name="version_canonical_upstream" type="TEXT" null="false"/> <column name="version_canonical_release" type="TEXT" null="false" options="COLLATE "C""/> <column name="version_revision" type="INTEGER" null="false"/> + <column name="config_index" type="BIGINT" null="false"/> <column name="index" type="BIGINT" null="false"/> <column name="exclusion" type="BOOLEAN" null="false"/> <column name="config" type="TEXT" null="false"/> @@ -917,7 +1248,7 @@ <column name="version_revision"/> </references> </foreign-key> - <index name="package_build_constraints_object_id_i"> + <index name="package_build_config_constraints_object_id_i"> <column name="tenant"/> <column name="name"/> <column name="version_epoch"/> @@ -925,9 +1256,6 @@ <column name="version_canonical_release"/> <column name="version_revision"/> </index> - <index name="package_build_constraints_index_i"> - <column name="index"/> - </index> </table> <table name="package_other_repositories" kind="container"> <column name="tenant" type="TEXT" null="false"/> diff --git a/libbrep/types.hxx b/libbrep/types.hxx index 65c9791..3b5777d 100644 --- a/libbrep/types.hxx +++ b/libbrep/types.hxx @@ -1,5 +1,4 @@ // file : libbrep/types.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef LIBBREP_TYPES_HXX @@ -22,11 +21,12 @@ #include <odb/lazy-ptr.hxx> -#include <libbutl/path.mxx> -#include <libbutl/path-io.mxx> -#include <libbutl/optional.mxx> -#include <libbutl/timestamp.mxx> -#include <libbutl/small-vector.mxx> +#include <libbutl/url.hxx> +#include <libbutl/path.hxx> +#include <libbutl/path-io.hxx> +#include <libbutl/optional.hxx> +#include <libbutl/timestamp.hxx> +#include <libbutl/small-vector.hxx> namespace brep { @@ -50,7 +50,7 @@ namespace brep using std::weak_ptr; using std::vector; - using butl::small_vector; // <libbutl/small-vector.mxx> + using butl::small_vector; // <libbutl/small-vector.hxx> using strings = vector<string>; using cstrings = vector<const char*>; @@ -69,7 +69,7 @@ namespace brep using std::generic_category; - // <libbutl/optional.mxx> + // <libbutl/optional.hxx> // using butl::optional; using butl::nullopt; @@ -79,7 +79,7 @@ namespace brep using odb::lazy_shared_ptr; using odb::lazy_weak_ptr; - // <libbutl/path.mxx> + // <libbutl/path.hxx> // using butl::path; using butl::dir_path; @@ -91,10 +91,15 @@ namespace brep using butl::path_cast; - // <libbutl/timestamp.mxx> + // <libbutl/url.hxx> + // + using butl::url; + + // <libbutl/timestamp.hxx> // using butl::system_clock; using butl::timestamp; + using butl::duration; using butl::timestamp_nonexistent; } diff --git a/libbrep/utility.hxx b/libbrep/utility.hxx index 96cf1d4..fce8fb5 100644 --- a/libbrep/utility.hxx +++ b/libbrep/utility.hxx @@ -1,17 +1,17 @@ // file : libbrep/utility.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef LIBBREP_UTILITY_HXX #define LIBBREP_UTILITY_HXX -#include <memory> // make_shared() -#include <string> // to_string() -#include <utility> // move(), forward(), declval(), make_pair() -#include <cassert> // assert() -#include <iterator> // make_move_iterator() +#include <memory> // make_shared() +#include <string> // to_string() +#include <utility> // move(), forward(), declval(), make_pair() +#include <cassert> // assert() +#include <iterator> // make_move_iterator() +#include <algorithm> // * -#include <libbutl/utility.mxx> // icasecmp(), reverse_iterate(), +#include <libbutl/utility.hxx> // icasecmp(), reverse_iterate(), // operator<<(ostream, exception) namespace brep @@ -25,8 +25,9 @@ namespace brep using std::make_move_iterator; using std::to_string; - // <libbutl/utility.mxx> + // <libbutl/utility.hxx> // + using butl::utf8; using butl::icasecmp; using butl::reverse_iterate; } diff --git a/libbrep/version.hxx.in b/libbrep/version.hxx.in index 00fb4ff..3ac3752 100644 --- a/libbrep/version.hxx.in +++ b/libbrep/version.hxx.in @@ -1,5 +1,4 @@ // file : libbrep/version.hxx.in -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef BREP_VERSION // Note: using the version macro itself. diff --git a/libbrep/wrapper-traits.hxx b/libbrep/wrapper-traits.hxx index 54c5ef1..8c9d830 100644 --- a/libbrep/wrapper-traits.hxx +++ b/libbrep/wrapper-traits.hxx @@ -1,5 +1,4 @@ // file : libbrep/wrapper-traits.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef LIBBREP_WRAPPER_TRAITS_HXX @@ -7,7 +6,7 @@ #include <odb/pre.hxx> -#include <libbutl/optional.mxx> +#include <libbutl/optional.hxx> #include <odb/wrapper-traits.hxx> |