From c9d13dff940ab16e28f2440a819a0151a3a7543f Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 2 Dec 2021 15:27:42 +0300 Subject: Prepare for supporting multiple dependencies in dependency alternative --- bpkg/database.cxx | 66 ++++++++++++++++++++++++++++++++++++++++++++ bpkg/package.hxx | 50 +++++++++++++++++++++++++-------- bpkg/package.xml | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ bpkg/pkg-build.cxx | 39 ++++++++++++++++---------- bpkg/pkg-configure.cxx | 17 +++++++----- bpkg/pkg-verify.cxx | 11 +++++--- bpkg/rep-fetch.cxx | 28 +++++++++++++++---- 7 files changed, 244 insertions(+), 42 deletions(-) diff --git a/bpkg/database.cxx b/bpkg/database.cxx index 4f3b102..39013e8 100644 --- a/bpkg/database.cxx +++ b/bpkg/database.cxx @@ -187,6 +187,72 @@ namespace bpkg "ON selected_package_prerequisites (configuration, prerequisite)"); }); + static const migration_entry<13> + migrate_v13 ([] (odb::database& db) + { + // Note that + // available_package_dependency_alternative_dependencies.alternative_index + // is copied from available_package_dependency_alternatives.index and + // available_package_dependency_alternative_dependencies.index is set to 0. + // + db.execute ( + "INSERT INTO \"main\".\"available_package_dependency_alternative_dependencies\" " + "(\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"dependency_index\", " + "\"alternative_index\", " + "\"index\", " + "\"dep_name\", " + "\"dep_min_version_epoch\", " + "\"dep_min_version_canonical_upstream\", " + "\"dep_min_version_canonical_release\", " + "\"dep_min_version_revision\", " + "\"dep_min_version_iteration\", " + "\"dep_min_version_upstream\", " + "\"dep_min_version_release\", " + "\"dep_max_version_epoch\", " + "\"dep_max_version_canonical_upstream\", " + "\"dep_max_version_canonical_release\", " + "\"dep_max_version_revision\", " + "\"dep_max_version_iteration\", " + "\"dep_max_version_upstream\", " + "\"dep_max_version_release\", " + "\"dep_min_open\", " + "\"dep_max_open\") " + "SELECT " + "\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"dependency_index\", " + "\"index\", " + "0, " + "\"dep_name\", " + "\"dep_min_version_epoch\", " + "\"dep_min_version_canonical_upstream\", " + "\"dep_min_version_canonical_release\", " + "\"dep_min_version_revision\", " + "\"dep_min_version_iteration\", " + "\"dep_min_version_upstream\", " + "\"dep_min_version_release\", " + "\"dep_max_version_epoch\", " + "\"dep_max_version_canonical_upstream\", " + "\"dep_max_version_canonical_release\", " + "\"dep_max_version_revision\", " + "\"dep_max_version_iteration\", " + "\"dep_max_version_upstream\", " + "\"dep_max_version_release\", " + "\"dep_min_open\", " + "\"dep_max_open\" " + "FROM \"main\".\"available_package_dependency_alternatives\""); + }); + static inline path cfg_path (const dir_path& d, bool create) { diff --git a/bpkg/package.hxx b/bpkg/package.hxx index fe1664f..ec86ea2 100644 --- a/bpkg/package.hxx +++ b/bpkg/package.hxx @@ -27,7 +27,7 @@ // #define DB_SCHEMA_VERSION_BASE 7 -#pragma db model version(DB_SCHEMA_VERSION_BASE, 12, closed) +#pragma db model version(DB_SCHEMA_VERSION_BASE, 13, closed) namespace bpkg { @@ -535,6 +535,7 @@ namespace bpkg #pragma db value(version_constraint) definition #pragma db value(dependency) definition #pragma db member(dependency::constraint) column("") + #pragma db value(dependency_alternative) definition #pragma db value(dependency_alternatives) definition // Extend dependency_alternatives to also represent the special test @@ -710,21 +711,48 @@ namespace bpkg // dependencies // - using _dependency_key = odb::nested_key; - using _dependency_alternatives_ex_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::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 dependency_alternatives_ex values. + // #pragma db member(dependencies) id_column("") value_column("") - #pragma db member(dependency_alternatives_ex) \ - table("available_package_dependency_alternatives") \ - virtual(_dependency_alternatives_ex_type) \ + + // Container of the dependency_alternative values. + // + using _dependency_alternative_key = + odb::nested_key; + + using _dependency_alternatives_type = + std::map<_dependency_alternative_key, dependency_alternative>; + + #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(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; + 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_") // tests diff --git a/bpkg/package.xml b/bpkg/package.xml index f54c902..9f17ab0 100644 --- a/bpkg/package.xml +++ b/bpkg/package.xml @@ -1,4 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index d027866..df4c079 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -1139,18 +1139,22 @@ namespace bpkg const lazy_shared_ptr& af (pkg.repository_fragment); const package_name& name (ap->id.name); - for (const dependency_alternatives_ex& da: ap->dependencies) + for (const dependency_alternatives_ex& das: ap->dependencies) { - if (da.conditional) // @@ TODO + if (das.conditional) // @@ TODO fail << "conditional dependencies are not yet supported"; - if (da.size () != 1) // @@ TODO + if (das.size () != 1) // @@ TODO fail << "multiple dependency alternatives not yet supported"; - const dependency& dp (da.front ()); + const dependency_alternative& da (das.front ()); + + assert (da.size () == 1); // @@ DEP + + const dependency& dp (da[0]); const package_name& dn (dp.name); - if (da.buildtime) + if (das.buildtime) { // Handle special names. // @@ -1204,11 +1208,11 @@ namespace bpkg // const version_constraint* dep_constr (nullptr); - database* ddb (fdb (pdb, dn, da.buildtime)); + database* ddb (fdb (pdb, dn, das.buildtime)); auto i (ddb != nullptr ? map_.find (*ddb, dn) - : map_.find_dependency (pdb, dn, da.buildtime)); + : map_.find_dependency (pdb, dn, das.buildtime)); if (i != map_.end ()) { @@ -1265,7 +1269,7 @@ namespace bpkg pair, database*> spd ( ddb != nullptr ? make_pair (ddb->find (dn), ddb) - : find_dependency (pdb, dn, da.buildtime)); + : find_dependency (pdb, dn, das.buildtime)); if (ddb == nullptr) ddb = &pdb; @@ -1360,7 +1364,7 @@ namespace bpkg // for this dependency on the command line (using --config-*), then // this configuration is used as the starting point for this search. // - if (da.buildtime && + if (das.buildtime && dsp == nullptr && ddb->type != buildtime_dependency_type (dn)) { @@ -1480,7 +1484,7 @@ namespace bpkg // same configuration with the build2 module it depends upon is an // error. // - if (da.buildtime && + if (das.buildtime && !build2_module (name) && build2_module (dn) && pdb == *ddb) @@ -2474,16 +2478,21 @@ namespace bpkg // be built in the order that is as close to the manifest as // possible. // - for (const dependency_alternatives_ex& da: + for (const dependency_alternatives_ex& das: reverse_iterate (ap->dependencies)) { - assert (!da.conditional && da.size () == 1); // @@ TODO - const dependency& d (da.front ()); + assert (!das.conditional && das.size () == 1); // @@ TODO + + const dependency_alternative& da (das.front ()); + + assert (da.size () == 1); // @@ DEP + + const dependency& d (da[0]); const package_name& dn (d.name); // Skip special names. // - if (da.buildtime && (dn == "build2" || dn == "bpkg")) + if (das.buildtime && (dn == "build2" || dn == "bpkg")) continue; // Note that for the repointed dependent we only order its new and @@ -2492,7 +2501,7 @@ namespace bpkg // update (order (pdb, d.name, - da.buildtime, + das.buildtime, chain, fdb, false /* reorder */)); diff --git a/bpkg/pkg-configure.cxx b/bpkg/pkg-configure.cxx index 65718ca..96f3607 100644 --- a/bpkg/pkg-configure.cxx +++ b/bpkg/pkg-configure.cxx @@ -28,16 +28,19 @@ namespace bpkg { package_prerequisites r; - for (const dependency_alternatives_ex& da: deps) + for (const dependency_alternatives_ex& das: deps) { - assert (!da.conditional); //@@ TODO + assert (!das.conditional); //@@ TODO bool satisfied (false); - for (const dependency& d: da) + for (const dependency_alternative& da: das) { + assert (da.size () == 1); // @@ DEP + + const dependency& d (da[0]); const package_name& n (d.name); - if (da.buildtime) + if (das.buildtime) { // Handle special names. // @@ -63,12 +66,12 @@ namespace bpkg } } - database* ddb (fdb ? fdb (db, n, da.buildtime) : nullptr); + database* ddb (fdb ? fdb (db, n, das.buildtime) : nullptr); pair, database*> spd ( ddb != nullptr ? make_pair (ddb->find (n), ddb) - : find_dependency (db, n, da.buildtime)); + : find_dependency (db, n, das.buildtime)); if (const shared_ptr& dp = spd.first) { @@ -111,7 +114,7 @@ namespace bpkg } if (!satisfied) - fail << "no configured package satisfies dependency on " << da; + fail << "no configured package satisfies dependency on " << das; } return r; diff --git a/bpkg/pkg-verify.cxx b/bpkg/pkg-verify.cxx index 0afe32b..757a2c5 100644 --- a/bpkg/pkg-verify.cxx +++ b/bpkg/pkg-verify.cxx @@ -54,18 +54,21 @@ namespace bpkg if (nv.name == "depends") try { - dependency_alternatives da (nv.value); + dependency_alternatives das (nv.value); - if (da.buildtime) + if (das.buildtime) { - for (dependency& d: da) + for (const dependency_alternative& da: das) { + assert (da.size () == 1); // @@ DEP + + const dependency& d (da[0]); const package_name& dn (d.name); if (dn != "build2" && dn != "bpkg") continue; - if (da.size () != 1) + if (das.size () != 1) { if (diag_level != 0) error (p.name (), nv.value_line, nv.value_column) diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx index 675dad0..d7e626c 100644 --- a/bpkg/rep-fetch.cxx +++ b/bpkg/rep-fetch.cxx @@ -1496,7 +1496,7 @@ namespace bpkg ds.push_back (dependency_alternatives_ex (td.type, td.buildtime)); - dependency_alternatives_ex& da (ds.back ()); + dependency_alternatives_ex& das (ds.back ()); // Note that since we store all the primary packages as // alternative dependencies (which must be all of the same @@ -1507,18 +1507,36 @@ namespace bpkg // `== ` constraints (see below), so we can use min // version of such a constraint as the primary package version. // - if (da.buildtime != td.buildtime) + if (das.buildtime != td.buildtime) + { + // Could only be empty if we just added it, which cannot be the + // case since the build-time flag differs. + // + assert (!das.empty ()); + + const dependency_alternative& da (das[0]); + + // We always add the primary package to the test package as a + // single-dependency alternative (see below). + // + assert (da.size () == 1); + fail << to_string (td.type) << " package " << td.name << " is a " << "build-time dependency for one primary package and a " << "run-time for another" << - info << (da.buildtime ? "build-time for " : "run-time for ") + info << (das.buildtime ? "build-time for " : "run-time for ") << package_string (da[0].name, *da[0].constraint->min_version) << info << (td.buildtime ? "build-time for " : "run-time for ") << package_string (p->id.name, p->version); + } + + dependency_alternative da; + + da.push_back ( + dependency {p->id.name, version_constraint (p->version)}); - da.push_back (dependency {p->id.name, - version_constraint (p->version)}); + das.push_back (move (da)); db.update (tp); } -- cgit v1.1