aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2021-08-25 20:24:57 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2021-08-30 15:57:58 +0300
commit00a83b2ab6ca84776dfb5bec1679863c1896a813 (patch)
tree5d0e1a96fb5ab5ba1bb32620c1eb265fc519d122
parente30e71dee35d8e7b1a1c4759bc839533521033e8 (diff)
Consider repository information from ultimate dependent databases rather then from just main database
-rw-r--r--bpkg/database.hxx39
-rw-r--r--bpkg/forward.hxx4
-rw-r--r--bpkg/package.cxx61
-rw-r--r--bpkg/package.hxx13
-rw-r--r--bpkg/pkg-build.cxx444
-rw-r--r--bpkg/pkg-checkout.cxx54
-rw-r--r--bpkg/pkg-checkout.hxx10
-rw-r--r--bpkg/pkg-fetch.cxx20
-rw-r--r--bpkg/pkg-fetch.hxx6
-rw-r--r--bpkg/pkg-status.cxx34
-rw-r--r--bpkg/pkg-unpack.cxx18
-rw-r--r--bpkg/pkg-unpack.hxx6
-rw-r--r--tests/pkg-build.testscript148
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<bpkg::database&> (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 <typename V>
+ class database_map:
+ public small_vector<pair<reference_wrapper<database>, V>, 16>
+ {
+ public:
+ using value_type = pair<reference_wrapper<database>, V>;
+ using base_type = small_vector<value_type, 16>;
+ 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<iterator, bool>
+ 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
{
+ // <bpkg/database.hxx>
+ //
+ class database;
+ class linked_databases;
class transaction;
// <bpkg/package.hxx>
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<repository_fragment>& i) -> bool
- {
- return i == rf;
- }));
-
- if (i != chain.end ())
+ if (find_if (chain.begin (), chain.end (),
+ [&rf] (const shared_ptr<repository_fragment>& 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<repository_count> () != 0)
+ {
+ rep = true;
+
+ if (db.query_value<available_package_count> () != 0)
+ {
+ pkg = true;
+ break;
+ }
+ }
+ }
- if (db.query_value<repository_count> () == 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<available_package_count> () == 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 <libbpkg/package-name.hxx>
#include <bpkg/types.hxx>
-#include <bpkg/forward.hxx> // database, transaction
+#include <bpkg/forward.hxx> // database, linked_databases, transaction
#include <bpkg/utility.hxx>
#include <bpkg/diagnostics.hxx>
@@ -826,11 +826,16 @@ namespace bpkg
odb::result<available_package>&&,
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<vector<shared_ptr<repository_fragment>>>;
+
+ 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<available_package> dap (ddb.find<available_package> (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<shared_ptr<repository_fragment>> ()).first;
+
+ vector<shared_ptr<repository_fragment>>& rfs (i->second);
+
+ for (const auto& pl: dap->locations)
+ {
+ shared_ptr<repository_fragment> 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<pair<shared_ptr<available_package>,
+ lazy_shared_ptr<repository_fragment>>>& 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<pair<shared_ptr<available_package>, shared_ptr<repository_fragment>>>
- find_available (database& db,
+ vector<pair<shared_ptr<available_package>,
+ lazy_shared_ptr<repository_fragment>>>
+ find_available (const linked_databases& dbs,
const package_name& name,
const optional<version_constraint>& c)
{
vector<pair<shared_ptr<available_package>,
- shared_ptr<repository_fragment>>> r;
+ lazy_shared_ptr<repository_fragment>>> r;
- for (shared_ptr<available_package> 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<available_package> 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<available_package> ap (find_imaginary_stub (name));
-
- if (ap != nullptr)
+ if (shared_ptr<available_package> 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<pair<shared_ptr<available_package>, shared_ptr<repository_fragment>>>
- find_available (database& db,
- const package_name& name,
+ vector<pair<shared_ptr<available_package>,
+ lazy_shared_ptr<repository_fragment>>>
+ find_available (const package_name& name,
const optional<version_constraint>& c,
- const vector<shared_ptr<repository_fragment>>& rfs,
+ const config_repo_fragments& rfs,
bool prereq = true)
{
- // Filter the result based on the repository fragments to which each
- // version belongs.
- //
vector<pair<shared_ptr<available_package>,
- shared_ptr<repository_fragment>>> r (
- filter (rfs, query_available (db, name, c), prereq));
+ lazy_shared_ptr<repository_fragment>>> r;
- if (r.empty ())
+ for (const auto& dfs: rfs)
{
- shared_ptr<available_package> 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<repository_fragment> (db, move (af.second)));
+ }
+ }
+
+ if (rfs.size () > 1)
+ sort_dedup (r);
- if (ap != nullptr)
+ if (r.empty ())
+ {
+ if (shared_ptr<available_package> 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<available_package>, shared_ptr<repository_fragment>>
- find_available_one (database& db,
- const package_name& name,
+ // It is assumed that the repository fragment lazy pointer contains the
+ // database information.
+ //
+ static pair<shared_ptr<available_package>,
+ lazy_shared_ptr<repository_fragment>>
+ find_available_one (const package_name& name,
const optional<version_constraint>& c,
- const shared_ptr<repository_fragment>& rf,
+ const lazy_shared_ptr<repository_fragment>& 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<repository_fragment> (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<shared_ptr<available_package>,
+ lazy_shared_ptr<repository_fragment>>
+ find_available_one (const linked_databases& dbs,
+ const package_name& name,
+ const optional<version_constraint>& c,
+ bool prereq = true)
+ {
+ for (database& db: dbs)
+ {
+ auto r (filter_one (db.load<repository_fragment> (""),
+ query_available (db, name, c),
+ prereq));
+
+ if (r.first != nullptr)
+ return make_pair (
+ move (r.first),
+ lazy_shared_ptr<repository_fragment> (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<available_package>, shared_ptr<repository_fragment>>
+ static pair<shared_ptr<available_package>,
+ lazy_shared_ptr<repository_fragment>>
make_available (const common_options& options,
database& db,
const shared_ptr<selected_package>& sp)
@@ -215,7 +358,7 @@ namespace bpkg
// moment).
//
shared_ptr<repository_fragment> af (
- db.main_database ().find<repository_fragment> (
+ db.find<repository_fragment> (
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<available_package> (move (m)), move (af));
+ return make_pair (make_shared<available_package> (move (m)),
+ (af != nullptr
+ ? lazy_shared_ptr<repository_fragment> (db, move (af))
+ : nullptr));
}
// Return true if the version constraint represents the wildcard version.
@@ -345,9 +491,11 @@ namespace bpkg
shared_ptr<selected_package> selected; // NULL if not selected.
shared_ptr<available_package> 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<bpkg::repository_fragment> repository_fragment;
+ lazy_shared_ptr<bpkg::repository_fragment> repository_fragment;
const package_name&
name () const
@@ -934,11 +1082,10 @@ namespace bpkg
}));
const shared_ptr<available_package>& ap (pkg.available);
- const shared_ptr<repository_fragment>& af (pkg.repository_fragment);
+ const lazy_shared_ptr<repository_fragment>& 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<selected_package>& dsp (spd.first);
pair<shared_ptr<available_package>,
- shared_ptr<repository_fragment>> rp;
+ lazy_shared_ptr<repository_fragment>> rp;
shared_ptr<available_package>& 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<repository_fragment> root (
- mdb.load<repository_fragment> (""));
-
- 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<version_constraint> ()));
// 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<database> db;
- shared_ptr<available_package> available;
- shared_ptr<bpkg::repository_fragment> repository_fragment;
- bool unused;
- bool system; // Is meaningless if unused.
+ // The system flag is meaningless if the unused flag is true.
+ //
+ reference_wrapper<database> db;
+ shared_ptr<available_package> available;
+ lazy_shared_ptr<bpkg::repository_fragment> 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<shared_ptr<repository_fragment>>&,
+ 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<shared_ptr<repository_fragment>> repo_frags;
+ config_repo_fragments repo_frags;
config_package_dependents dependents;
for (auto& pd: pds)
@@ -2586,17 +2728,10 @@ namespace bpkg
shared_ptr<selected_package> dsp (
ddb.load<selected_package> (dep.name));
- shared_ptr<available_package> dap (
- mdb.find<available_package> (
- 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<shared_ptr<repository_fragment>>& rfs,
+ const config_repo_fragments& rfs,
const config_package_dependents& dependents,
bool ignore_unsatisfiable)
{
@@ -2689,12 +2824,8 @@ namespace bpkg
c = dvc;
vector<pair<shared_ptr<available_package>,
- shared_ptr<repository_fragment>>> afs (
- find_available (db.main_database (),
- nm,
- c,
- vector<shared_ptr<repository_fragment>> (rfs.begin (),
- rfs.end ())));
+ lazy_shared_ptr<repository_fragment>>> 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<shared_ptr<repository_fragment>> 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<bool> 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<available_package> dap (
- mdb.find<available_package> (
- 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<repository_location> locations;
+ database_map<vector<repository_location>> 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 [<packages>]@<location> form or looks
// like a URL. Find the position of <location> 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<repository> (q));
+ auto rs (pdb.query<repository> (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<repository_location> ()).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<repository_location>& 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 [[<packages>]@]<location> 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<repository> r (
- mdb.find<repository> (ps.location.canonical_name ()));
+ pdb.find<repository> (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<repository_fragment_package>;
- for (const auto& rp: mdb.query<repository_fragment_package> (
+ for (const auto& rp: pdb.query<repository_fragment_package> (
(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<selected_package> sp (
- ps.db->find<selected_package> (nm));
+ pdb.find<selected_package> (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<version_constraint> c;
shared_ptr<selected_package> sp;
- database& pdb (*ps.db);
-
if (!sys)
{
if (!vc)
@@ -3954,7 +4110,7 @@ namespace bpkg
}
shared_ptr<available_package> 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<repository_fragment> root (
- mdb.load<repository_fragment> (""));
-
// 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<repository_fragment> root (pdb, empty_string);
+
// Reduce all the potential variations (archive, directory, package
// name, package name/version) to a single available_package object.
//
- shared_ptr<repository_fragment> af;
+ // Note that the repository fragment is only used for the
+ // build-to-hold packages.
+ //
+ lazy_shared_ptr<repository_fragment> af;
shared_ptr<available_package> 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<repository_fragment> root (mdb, empty_string);
+
using query = query<selected_package>;
for (shared_ptr<selected_package> 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<available_package> ap (move (apr.first));
if (ap == nullptr || ap->stub ())
@@ -4800,15 +4957,15 @@ namespace bpkg
{
struct dep
{
- reference_wrapper<database> db;
- package_name name; // Empty if up/down-grade.
+ reference_wrapper<database> db;
+ package_name name; // Empty if up/down-grade.
// Both are NULL if drop.
//
- shared_ptr<available_package> available;
- shared_ptr<bpkg::repository_fragment> repository_fragment;
+ shared_ptr<available_package> available;
+ lazy_shared_ptr<bpkg::repository_fragment> repository_fragment;
- bool system;
+ bool system;
};
vector<dep> deps;
@@ -6130,6 +6287,7 @@ namespace bpkg
shared_ptr<selected_package>& sp (p.selected);
const shared_ptr<available_package>& ap (p.available);
+ const lazy_shared_ptr<repository_fragment>& 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<selected_package>
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<selected_package> p (db.find<selected_package> (n));
+ shared_ptr<selected_package> p (pdb.find<selected_package> (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<available_package> ap (
- mdb.find<available_package> (available_package_id (n, v)));
+ rdb.find<available_package> (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<selected_package>
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<selected_package>
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<selected_package>
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<selected_package>
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<selected_package>
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<available_package> ap (
- mdb.find<available_package> (available_package_id (n, v)));
+ rdb.find<available_package> (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<selected_package> 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<selected_package>
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_package> 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<apkg> 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<repository_fragment> root (
- mdb.load<repository_fragment> (""));
+ rdb.load<repository_fragment> (""));
using query = query<available_package>;
query q (query::id.name == p.name);
{
- auto r (mdb.query<available_package> (q));
+ auto r (rdb.query<available_package> (q));
known = !r.empty ();
build = filter_one (root, move (r)).first != nullptr;
}
@@ -109,7 +111,7 @@ namespace bpkg
//
for (shared_ptr<available_package> ap:
pointer_result (
- mdb.query<available_package> (q)))
+ rdb.query<available_package> (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<selected_package> d (pair.first.load ());
database& db (pair.first.database ());
const optional<version_constraint>& 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<selected_package>;
@@ -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<selected_package> (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<selected_package>
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<available_package> ap (
- mdb.find<available_package> (available_package_id (n, v)));
+ rdb.find<available_package> (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<selected_package>
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 } <<EOI 2>>~%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 } <<EOI 2>>~%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 } <<EOI 2>>~%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 } <<EOI 2>>~%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 } <<EOI 2>>~%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 } <<EOI 2>>~%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 } <<EOI 2>>~%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 } <<EOI 2>>~%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