From 00a83b2ab6ca84776dfb5bec1679863c1896a813 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 25 Aug 2021 20:24:57 +0300 Subject: Consider repository information from ultimate dependent databases rather then from just main database --- bpkg/database.hxx | 39 ++++ bpkg/forward.hxx | 4 + bpkg/package.cxx | 61 +++++-- bpkg/package.hxx | 13 +- bpkg/pkg-build.cxx | 444 +++++++++++++++++++++++++++++++-------------- bpkg/pkg-checkout.cxx | 54 +++--- bpkg/pkg-checkout.hxx | 10 +- bpkg/pkg-fetch.cxx | 20 +- bpkg/pkg-fetch.hxx | 6 +- bpkg/pkg-status.cxx | 34 +++- bpkg/pkg-unpack.cxx | 18 +- bpkg/pkg-unpack.hxx | 6 +- tests/pkg-build.testscript | 148 +++++++++++++-- 13 files changed, 619 insertions(+), 238 deletions(-) diff --git a/bpkg/database.hxx b/bpkg/database.hxx index c7f059d..bc3ac08 100644 --- a/bpkg/database.hxx +++ b/bpkg/database.hxx @@ -662,6 +662,45 @@ namespace bpkg { return static_cast (base_type::database ()); } + + // Map databases to values of arbitrary types. + // + // Note that keys are stored as non-constant references (since they are + // normally passed around as such), but they should never be changed + // directly. + // + template + class database_map: + public small_vector, V>, 16> + { + public: + using value_type = pair, V>; + using base_type = small_vector; + using iterator = typename base_type::iterator; + + using base_type::begin; + using base_type::end; + + iterator + find (database& db) + { + return find_if (begin (), end (), + [&db] (const value_type& i) -> bool + { + return i.first == db; + }); + } + + pair + insert (database& db, V&& v) + { + iterator i (find (db)); + if (i != end ()) + return make_pair (i, false); + + return make_pair (base_type::emplace (end (), db, move (v)), true); + } + }; } #endif // BPKG_DATABASE_HXX diff --git a/bpkg/forward.hxx b/bpkg/forward.hxx index 6b11024..ebf8cbd 100644 --- a/bpkg/forward.hxx +++ b/bpkg/forward.hxx @@ -6,6 +6,10 @@ namespace bpkg { + // + // + class database; + class linked_databases; class transaction; // diff --git a/bpkg/package.cxx b/bpkg/package.cxx index e0101fb..e458a86 100644 --- a/bpkg/package.cxx +++ b/bpkg/package.cxx @@ -217,13 +217,11 @@ namespace bpkg // assert (!prereq || chain.empty ()); - auto i (find_if (chain.begin (), chain.end (), - [&rf] (const shared_ptr& i) -> bool - { - return i == rf; - })); - - if (i != chain.end ()) + if (find_if (chain.begin (), chain.end (), + [&rf] (const shared_ptr& i) -> bool + { + return i == rf; + }) != chain.end ()) return nullptr; chain.emplace_back (rf); @@ -390,26 +388,55 @@ namespace bpkg } void - check_any_available (database& db, transaction&, const diag_record* dr) + check_any_available (const linked_databases& dbs, + transaction&, + const diag_record* drp) { - const dir_path& c (db.config_orig); + bool rep (false); + bool pkg (false); + for (database& db: dbs) + { + if (db.query_value () != 0) + { + rep = true; + + if (db.query_value () != 0) + { + pkg = true; + break; + } + } + } - if (db.query_value () == 0) + if (pkg) + return; + + diag_record d; + const diag_record& dr (drp != nullptr ? *drp << info : d << fail); + + if (dbs.size () == 1) + dr << "configuration " << dbs[0].get ().config_orig << " has "; + else + dr << "specified configurations have "; + + if (!rep) { - diag_record d; - (dr != nullptr ? *dr << info : d << fail) - << "configuration " << c << " has no repositories" << + dr << "no repositories" << info << "use 'bpkg rep-add' to add a repository"; } - else if (db.query_value () == 0) + else { - diag_record d; - (dr != nullptr ? *dr << info : d << fail) - << "configuration " << c << " has no available packages" << + dr << "no available packages" << info << "use 'bpkg rep-fetch' to fetch available packages list"; } } + void + check_any_available (database& db, transaction& t, const diag_record* dr) + { + return check_any_available (linked_databases ({db}), t, dr); + } + string package_string (const package_name& n, const version& v, bool system) { diff --git a/bpkg/package.hxx b/bpkg/package.hxx index 1c643b3..6256481 100644 --- a/bpkg/package.hxx +++ b/bpkg/package.hxx @@ -18,7 +18,7 @@ #include #include -#include // database, transaction +#include // database, linked_databases, transaction #include #include @@ -826,11 +826,16 @@ namespace bpkg odb::result&&, bool prereq = true); - // Check if there are packages available in the configuration. If that's not - // the case then print the info message into the diag record or, if it is - // NULL, print the error message and fail. + // Check if there are packages available in the specified configurations. If + // that's not the case then print the info message into the diag record or, + // if it is NULL, print the error message and fail. // void + check_any_available (const linked_databases&, + transaction&, + const diag_record* = nullptr); + + void check_any_available (database&, transaction&, const diag_record* = nullptr); // package_state diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index 60bdb08..a76e4e2 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -43,6 +43,74 @@ namespace bpkg // - Configuration vars (both passed and preserved) // + // Configurations to use as the repository information sources. + // + // The list contains the current configuration and configurations of the + // specified on the command line build-to-hold packages (ultimate + // dependents). + // + // For ultimate dependents we use configurations in which they are being + // built as a source of the repository information. For dependency packages + // we use configurations of their ultimate dependents. + // + static linked_databases repo_configs; + + // Return the ultimate dependent configurations for packages in this + // configuration. + // + static linked_databases + dependent_repo_configs (database& db) + { + linked_databases r; + for (database& ddb: db.dependent_configs ()) + { + if (find (repo_configs.begin (), repo_configs.end (), ddb) != + repo_configs.end ()) + r.push_back (ddb); + } + + return r; + } + + // Retrieve the repository fragments for the specified package from its + // ultimate dependent configurations and add them to the respective + // configuration-associated fragment lists. + // + using config_repo_fragments = + database_map>>; + + static void + add_dependent_repo_fragments (database& db, + const available_package_id& id, + config_repo_fragments& r) + { + for (database& ddb: dependent_repo_configs (db)) + { + shared_ptr dap (ddb.find (id)); + + if (dap != nullptr) + { + assert (!dap->locations.empty ()); + + config_repo_fragments::iterator i (r.find (ddb)); + + if (i == r.end ()) + i = r.insert (ddb, + vector> ()).first; + + vector>& rfs (i->second); + + for (const auto& pl: dap->locations) + { + shared_ptr rf (pl.repository_fragment.load ()); + + if (find (rfs.begin (), rfs.end (), rf) == rfs.end ()) + rfs.push_back (move (rf)); + } + } + } + } + // Try to find an available stub package in the imaginary system repository. // Such a repository contains stubs corresponding to the system packages // specified by the user on the command line with version information @@ -65,44 +133,76 @@ namespace bpkg return i != imaginary_stubs.end () ? *i : nullptr; } + // Sort the available package fragments in the package version descending + // order and suppress duplicate packages. + // + static void + sort_dedup (vector, + lazy_shared_ptr>>& pfs) + { + sort (pfs.begin (), pfs.end (), + [] (const auto& x, const auto& y) + { + return x.first->version > y.first->version; + }); + + pfs.erase (unique (pfs.begin(), pfs.end(), + [] (const auto& x, const auto& y) + { + return x.first->version == y.first->version; + }), + pfs.end ()); + } + // Try to find packages that optionally satisfy the specified version - // constraint. Return the list of packages and repository fragments in which - // each was found or empty list if none were found. Note that a stub - // satisfies any constraint. + // constraint in multiple databases, suppressing duplicates. Return the list + // of packages and repository fragments in which each was found in the + // package version descending or empty list if none were found. Note that a + // stub satisfies any constraint. + // + // Note that we return (loaded) lazy_shared_ptr in order to also convey + // the database to which it belongs. // static - vector, shared_ptr>> - find_available (database& db, + vector, + lazy_shared_ptr>> + find_available (const linked_databases& dbs, const package_name& name, const optional& c) { vector, - shared_ptr>> r; + lazy_shared_ptr>> r; - for (shared_ptr ap: - pointer_result (query_available (db, name, c))) + for (database& db: dbs) { - // An available package should come from at least one fetched - // repository fragment. - // - assert (!ap->locations.empty ()); + for (shared_ptr ap: + pointer_result (query_available (db, name, c))) + { + // An available package should come from at least one fetched + // repository fragment. + // + assert (!ap->locations.empty ()); - // All repository fragments the package comes from are equally good, so - // we pick the first one. - // - r.emplace_back (move (ap), - ap->locations[0].repository_fragment.load ()); + // All repository fragments the package comes from are equally good, so + // we pick the first one. + // + r.emplace_back (move (ap), ap->locations[0].repository_fragment); + } } + // If there are multiple databases specified, then sort the result in the + // package version descending order and suppress duplicates. + // + if (dbs.size () > 1) + sort_dedup (r); + // Adding a stub from the imaginary system repository to the non-empty // results isn't necessary but may end up with a duplicate. That's why we // only add it if nothing else is found. // if (r.empty ()) { - shared_ptr ap (find_imaginary_stub (name)); - - if (ap != nullptr) + if (shared_ptr ap = find_imaginary_stub (name)) r.emplace_back (move (ap), nullptr); } @@ -111,29 +211,38 @@ namespace bpkg // As above but only look for packages from the specified list of repository // fragments, their prerequisite repositories, and their complements, - // recursively (note: recursivity applies to complements, not - // prerequisites). + // recursively (note: recursivity applies to complements, not prerequisites). // static - vector, shared_ptr>> - find_available (database& db, - const package_name& name, + vector, + lazy_shared_ptr>> + find_available (const package_name& name, const optional& c, - const vector>& rfs, + const config_repo_fragments& rfs, bool prereq = true) { - // Filter the result based on the repository fragments to which each - // version belongs. - // vector, - shared_ptr>> r ( - filter (rfs, query_available (db, name, c), prereq)); + lazy_shared_ptr>> r; - if (r.empty ()) + for (const auto& dfs: rfs) { - shared_ptr ap (find_imaginary_stub (name)); + database& db (dfs.first); + for (auto& af: filter (dfs.second, + query_available (db, name, c), + prereq)) + { + r.emplace_back ( + move (af.first), + lazy_shared_ptr (db, move (af.second))); + } + } + + if (rfs.size () > 1) + sort_dedup (r); - if (ap != nullptr) + if (r.empty ()) + { + if (shared_ptr ap = find_imaginary_stub (name)) r.emplace_back (move (ap), nullptr); } @@ -146,22 +255,30 @@ namespace bpkg // prerequisites). Return the package and the repository fragment in which // it was found or NULL for both if not found. // - static pair, shared_ptr> - find_available_one (database& db, - const package_name& name, + // It is assumed that the repository fragment lazy pointer contains the + // database information. + // + static pair, + lazy_shared_ptr> + find_available_one (const package_name& name, const optional& c, - const shared_ptr& rf, + const lazy_shared_ptr& rf, bool prereq = true) { // Filter the result based on the repository fragment to which each // version belongs. // - auto r (filter_one (rf, query_available (db, name, c), prereq)); + database& db (rf.database ()); + auto r (filter_one (rf.load (), query_available (db, name, c), prereq)); if (r.first == nullptr) r.first = find_imaginary_stub (name); - return r; + return make_pair (r.first, + (r.second != nullptr + ? lazy_shared_ptr (db, + move (r.second)) + : nullptr)); } // As above but look for a single package from a list of repository @@ -185,6 +302,31 @@ namespace bpkg return r; } + // As above but look for a single package in multiple databases from their + // respective root repository fragments. + // + static pair, + lazy_shared_ptr> + find_available_one (const linked_databases& dbs, + const package_name& name, + const optional& c, + bool prereq = true) + { + for (database& db: dbs) + { + auto r (filter_one (db.load (""), + query_available (db, name, c), + prereq)); + + if (r.first != nullptr) + return make_pair ( + move (r.first), + lazy_shared_ptr (db, move (r.second))); + } + + return make_pair (find_imaginary_stub (name), nullptr); + } + // Create a transient (or fake, if you prefer) available_package object // corresponding to the specified selected object. Note that the package // locations list is left empty and that the returned repository fragment @@ -195,7 +337,8 @@ namespace bpkg // the package moves (e.g., from testing to stable), then we will be using // stable to resolve its dependencies. // - static pair, shared_ptr> + static pair, + lazy_shared_ptr> make_available (const common_options& options, database& db, const shared_ptr& sp) @@ -215,7 +358,7 @@ namespace bpkg // moment). // shared_ptr af ( - db.main_database ().find ( + db.find ( sp->repository_fragment.canonical_name ())); // The package is in at least fetched state, which means we should @@ -234,7 +377,10 @@ namespace bpkg // Copy potentially fixed up version from selected package. [&sp] (version& v) {v = sp->version;})); - return make_pair (make_shared (move (m)), move (af)); + return make_pair (make_shared (move (m)), + (af != nullptr + ? lazy_shared_ptr (db, move (af)) + : nullptr)); } // Return true if the version constraint represents the wildcard version. @@ -345,9 +491,11 @@ namespace bpkg shared_ptr selected; // NULL if not selected. shared_ptr available; // Can be NULL, fake/transient. - // Can be NULL (orphan) or root. + // Can be NULL (orphan) or root. If not NULL, then loaded from the + // repository configuration database, which may differ from the + // configuration the package is being built in. // - shared_ptr repository_fragment; + lazy_shared_ptr repository_fragment; const package_name& name () const @@ -934,11 +1082,10 @@ namespace bpkg })); const shared_ptr& ap (pkg.available); - const shared_ptr& af (pkg.repository_fragment); + const lazy_shared_ptr& af (pkg.repository_fragment); const package_name& name (ap->id.name); database& pdb (pkg.db); - database& mdb (pdb.main_database ()); for (const dependency_alternatives_ex& da: ap->dependencies) { @@ -1070,7 +1217,7 @@ namespace bpkg shared_ptr& dsp (spd.first); pair, - shared_ptr> rp; + lazy_shared_ptr> rp; shared_ptr& dap (rp.first); @@ -1122,15 +1269,11 @@ namespace bpkg // system package we pick the latest one (its exact version // doesn't really matter). // - shared_ptr root ( - mdb.load ("")); - - rp = system - ? find_available_one (mdb, dn, nullopt, root) - : find_available_one (mdb, - dn, - version_constraint (dsp->version), - root); + rp = find_available_one (dependent_repo_configs (*ddb), + dn, + (!system + ? version_constraint (dsp->version) + : optional ())); // A stub satisfies any version constraint so we weed them out // (returning stub as an available package feels wrong). @@ -1351,10 +1494,7 @@ namespace bpkg // the package is recognized. An unrecognized package means the // broken/stale repository (see below). // - rp = find_available_one (mdb, - dn, - !system ? d.constraint : nullopt, - af); + rp = find_available_one (dn, !system ? d.constraint : nullopt, af); if (dap == nullptr) { @@ -1431,7 +1571,7 @@ namespace bpkg *ddb, dsp, dap, - rp.second, + move (rp.second), nullopt, // Hold package. nullopt, // Hold version. {}, // Constraints. @@ -2435,11 +2575,13 @@ namespace bpkg // struct evaluate_result { - reference_wrapper db; - shared_ptr available; - shared_ptr repository_fragment; - bool unused; - bool system; // Is meaningless if unused. + // The system flag is meaningless if the unused flag is true. + // + reference_wrapper db; + shared_ptr available; + lazy_shared_ptr repository_fragment; + bool unused; + bool system; }; struct config_package_dependent @@ -2464,7 +2606,7 @@ namespace bpkg database& desired_db, bool patch, bool explicitly, - const set>&, + const config_repo_fragments&, const config_package_dependents&, bool ignore_unsatisfiable); @@ -2575,7 +2717,7 @@ namespace bpkg // from. Also cache the dependents and the constraints they apply to this // dependency. // - set> repo_frags; + config_repo_fragments repo_frags; config_package_dependents dependents; for (auto& pd: pds) @@ -2586,17 +2728,10 @@ namespace bpkg shared_ptr dsp ( ddb.load (dep.name)); - shared_ptr dap ( - mdb.find ( - available_package_id (dsp->name, dsp->version))); - - if (dap != nullptr) - { - assert (!dap->locations.empty ()); - - for (const auto& pl: dap->locations) - repo_frags.insert (pl.repository_fragment.load ()); - } + add_dependent_repo_fragments ( + ddb, + available_package_id (dsp->name, dsp->version), + repo_frags); dependents.emplace_back (ddb, move (dsp), move (dep.constraint)); } @@ -2644,7 +2779,7 @@ namespace bpkg database& ddb, bool patch, bool explicitly, - const set>& rfs, + const config_repo_fragments& rfs, const config_package_dependents& dependents, bool ignore_unsatisfiable) { @@ -2689,12 +2824,8 @@ namespace bpkg c = dvc; vector, - shared_ptr>> afs ( - find_available (db.main_database (), - nm, - c, - vector> (rfs.begin (), - rfs.end ()))); + lazy_shared_ptr>> afs ( + find_available (nm, c, rfs)); // Go through up/down-grade candidates and pick the first one that // satisfies all the dependents. Collect (and sort) unsatisfied dependents @@ -2985,7 +3116,7 @@ namespace bpkg // Also cache the dependents and the constraints they apply to this // dependency. // - set> repo_frags; + config_repo_fragments repo_frags; config_package_dependents dependents; // Only collect repository fragments (for best version selection) of @@ -2994,8 +3125,6 @@ namespace bpkg // optional upgrade; - database& mdb (db.main_database ()); - for (database& ddb: db.dependent_configs ()) { for (auto& pd: query_dependents_cache (ddb, sp->name, db)) @@ -3017,17 +3146,10 @@ namespace bpkg // continue to iterate over dependents, collecting the repository // fragments and the constraints. // - shared_ptr dap ( - mdb.find ( - available_package_id (dsp->name, dsp->version))); - - if (dap != nullptr) - { - assert (!dap->locations.empty ()); - - for (const auto& pl: dap->locations) - repo_frags.insert (pl.repository_fragment.load ()); - } + add_dependent_repo_fragments ( + ddb, + available_package_id (dsp->name, dsp->version), + repo_frags); } } @@ -3245,6 +3367,16 @@ namespace bpkg // duplicates. Note that the last repository location overrides the // previous ones with the same canonical name. // + // Also note that the dependency specs may not have the repository + // location specified, since they obtain the repository information via + // their ultimate dependent configurations. + // + // Also collect the databases specified on the command line for the held + // packages, to later use them as a repository information sources for the + // dependencies. + // + repo_configs.push_back (mdb); + struct pkg_spec { database* db; // A pointer since we build these objects incrementally. @@ -3299,7 +3431,7 @@ namespace bpkg fail << "configuration variables must be separated from packages " << "with '--'"; - vector locations; + database_map> locations; transaction t (mdb); @@ -3366,6 +3498,16 @@ namespace bpkg a.erase (0, 1); } + database& pdb (*ps.db); + + // If this is a package to hold, then add its database to the + // repository information source list, suppressing duplicates. + // + if (!ps.options.dependency () && + find (repo_configs.begin (), repo_configs.end (), pdb) == + repo_configs.end ()) + repo_configs.push_back (pdb); + // Check if the argument has the []@ form or looks // like a URL. Find the position of if that's the case and // set it to string::npos otherwise. @@ -3406,6 +3548,11 @@ namespace bpkg if (l.empty ()) fail << "empty repository location in '" << a << "'"; + if (ps.options.dependency ()) + fail << "unexpected repository location in '?" << a << "'" << + info << "repository location cannot be specified for " + << "dependencies"; + // Search for the repository location in the database before trying // to parse it. Note that the straight parsing could otherwise fail, // being unable to properly guess the repository type. @@ -3444,7 +3591,7 @@ namespace bpkg ( query::local && u + " COLLATE nocase = " + query::_val (l))); #endif - auto rs (mdb.query (q)); + auto rs (pdb.query (q)); auto i (rs.begin ()); if (i != rs.end ()) @@ -3468,17 +3615,23 @@ namespace bpkg if (!o.no_fetch ()) { + auto i (locations.find (pdb)); + if (i == locations.end ()) + i = locations.insert (pdb, + vector ()).first; + auto pr = [&ps] (const repository_location& i) -> bool { return i.canonical_name () == ps.location.canonical_name (); }; - auto i (find_if (locations.begin (), locations.end (), pr)); + vector& ls (i->second); + auto j (find_if (ls.begin (), ls.end (), pr)); - if (i != locations.end ()) - *i = ps.location; + if (j != ls.end ()) + *j = ps.location; else - locations.push_back (ps.location); + ls.push_back (ps.location); } } else @@ -3492,10 +3645,10 @@ namespace bpkg // Note that during this build only the repositories information from // the main database will be used. // - if (!locations.empty ()) + for (const auto& l: locations) rep_fetch (o, - mdb, - locations, + l.first, + l.second, o.fetch_shallow (), string () /* reason for "fetching ..." */); } @@ -3780,16 +3933,21 @@ namespace bpkg continue; } + // Use it both as the package database and the source of the + // repository information. + // + database& pdb (*ps.db); + // Expand the [[]@] spec. Fail if the repository // is not found in this configuration, that can be the case in the // presence of --no-fetch option. // shared_ptr r ( - mdb.find (ps.location.canonical_name ())); + pdb.find (ps.location.canonical_name ())); if (r == nullptr) - fail << "repository '" << ps.location - << "' does not exist in this configuration"; + fail << "repository '" << ps.location << "' does not exist in this " + << "configuration"; // If no packages are specified explicitly (the argument starts with // '@' or is a URL) then we select latest versions of all the packages @@ -3808,7 +3966,7 @@ namespace bpkg { using query = query; - for (const auto& rp: mdb.query ( + for (const auto& rp: pdb.query ( (query::repository_fragment::name == rf.fragment.load ()->name) + order_by_version_desc (query::package::id.version))) @@ -3823,7 +3981,7 @@ namespace bpkg if (ps.options.patch ()) { shared_ptr sp ( - ps.db->find (nm)); + pdb.find (nm)); // It seems natural in the presence of --patch option to only // patch the selected packages and not to build new packages if @@ -3874,7 +4032,7 @@ namespace bpkg info << "package " << pv.first << " is not present in " << "configuration"; else - pkg_args.push_back (arg_package (*ps.db, + pkg_args.push_back (arg_package (pdb, package_scheme::none, pv.first, version_constraint (pv.second), @@ -3931,8 +4089,6 @@ namespace bpkg optional c; shared_ptr sp; - database& pdb (*ps.db); - if (!sys) { if (!vc) @@ -3954,7 +4110,7 @@ namespace bpkg } shared_ptr ap ( - find_available_one (mdb, n, c, rfs, false /* prereq */).first); + find_available_one (pdb, n, c, rfs, false /* prereq */).first); // Fail if no available package is found or only a stub is // available and we are building a source package. @@ -3991,7 +4147,7 @@ namespace bpkg // Don't move options and variables as they may be reused. // - pkg_args.push_back (arg_package (*ps.db, + pkg_args.push_back (arg_package (pdb, sc, move (n), move (vc), @@ -4057,9 +4213,6 @@ namespace bpkg transaction t (mdb); - shared_ptr root ( - mdb.load ("")); - // Here is what happens here: for unparsed package args we are going to // try and guess whether we are dealing with a package archive, package // directory, or package name/version by first trying it as an archive, @@ -4076,10 +4229,15 @@ namespace bpkg pkg_arg& pa (*i); database& pdb (pa.db); + lazy_shared_ptr root (pdb, empty_string); + // Reduce all the potential variations (archive, directory, package // name, package name/version) to a single available_package object. // - shared_ptr af; + // Note that the repository fragment is only used for the + // build-to-hold packages. + // + lazy_shared_ptr af; shared_ptr ap; if (!arg_parsed (pa)) @@ -4322,7 +4480,8 @@ namespace bpkg else if (!arg_sys (pa)) c = pa.constraint; - auto rp (find_available_one (mdb, pa.name, c, root)); + auto rp (find_available_one (pa.name, c, root)); + ap = move (rp.first); af = move (rp.second); } @@ -4376,16 +4535,15 @@ namespace bpkg // Make sure that the package is known. // - auto apr (!pa.constraint || sys - ? find_available (mdb, pa.name, nullopt) - : find_available (mdb, pa.name, *pa.constraint)); + auto apr (find_available (repo_configs, + pa.name, + !sys ? pa.constraint : nullopt)); if (apr.empty ()) { diag_record dr (fail); - dr << "unknown package " << arg_string (pa, false /* options */); - check_any_available (mdb, t, &dr); + check_any_available (repo_configs, t, &dr); } // Save before the name move. @@ -4446,10 +4604,7 @@ namespace bpkg if (ap == nullptr) { if (pa.constraint && - find_available_one (mdb, - pa.name, - nullopt, - root).first != nullptr) + find_available_one (pa.name, nullopt, root).first != nullptr) sys_advise = true; } else if (ap->stub ()) @@ -4528,7 +4683,7 @@ namespace bpkg // Let's help the new user out here a bit. // - check_any_available (mdb, t, &dr); + check_any_available (pdb, t, &dr); } else { @@ -4618,6 +4773,8 @@ namespace bpkg if (hold_pkgs.empty () && dep_pkgs.empty () && (o.upgrade () || o.patch ())) { + lazy_shared_ptr root (mdb, empty_string); + using query = query; for (shared_ptr sp: @@ -4645,7 +4802,7 @@ namespace bpkg continue; } - auto apr (find_available_one (mdb, name, pc, root)); + auto apr (find_available_one (name, pc, root)); shared_ptr ap (move (apr.first)); if (ap == nullptr || ap->stub ()) @@ -4800,15 +4957,15 @@ namespace bpkg { struct dep { - reference_wrapper db; - package_name name; // Empty if up/down-grade. + reference_wrapper db; + package_name name; // Empty if up/down-grade. // Both are NULL if drop. // - shared_ptr available; - shared_ptr repository_fragment; + shared_ptr available; + lazy_shared_ptr repository_fragment; - bool system; + bool system; }; vector deps; @@ -6130,6 +6287,7 @@ namespace bpkg shared_ptr& sp (p.selected); const shared_ptr& ap (p.available); + const lazy_shared_ptr& af (p.repository_fragment); // Purge the dropped or system package, fetch/unpack or checkout the // other one. @@ -6243,6 +6401,7 @@ namespace bpkg { sp = pkg_fetch (o, pdb, + af.database (), t, ap->id.name, p.available_version (), @@ -6256,6 +6415,7 @@ namespace bpkg ? pkg_checkout (checkout_cache, o, pdb, + af.database (), t, ap->id.name, p.available_version (), @@ -6266,6 +6426,7 @@ namespace bpkg : pkg_checkout (checkout_cache, o, pdb, + af.database (), t, ap->id.name, p.available_version (), @@ -6277,6 +6438,7 @@ namespace bpkg { sp = pkg_unpack (o, pdb, + af.database (), t, ap->id.name, p.available_version (), diff --git a/bpkg/pkg-checkout.cxx b/bpkg/pkg-checkout.cxx index 94dd19b..d8c6819 100644 --- a/bpkg/pkg-checkout.cxx +++ b/bpkg/pkg-checkout.cxx @@ -89,7 +89,8 @@ namespace bpkg static shared_ptr pkg_checkout (pkg_checkout_cache& cache, const common_options& o, - database& db, + database& pdb, + database& rdb, transaction& t, package_name n, version v, @@ -100,13 +101,13 @@ namespace bpkg { tracer trace ("pkg_checkout"); - tracer_guard tg (db, trace); + tracer_guard tg (pdb, trace); // NOTE: sets tracer for the whole cluster. - const dir_path& c (db.config_orig); + const dir_path& c (pdb.config_orig); // See if this package already exists in this configuration. // - shared_ptr p (db.find (n)); + shared_ptr p (pdb.find (n)); if (p != nullptr) { @@ -127,15 +128,13 @@ namespace bpkg } } - database& mdb (db.main_database ()); - - check_any_available (mdb, t); + check_any_available (rdb, t); // Note that here we compare including the revision (see pkg-fetch() // implementation for more details). // shared_ptr ap ( - mdb.find (available_package_id (n, v))); + rdb.find (available_package_id (n, v))); if (ap == nullptr) fail << "package " << n << " " << v << " is not available"; @@ -190,7 +189,7 @@ namespace bpkg // if the previous checkout have failed or been interrupted. // dir_path sd (repository_state (rl)); - dir_path rd (mdb.config_orig / repos_dir / sd); + dir_path rd (rdb.config_orig / repos_dir / sd); // Try to reuse the cached repository (moved to the temporary directory // with some fragment checked out and fixed up). @@ -209,7 +208,8 @@ namespace bpkg // if (!exists (rd)) fail << "missing repository directory for package " << n << " " << v - << " in configuration " << c << + << " in its repository information configuration " + << rdb.config_orig << info << "run 'bpkg rep-fetch' to repair"; // The repository temporary directory. @@ -241,7 +241,7 @@ namespace bpkg state& s (i->second); const dir_path& td (s.rmt.path); - checkout (o, rl, td, ap, db); + checkout (o, rl, td, ap, pdb); s.fixedup = fixup (o, rl, td); } @@ -292,7 +292,7 @@ namespace bpkg // build system's actual progress. // if (verb == 1 && !o.no_progress ()) - text << "distributing " << n << '/' << v << db; + text << "distributing " << n << '/' << v << pdb; run_b (o, verb_b::progress, @@ -310,7 +310,7 @@ namespace bpkg // replacing. Once this is done, there is no going back. If things go // badly, we can't simply abort the transaction. // - pkg_purge_fs (db, t, p, simulate); + pkg_purge_fs (pdb, t, p, simulate); // Note that if the package name spelling changed then we need to update // it, to make sure that the subsequent commands don't fail and the @@ -319,7 +319,7 @@ namespace bpkg // if (p->name.string () != n.string ()) { - db.erase (p); + pdb.erase (p); p = nullptr; } } @@ -330,8 +330,8 @@ namespace bpkg // normalize (d, "package"); - if (d.sub (db.config)) - d = d.leaf (db.config); + if (d.sub (pdb.config)) + d = d.leaf (pdb.config); if (p != nullptr) { @@ -342,7 +342,7 @@ namespace bpkg p->purge_src = purge; p->manifest_checksum = move (mc); - db.update (p); + pdb.update (p); } else { @@ -364,7 +364,7 @@ namespace bpkg nullopt, // No output directory yet. {}}); // No prerequisites captured yet. - db.persist (p); + pdb.persist (p); } t.commit (); @@ -376,7 +376,8 @@ namespace bpkg shared_ptr pkg_checkout (pkg_checkout_cache& cache, const common_options& o, - database& db, + database& pdb, + database& rdb, transaction& t, package_name n, version v, @@ -387,7 +388,8 @@ namespace bpkg { return pkg_checkout (cache, o, - db, + pdb, + rdb, t, move (n), move (v), @@ -400,7 +402,8 @@ namespace bpkg shared_ptr pkg_checkout (pkg_checkout_cache& cache, const common_options& o, - database& db, + database& pdb, + database& rdb, transaction& t, package_name n, version v, @@ -409,7 +412,8 @@ namespace bpkg { return pkg_checkout (cache, o, - db, + pdb, + rdb, t, move (n), move (v), @@ -452,7 +456,8 @@ namespace bpkg if (o.output_root_specified ()) p = pkg_checkout (checkout_cache, o, - db, + db /* pdb */, + db /* rdb */, t, move (n), move (v), @@ -463,7 +468,8 @@ namespace bpkg else p = pkg_checkout (checkout_cache, o, - db, + db /* pdb */, + db /* rdb */, t, move (n), move (v), diff --git a/bpkg/pkg-checkout.hxx b/bpkg/pkg-checkout.hxx index d910509..b775b07 100644 --- a/bpkg/pkg-checkout.hxx +++ b/bpkg/pkg-checkout.hxx @@ -76,6 +76,10 @@ namespace bpkg erase (state_map::iterator, bool ignore_errors = false); }; + // Note that for the following functions both package and repository + // information configurations need to be passed. + // + // Check out the package from a version control-based repository into a // directory other than the configuration directory and commit the // transaction. Return the selected package object which may replace the @@ -84,7 +88,8 @@ namespace bpkg shared_ptr pkg_checkout (pkg_checkout_cache&, const common_options&, - database&, + database& pdb, + database& rdb, transaction&, package_name, version, @@ -100,7 +105,8 @@ namespace bpkg shared_ptr pkg_checkout (pkg_checkout_cache&, const common_options&, - database&, + database& pdb, + database& rdb, transaction&, package_name, version, diff --git a/bpkg/pkg-fetch.cxx b/bpkg/pkg-fetch.cxx index 5155092..ab67ffe 100644 --- a/bpkg/pkg-fetch.cxx +++ b/bpkg/pkg-fetch.cxx @@ -185,7 +185,8 @@ namespace bpkg shared_ptr pkg_fetch (const common_options& co, - database& db, + database& pdb, + database& rdb, transaction& t, package_name n, version v, @@ -194,15 +195,13 @@ namespace bpkg { tracer trace ("pkg_fetch"); - tracer_guard tg (db, trace); + tracer_guard tg (pdb, trace); // NOTE: sets tracer for the whole cluster. // Check/diagnose an already existing package. // - pkg_fetch_check (db, t, n, replace); + pkg_fetch_check (pdb, t, n, replace); - database& mdb (db.main_database ()); - - check_any_available (mdb, t); + check_any_available (rdb, t); // Note that here we compare including the revision (unlike, say in // pkg-status). Which means one cannot just specify 1.0.0 and get 1.0.0+1 @@ -210,7 +209,7 @@ namespace bpkg // a low-level command where some extra precision doesn't hurt. // shared_ptr ap ( - mdb.find (available_package_id (n, v))); + rdb.find (available_package_id (n, v))); if (ap == nullptr) fail << "package " << n << " " << v << " is not available"; @@ -242,7 +241,7 @@ namespace bpkg << "from " << pl->repository_fragment->name; auto_rmfile arm; - path a (db.config_orig / pl->location.leaf ()); + path a (pdb.config_orig / pl->location.leaf ()); if (!simulate) { @@ -268,7 +267,7 @@ namespace bpkg } shared_ptr p ( - pkg_fetch (db, + pkg_fetch (pdb, t, move (n), move (v), @@ -326,7 +325,8 @@ namespace bpkg info << "run 'bpkg help pkg-fetch' for more information"; p = pkg_fetch (o, - db, + db /* pdb */, + db /* rdb */, t, move (n), move (v), diff --git a/bpkg/pkg-fetch.hxx b/bpkg/pkg-fetch.hxx index 9dd53f6..5d698d5 100644 --- a/bpkg/pkg-fetch.hxx +++ b/bpkg/pkg-fetch.hxx @@ -34,9 +34,13 @@ namespace bpkg // transaction. Return the selected package object which may replace the // existing one. // + // Note that both package and repository information configurations need to + // be passed. + // shared_ptr pkg_fetch (const common_options&, - database&, + database& pdb, + database& rdb, transaction&, package_name, version, diff --git a/bpkg/pkg-status.cxx b/bpkg/pkg-status.cxx index b038f1d..a376d38 100644 --- a/bpkg/pkg-status.cxx +++ b/bpkg/pkg-status.cxx @@ -18,7 +18,8 @@ namespace bpkg { struct package { - database& db; + database& pdb; // Package database. + database& rdb; // Repository info database. package_name name; bpkg::version version; // Empty if unspecified. shared_ptr selected; // NULL if none selected. @@ -42,6 +43,9 @@ namespace bpkg { l4 ([&]{trace << "package " << p.name << "; version " << p.version;}); + database& pdb (p.pdb); + database& rdb (p.rdb); + // Can't be both. // assert (p.version.empty () || !p.constraint); @@ -59,8 +63,6 @@ namespace bpkg }; vector apkgs; - database& mdb (p.db.main_database ()); - // A package with this name is known in available packages potentially // for build. // @@ -68,13 +70,13 @@ namespace bpkg bool build (false); { shared_ptr root ( - mdb.load ("")); + rdb.load ("")); using query = query; query q (query::id.name == p.name); { - auto r (mdb.query (q)); + auto r (rdb.query (q)); known = !r.empty (); build = filter_one (root, move (r)).first != nullptr; } @@ -109,7 +111,7 @@ namespace bpkg // for (shared_ptr ap: pointer_result ( - mdb.query (q))) + rdb.query (q))) { bool build (filter (root, ap)); apkgs.push_back (apkg {move (ap), build}); @@ -132,7 +134,7 @@ namespace bpkg // If the package name is selected, then print its exact spelling. // - cout << (s != nullptr ? s->name : p.name) << p.db; + cout << (s != nullptr ? s->name : p.name) << pdb; if (o.constraint () && p.constraint) cout << ' ' << *p.constraint; @@ -231,6 +233,9 @@ namespace bpkg { // Collect and recurse. // + // Let's propagate the repository information source database from the + // dependent to its prerequisites. + // packages dpkgs; if (s != nullptr) { @@ -239,7 +244,8 @@ namespace bpkg shared_ptr d (pair.first.load ()); database& db (pair.first.database ()); const optional& c (pair.second); - dpkgs.push_back (package {db, d->name, version (), move (d), c}); + dpkgs.push_back ( + package {db, rdb, d->name, version (), move (d), c}); } } @@ -268,6 +274,13 @@ namespace bpkg transaction t (db); session s; + // Let's use as repository information source the package database for the + // held packages and the current database for the dependency packages. + // + // For the dependency packages we should probably use their dependent held + // package configurations recursively, but feels a bit hairy at the + // moment. So let's keep it simple for now. @@ TODO. + // packages pkgs; { using query = query; @@ -303,6 +316,7 @@ namespace bpkg if (sp != nullptr) { pkgs.push_back (package {ldb, + sp->hold_package ? ldb : db, pn, pv, move (sp), @@ -314,6 +328,7 @@ namespace bpkg if (!found) { pkgs.push_back (package {db, + db, move (pn), move (pv), nullptr /* selected */, @@ -333,12 +348,11 @@ namespace bpkg ldb.query (query::hold_package))) { pkgs.push_back (package {ldb, + s->hold_package ? ldb : db, s->name, version (), move (s), nullopt /* constraint */}); - - } } diff --git a/bpkg/pkg-unpack.cxx b/bpkg/pkg-unpack.cxx index 04250f8..862feac 100644 --- a/bpkg/pkg-unpack.cxx +++ b/bpkg/pkg-unpack.cxx @@ -214,7 +214,8 @@ namespace bpkg shared_ptr pkg_unpack (const common_options& o, - database& db, + database& pdb, + database& rdb, transaction& t, package_name n, version v, @@ -223,21 +224,19 @@ namespace bpkg { tracer trace ("pkg_unpack"); - tracer_guard tg (db, trace); + tracer_guard tg (pdb, trace); // NOTE: sets tracer for the whole cluster. // Check/diagnose an already existing package. // - pkg_unpack_check (db, t, n, replace); - - database& mdb (db.main_database ()); + pkg_unpack_check (pdb, t, n, replace); - check_any_available (mdb, t); + check_any_available (rdb, t); // Note that here we compare including the revision (see pkg-fetch() // implementation for more details). // shared_ptr ap ( - mdb.find (available_package_id (n, v))); + rdb.find (available_package_id (n, v))); if (ap == nullptr) fail << "package " << n << " " << v << " is not available"; @@ -267,7 +266,7 @@ namespace bpkg const repository_location& rl (pl->repository_fragment->location); return pkg_unpack (o, - db, + pdb, t, move (n), move (v), @@ -417,7 +416,8 @@ namespace bpkg p = v.empty () ? pkg_unpack (o, db, t, n, false /* simulate */) : pkg_unpack (o, - db, + db /* pdb */, + db /* rdb */, t, move (n), move (v), diff --git a/bpkg/pkg-unpack.hxx b/bpkg/pkg-unpack.hxx index c6496d6..7394732 100644 --- a/bpkg/pkg-unpack.hxx +++ b/bpkg/pkg-unpack.hxx @@ -43,9 +43,13 @@ namespace bpkg // repository and commit the transaction. Return the selected package object // which may replace the existing one. // + // Note that both package and repository information configurations need to + // be passed. + // shared_ptr pkg_unpack (const common_options&, - database&, + database& pdb, + database& rdb, transaction&, package_name, version, diff --git a/tests/pkg-build.testscript b/tests/pkg-build.testscript index b316094..3b4bf5c 100644 --- a/tests/pkg-build.testscript +++ b/tests/pkg-build.testscript @@ -561,7 +561,7 @@ test.options += --no-progress $cfg_create -d cfg2 &cfg2/***; $cfg_link -d cfg cfg2; - $* libbar/1.1.0 +{ --config-id 1 } >>~%EOO% + $* "libbar/1.1.0@$rep/t4e" +{ --config-id 1 } --trust-yes >>~%EOO% 2>! %new libfoo/1.1.0\+1 \[cfg2.\] \(required by libbar \[cfg2.\]\)% %new libbar/1.1.0 \[cfg2.\]% EOO @@ -816,6 +816,7 @@ test.options += --no-progress $clone_cfg; $cfg_create -d cfg2 &cfg2/***; $cfg_link -d cfg cfg2; + $rep_add -d cfg2 $rep/t4c && $rep_fetch -d cfg2; $* libbaz ?libbar +{ --config-id 1 } libfoo/1.0.0 +{ --config-id 1 } 2>>~%EOE% != 0 error: unable to satisfy constraints on package libfoo info: command line depends on (libfoo == 1.0.0) @@ -1279,6 +1280,7 @@ test.options += --no-progress $clone_cfg; $cfg_create -d cfg2 &cfg2/***; $cfg_link -d cfg cfg2; + $rep_fetch -d cfg2 $rep/t4c; $* libfoo/1.0.0 +{ --config-id 1 } 2>>~%EOE%; %fetched libfoo/1.0.0 \[cfg2.\]% @@ -1288,7 +1290,7 @@ test.options += --no-progress %updated libfoo/1.0.0 \[cfg2.\]% EOE - $pkg_status -d cfg2 libfoo >'!libfoo configured !1.0.0'; + $pkg_status -d cfg2 libfoo >'!libfoo configured !1.0.0 available [1.1.0]'; $* libbaz ?libbar +{ --config-id 1 } 2>>~%EOE% != 0; %error: package libbar \[cfg2.\] dependency on \(libfoo == 1.1.0\) is forcing upgrade of libfoo/1.0.0 \[cfg2.\] to 1.1.0% @@ -1633,7 +1635,7 @@ test.options += --no-progress $* libfoo '?sys:libhello' 2>'error: unknown package sys:libhello' != 0; - $* "?sys:libhello/2.0@$rep/t0a" --trust-yes 2>>~%EOE% != 0; + $* "sys:libhello/2.0@$rep/t0a" --trust-yes 2>>~%EOE% != 0; %.+ %error: package sys:libhello/2\.0 is not found in .+t0a% EOE @@ -3090,9 +3092,9 @@ test.options += --no-progress cp -r $src/libfoo-1.1.0/ libfoo; echo "depends: libfoo" >+ libfoo/manifest; - $rep_add libfoo --type dir; + $rep_add libfoo --type dir -d cfg2; - $rep_fetch; + $rep_fetch -d cfg2; $* libfoo +{ --config-id 1 } 2>>~%EOE% != 0 %error: dependency cycle detected involving package libfoo \[cfg2.\]% @@ -3775,6 +3777,38 @@ test.options += --no-progress $pkg_disfigure libfoo 2>'disfigured libfoo/1.1.0'; $pkg_purge libfoo 2>'purged libfoo/1.1.0' } + + : preferred-config + : + : As above but with a linked configuration. + : + { + $clone_root_cfg; + + $cfg_create -d cfg2 &cfg2/***; + $cfg_link -d cfg cfg2; + + $rep_fetch -d cfg2 $rep/t4a; + $rep_add -d cfg2 $src/libfoo-1.1.0 --type dir; + + d = $canonicalize([dir_path] $src/libfoo-1.1.0); + + if! $posix + d = [dir_path] $string.lcase($d) + end; + + $rep_fetch -d cfg2 "dir:$d"; + + $* libfoo +{ --config-id 1 } 2>>~%EOE%; + %using libfoo/1.1.0 \[cfg2.\] \(external\)% + %configured libfoo/1.1.0 \[cfg2.\]% + %info: .+ is up to date% + %updated libfoo/1.1.0 \[cfg2.\]% + EOE + + $pkg_disfigure -d cfg2 libfoo 2>'disfigured libfoo/1.1.0'; + $pkg_purge -d cfg2 libfoo 2>'purged libfoo/1.1.0' + } } : keep-out @@ -4119,6 +4153,38 @@ else $pkg_purge style-basic } + : prerequisite-repo-config + : + : As above but with a linked configuration. + : + { + $clone_root_cfg; + $rep_add "$rep0/libbar.git#master"; + $rep_fetch &cfg/.bpkg/repos/*/***; + + $cfg_create -d cfg2 &cfg2/***; + $cfg_link -d cfg cfg2; + + $rep_add -d cfg2 "$rep0/style-basic.git#master"; + $rep_fetch -d cfg2 &cfg/.bpkg/repos/*/***; + + $* libmbar style-basic +{ --config-id 1 } 2>>~%EOE%; + %checked out style-basic/.+ \[cfg2.\]% + checked out libmbar/1.0.0 + %configured style-basic/.+ \[cfg2.\]% + configured libmbar/1.0.0 + %info: .+ is up to date%{2} + %updated style-basic/.+ \[cfg2.\]% + updated libmbar/1.0.0 + EOE + + $pkg_disfigure libmbar; + $pkg_disfigure -d cfg2 style-basic; + + $pkg_purge libmbar; + $pkg_purge -d cfg2 style-basic + } + : no-prerequisite-repos : : Dependent package repository has no prerequisites nor complements. Its @@ -4173,6 +4239,34 @@ else $pkg_disfigure style-basic } + : build-unpacked-config + : + : As above but with a linked configuration. + : + if! $remote + { + $clone_root_cfg; + + $cfg_create -d cfg2 &cfg2/***; + $cfg_link -d cfg cfg2; + + d = $canonicalize([dir_path] $out_git/state0/style-basic.git); + $pkg_unpack -d cfg2 -e $d; + + $* style-basic +{ --config-id 1 } 2>>~%EOE%; + %configured style-basic/1\.1\.0-a\.0\.\d+\..+% + %info: .+ is up to date% + %updated style-basic/1\.1\.0-a\.0\.\d+\..+% + EOE + + $* $d +{ --config-id 1 } 2>>~%EOE%; + %info: .+ is up to date% + %updated style-basic/1\.1\.0-a\.0\.\d+\..+% + EOE + + $pkg_disfigure -d cfg2 style-basic + } + : checkout-root : { @@ -4551,7 +4645,7 @@ else $cfg_create -d cfg3 --type host &cfg3/***; $cfg_link -d cfg2 cfg3; - $rep_add -d cfg2 $rep/t7a && $rep_fetch -d cfg2; + $rep_add -d cfg3 $rep/t7a && $rep_fetch -d cfg3; $* -d cfg2 libbaz +{ --config-id 2 } 2>!; @@ -4806,6 +4900,8 @@ else !libbaz configured 1.0.0 EOO + $rep_add -d t2 $rep/t7a && $rep_fetch -d t2; + $* -d t1 libbaz +{ --config-name t2 } 2>>~%EOE%; %fetched libbaz/1.0.0 \[t2.\]% %unpacked libbaz/1.0.0 \[t2.\]% @@ -4859,6 +4955,8 @@ else !libbaz configured 1.0.0 EOO + $rep_add -d t2 $rep/t7a && $rep_fetch -d t2; + $* -d t1 foo libbaz +{ --config-name t2 } <>~%EOE%; y EOI @@ -5074,6 +5172,8 @@ else libbuild2-bar [t1/.bpkg/build2/] configured 1.0.0 EOO + $rep_add -d t2 $rep/t7a && $rep_fetch -d t2; + $* -d t1 libbaz +{ --config-name t2 } <>~%EOE%; y y @@ -5120,6 +5220,8 @@ else libbuild2-bar [t1/.bpkg/build2/] configured 1.0.0 EOO + $rep_add -d t2 $rep/t7a && $rep_fetch -d t2; + $* -d t1 ?foo libbaz +{ --config-name t2 } <>~%EOE%; y EOI @@ -5163,6 +5265,8 @@ else libbuild2-bar [h1/.bpkg/build2/] configured 1.0.0 EOO + $rep_add -d h2 $rep/t7a && $rep_fetch -d h2; + $* -d h1 libbar libbaz +{ --config-name h2 } <>~%EOE%; y EOI @@ -5305,6 +5409,8 @@ else $rep_remove -d h1 $rep/t7b; $rep_add -d h1 $rep/t7a && $rep_fetch -d h1; + $rep_add -d h2 $rep/t7a && $rep_fetch -d h2; + $* -d h1 libbaz +{ --config-name h2 } 2>>EOE != 0 error: package foo/1.1.0 is orphaned info: explicitly upgrade it to a new version @@ -5330,6 +5436,8 @@ else libbuild2-bar [h1/.bpkg/build2/] configured 1.0.0 EOO + $rep_add -d h2 $rep/t7a && $rep_fetch -d h2; + $* -d h1 libbar ?foo libbaz +{ --config-name h2 } <>~%EOE%; y EOI @@ -5587,7 +5695,7 @@ else $cfg_link -d t1 t2 2>!; - $rep_add -d t1 $rep/t7b && $rep_fetch -d t1; + $rep_add -d t2 $rep/t7b && $rep_fetch -d t2; $* -d t1 libbaz +{ --config-name t2 } <>~%EOE%; y @@ -5611,9 +5719,9 @@ else EOE $pkg_status -d t1 -r >>/EOO - !libbar configured 1.0.0 available 1.1.0 - foo [t1/.bpkg/host/] configured 1.0.0 available 1.1.0 - libbaz [t1/.bpkg/host/] configured 1.0.0 available 1.1.0 + !libbar configured 1.0.0 + foo [t1/.bpkg/host/] configured 1.0.0 + libbaz [t1/.bpkg/host/] configured 1.0.0 libbuild2-bar [t1/.bpkg/build2/] configured 1.0.0 !libbaz [t2/] configured 1.1.0 !libbaz [t2/] configured 1.1.0 @@ -5641,7 +5749,7 @@ else $cfg_link -d t1 t2 2>!; - $rep_add -d t1 $rep/t7b && $rep_fetch -d t1; + $rep_add -d t2 $rep/t7b && $rep_fetch -d t2; $* -d t1 libbar +{ --config-name t2 } <>~%EOE%; y @@ -5667,11 +5775,11 @@ else EOE $pkg_status -d t1 -r >>/EOO - !libbar configured 1.0.0 available 1.1.0 - foo [t1/.bpkg/host/] configured 1.0.0 available 1.1.0 - libbaz [t1/.bpkg/host/] configured 1.0.0 available 1.1.0 + !libbar configured 1.0.0 + foo [t1/.bpkg/host/] configured 1.0.0 + libbaz [t1/.bpkg/host/] configured 1.0.0 libbuild2-bar [t1/.bpkg/build2/] configured 1.0.0 - libbaz configured 1.0.0 available 1.1.0 + libbaz configured 1.0.0 !libbar [t2/] configured 1.1.0 foo [t2/.bpkg/host/] configured 1.1.0 libbaz [t2/.bpkg/host/] configured 1.1.0 @@ -5710,6 +5818,8 @@ else EOO $rep_add -d t1 $rep/t7b && $rep_fetch -d t1; + $rep_add -d t2 $rep/t7b && $rep_fetch -d t2; + $rep_add -d h1 $rep/t7b && $rep_fetch -d h1; $* -d t1 libfix libfax +{ --config-name t2 } foo +{ --config-name h1 } <>~%EOE%; y @@ -5908,7 +6018,6 @@ else : { $cfg_create -d cfg &cfg/***; - $rep_add $rep/t7a && $rep_fetch; $cfg_create -d cfg2 --name cfg2 &cfg2/***; $cfg_link -d cfg cfg2; @@ -5916,10 +6025,11 @@ else $cfg_create -d cfg3 --name cfg3 &cfg3/***; $cfg_link -d cfg cfg3; - $* libbiz +{ --config-name cfg2 } --yes 2>!; - $* libbuz +{ --config-name cfg3 } --yes 2>!; + $* "libbiz@$rep/t7a" +{ --config-name cfg2 } --yes --trust-yes 2>!; + $* "libbuz@$rep/t7a" +{ --config-name cfg3 } --yes --trust-yes 2>!; - $* libbix 2>>/~%EOE% != 0 + $* "libbix@$rep/t7a" --trust-yes 2>>/~%EOE% != 0 + %(added|fetching).+%{2} error: building build system module libbuild2-bar in multiple configurations % info: cfg(2|3)/.bpkg/build2/%{2} EOE -- cgit v1.1