diff options
Diffstat (limited to 'bpkg/package.hxx')
-rw-r--r-- | bpkg/package.hxx | 325 |
1 files changed, 222 insertions, 103 deletions
diff --git a/bpkg/package.hxx b/bpkg/package.hxx index d7c9461..400519a 100644 --- a/bpkg/package.hxx +++ b/bpkg/package.hxx @@ -11,6 +11,7 @@ #include <type_traits> // static_assert #include <odb/core.hxx> +#include <odb/section.hxx> #include <odb/nested-container.hxx> #include <libbutl/timestamp.hxx> @@ -25,9 +26,13 @@ // Used by the data migration entries. // -#define DB_SCHEMA_VERSION_BASE 7 +// NOTE: drop all the `#pragma db member(...) default(...)` pragmas when +// migration is no longer supported (i.e., the current and base schema +// versions are the same). +// +#define DB_SCHEMA_VERSION_BASE 12 -#pragma db model version(DB_SCHEMA_VERSION_BASE, 20, closed) +#pragma db model version(DB_SCHEMA_VERSION_BASE, 26, closed) namespace bpkg { @@ -513,6 +518,10 @@ namespace bpkg operator size_t () const {return result;} }; + // language + // + #pragma db value(language) definition + // package_location // #pragma db value @@ -613,9 +622,6 @@ namespace bpkg // #pragma db value(test_dependency) definition - // @@ TMP Drop when database migration to the schema version 11 is no longer - // supported. - // #pragma db member(test_dependency::buildtime) default(false) using optional_test_dependency_type = optional<test_dependency_type>; @@ -670,14 +676,27 @@ namespace bpkg // #pragma db value(buildfile) definition + // distribution_name_value + // + #pragma db value(distribution_name_value) definition + #pragma db object pointer(shared_ptr) session class available_package { public: using version_type = bpkg::version; + using upstream_version_type = bpkg::upstream_version; available_package_id id; - upstream_version version; + upstream_version_type version; + + optional<string> upstream_version; + optional<string> type; + + small_vector<language, 1> languages; + odb::section languages_section; + + optional<package_name> project; // List of repository fragments to which this package version belongs // (yes, in our world, it can be in multiple, unrelated repositories) @@ -697,8 +716,17 @@ namespace bpkg // Package manifest data and, potentially, the special test dependencies. // - // Note that there can be only one special test dependencies entry in the - // list and it's always the last one, if present. + // Note that there can only be one special test dependencies entry in the + // list. It can only be present for a test package and specifies all the + // main packages as the alternative dependencies. If present, it is + // located right after the last explicit depends clause which specifies a + // main package for this test package, if such a clause is present, and as + // the first entry otherwise. The idea here is to inject the special + // depends clause as early as possible, so that the other clauses could + // potentially refer to the reflection variables it may set. But not too + // early, so that the explicit main package dependencies are already + // resolved by the time of resolving the special clause to avoid the + // 'unable to select dependency alternative' error. // using dependencies_type = bpkg::dependencies; @@ -716,6 +744,8 @@ namespace bpkg optional<string> root_build; vector<buildfile> buildfiles; + vector<distribution_name_value> distribution_values; + // Present for non-transient objects only (and only for certain repository // types). // @@ -732,8 +762,13 @@ namespace bpkg available_package (package_manifest&& m) : id (move (m.name), m.version), version (move (m.version)), + upstream_version (move (m.upstream_version)), + type (move (m.type)), + languages (move (m.languages)), + project (move (m.project)), dependencies (convert (move (m.dependencies))), tests (move (m.tests)), + distribution_values (move (m.distribution_values)), sha256sum (move (m.sha256sum)) { if (!stub ()) @@ -765,6 +800,18 @@ namespace bpkg bool stub () const {return version.compare (wildcard_version, true) == 0;} + string + effective_type () const + { + return package_manifest::effective_type (type, id.name); + } + + small_vector<language, 1> + effective_languages () const + { + return package_manifest::effective_languages (languages, id.name); + } + // Return package system version if one has been discovered. Note that // we do not implicitly assume a wildcard version. // @@ -781,6 +828,16 @@ namespace bpkg // #pragma db member(id) id column("") #pragma db member(version) set(this.version.init (this.id.version, (?))) + + // languages + // + #pragma db member(languages) id_column("") value_column("language_") \ + section(languages_section) + + #pragma db member(languages_section) load(lazy) update(always) + + // locations + // #pragma db member(locations) id_column("") value_column("") \ unordered value_not_null @@ -834,31 +891,27 @@ namespace bpkg // #pragma db member(tests) id_column("") value_column("test_") - // alt_naming + // distribution_values // - // @@ TMP Drop when database migration to the schema version 20 is no - // longer supported. + #pragma db member(distribution_values) id_column("") value_column("dist_") + + // alt_naming // - // Note that since no real packages with alternative buildfile naming - // use conditional dependencies yet, we can just set alt_naming to - // false during migration to the database schema version 20. Also we - // never rely on alt_naming to be nullopt for the stub packages, so - // let's not complicate things and set alt_naming to false for them - // either. + // Note that since no real packages with alternative buildfile naming use + // conditional dependencies yet, we can just set alt_naming to false + // during migration to the database schema version 20. Also we never rely + // on alt_naming to be nullopt for the stub packages, so let's not + // complicate things and set alt_naming to false for them either. // #pragma db member(alt_naming) default(false) // *_build // - // @@ TMP Drop when database migration to the schema version 15 is no - // longer supported. - // - // Note that since no real packages use conditional dependencies yet, - // we can just set bootstrap_build to the empty string during migration - // to the database schema version 15. Also we never rely on - // bootstrap_build to be nullopt for the stub packages, so let's not - // complicate things and set bootstrap_build to the empty string for - // them either. + // Note that since no real packages use conditional dependencies yet, we + // can just set bootstrap_build to the empty string during migration to + // the database schema version 15. Also we never rely on bootstrap_build + // to be nullopt for the stub packages, so let's not complicate things and + // set bootstrap_build to the empty string for them either. // #pragma db member(bootstrap_build) default("") @@ -871,6 +924,15 @@ namespace bpkg available_package () = default; }; + // The available packages together with the repository fragments they belong + // to. + // + // Note that lazy_shared_ptr is used to also convey the databases the + // objects belong to. + // + using available_packages = vector<pair<shared_ptr<available_package>, + lazy_shared_ptr<repository_fragment>>>; + #pragma db view object(available_package) struct available_package_count { @@ -1033,37 +1095,9 @@ namespace bpkg // optional<version_constraint> constraint; - // Position of the first dependency alternative with a configuration - // clause, if any. - // - // Specifically, if there is such an alternative then this is a pair of - // 1-based indexes of the respective depends value (first) and the - // dependency alternative (second) in the dependent's manifest. Otherwise, - // this is a pair of zeros. - // - // For example, for the following dependent the position for libfoo/1.2.0 - // prerequisite will be {2,2}: - // - // libbar: depends: libfoo >= 1.1.0 - // depends: libfox | libfoo >= 1.2.0 {require {...}} - // - pair<size_t, size_t> config_position; - // Database mapping. // #pragma db member(constraint) column("") - - #pragma db member(config_position) transient - - #pragma db member(config_dependency_index) \ - virtual(size_t) \ - access(config_position.first) \ - default(0) - - #pragma db member(config_alternative_index) \ - virtual(size_t) \ - access(config_position.second) \ - default(0) }; // Note that the keys for this map need to be created with the database @@ -1177,9 +1211,9 @@ namespace bpkg // package version revision increment. In particular, new subprojects // should trigger the package reconfiguration. // - // Must be present if the source directory is present, unless the object - // is created/updated during the package build simulation (see pkg-build - // for details). Note that during the simulation the manifest may not be + // Only present for external packages, unless the objects are + // created/updated during the package build simulation (see pkg-build for + // details). Note that during the simulation the manifest may not be // available. // // @@ Currently we don't consider subprojects recursively (would most @@ -1191,30 +1225,46 @@ namespace bpkg // optional<std::string> manifest_checksum; - // Absent if the package has no buildfile clauses in the dependencies. - // Otherwise, the checksum of the buildfiles calculated over the *-build - // manifest values or, if unspecified, the files in the package source - // directory. + // Only present for external packages which have buildfile clauses in the + // dependencies, unless the objects are created/updated during the package + // build simulation (see pkg-build for details). // - // Note that for external packages the checksum is always calculated over - // the files. This is "parallel" to the package skeleton logic. + // Note that the checksum is always calculated over the files rather than + // the *-build manifest values. This is "parallel" to the package skeleton + // logic. // optional<std::string> buildfiles_checksum; - // Path to the output directory of this package, if any. It is - // always relative to the configuration directory, and is <name> - // for external packages and <name>-<version> for others. It is - // only set once the package is configured and its main purse is - // to keep track of what needs to be cleaned by the user before - // a broken package can be purged. Note that it could be the - // same as src_root. + // Path to the output directory of this package, if any. It is always + // relative to the configuration directory, and is <name> for external + // packages and <name>-<version> for others. It is only set once the + // package is configured and its main purpose is to keep track of what + // needs to be cleaned by the user before a broken package can be + // purged. Note that it could be the same as src_root. // optional<dir_path> out_root; package_prerequisites prerequisites; + // 1-based indexes of the selected dependency alternatives which the + // prerequisite packages are resolved from. Parallel to the dependencies + // member of the respective available package. Entries which don't + // correspond to a selected alternative (toolchain build-time dependency, + // not enabled alternatives, etc) are set to 0. + // + using indexes_type = vector<size_t>; // Make sure ODB maps it portably. + indexes_type dependency_alternatives; + odb::section dependency_alternatives_section; + + // Project configuration variable names and their sources. + // vector<config_variable> config_variables; + // SHA256 checksum of variables (names and values) referred to by the + // config_variables member. + // + std::string config_checksum; + public: bool system () const @@ -1259,6 +1309,18 @@ namespace bpkg std::string string (database&) const; + // Return the relative archive path completed using the configuration + // directory. Return the absolute archive path as is. + // + path + effective_archive (const dir_path& configuration) const + { + // Cast for compiling with ODB (see above). + // + assert (static_cast<bool> (archive)); + return archive->absolute () ? *archive : configuration / *archive; + } + // Return the relative source directory completed using the configuration // directory. Return the absolute source directory as is. // @@ -1271,8 +1333,7 @@ namespace bpkg return src_root->absolute () ? *src_root : configuration / *src_root; } - // Return the output directory using the configuration directory. Note - // that the output directory is always relative. + // Return the output directory using the configuration directory. // dir_path effective_out_root (const dir_path& configuration) const @@ -1280,6 +1341,9 @@ namespace bpkg // Cast for compiling with ODB (see above). // assert (static_cast<bool> (out_root)); + + // Note that out_root is always relative. + // return configuration / *out_root; } @@ -1290,8 +1354,21 @@ namespace bpkg #pragma db member(prerequisites) id_column("package") \ key_column("") value_column("") + #pragma db member(dependency_alternatives) id_column("package") \ + value_column("position") section(dependency_alternatives_section) + + #pragma db member(dependency_alternatives_section) load(lazy) update(always) + #pragma db member(config_variables) id_column("package") value_column("") + // For the sake of simplicity let's not calculate the checksum during + // migration. It seems that the only drawback of this approach is a + // (single) spurious reconfiguration of a dependency of a dependent with + // configuration clause previously configured by bpkg with the database + // schema version prior to 24. + // + #pragma db member(config_checksum) default("") + // Explicit aggregate initialization for C++20 (private default ctor). // selected_package (package_name n, @@ -1361,21 +1438,24 @@ namespace bpkg // // Pass the build2 project info for the package, if available, to speed up // the call and NULL otherwise (in which case it will be queried by the - // implementation). + // implementation). In the former case it is assumed that the package info + // has been retrieved with the b_info_flags::subprojects flag. // // Notes: // // - The package directory is considered an iteration of the package if this // upstream version and revision is already present (selected) in the - // configuration and has a source directory. If that's the case, then the - // specified directory path and the checksum of the manifest file it - // contains are compared to the ones of the package present in the - // configuration. If both match, then the present package version - // (including its iteration, if any) is returned. Otherwise (the package - // has moved and/or the packaging information has changed), the present - // package version with the incremented iteration number is returned. Note - // that the directory path is matched only for the external selected - // packages. + // configuration and has a source directory. If that's the case and if the + // present version is not external (the package is being switched to a + // local potentially amended version), then the present package version + // with the incremented iteration number is returned. Otherwise (the + // present package is external), the specified directory path and the + // package checksum (see package_checksum() for details) are compared to + // the ones of the package present in the configuration. If both match, + // then the present package version (including its iteration, if any) is + // returned. Otherwise (the package has moved and/or the package + // information has changed), the present package version with the + // incremented iteration number is returned. // // - Only a single package iteration is valid per version in the // configuration. This, in particular, means that a package of the @@ -1511,21 +1591,6 @@ namespace bpkg #pragma db column("pp.package") package_name name; - #pragma db transient - pair<size_t, size_t> config_position; - - #pragma db member(config_dependency_index) \ - column("pp.config_dependency_index") \ - virtual(size_t) \ - access(config_position.first) \ - default(0) - - #pragma db member(config_alternative_index) \ - column("pp.config_alternative_index") \ - virtual(size_t) \ - access(config_position.second) \ - default(0) - #pragma db column("pp.") optional<version_constraint> constraint; }; @@ -1558,12 +1623,6 @@ namespace bpkg package_key (database& d, package_name n): db (d), name (move (n)) {} - // Create a pseudo-package (command line as a dependent, etc). - // - package_key (database& d, string n) - : db (d), - name (n.empty () ? package_name () : package_name (move (n))) {} - bool operator== (const package_key& v) const { @@ -1595,6 +1654,66 @@ namespace bpkg return os << p.string (); } + // Database, package name, and package version. + // + // It is normally used as a key for maps containing data for package + // versions across multiple linked configurations. Assumes that the + // respective databases are not detached during such map lifetimes. + // Considers all package name, package version, and database for objects + // comparison. + // + // The package name can be a pseudo-package (command line as a dependent, + // etc), in which case the version is absent. The version can also be empty, + // denoting a package of an unknown version. + // + struct package_version_key + { + reference_wrapper<database> db; + package_name name; + optional<bpkg::version> version; + + package_version_key (database& d, package_name n, bpkg::version v) + : db (d), name (move (n)), version (move (v)) {} + + // Create a pseudo-package (command line as a dependent, etc). + // + package_version_key (database& d, string n) + : db (d), + name (move (n), package_name::raw_string) {} + + bool + operator== (const package_version_key& v) const + { + // See operator==(database, database). + // + return name == v.name && + version == v.version && + &db.get () == &v.db.get (); + } + + bool + operator!= (const package_version_key& v) const + { + return !(*this == v); + } + + bool + operator< (const package_version_key&) const; + + // Return the package string representation in the form: + // + // <name>[/<version>] [ <config-dir>] + // + std::string + string (bool ignore_version = false) const; + }; + + inline ostream& + operator<< (ostream& os, const package_version_key& p) + { + return os << p.string (); + } + // Return a count of repositories that contain this repository fragment. // #pragma db view table("main.repository_fragments") |