aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bpkg/build.cxx2
-rw-r--r--bpkg/package26
-rw-r--r--bpkg/package.cxx49
-rw-r--r--bpkg/pkg-fetch.cxx13
-rw-r--r--bpkg/pkg-unpack.cxx4
5 files changed, 74 insertions, 20 deletions
diff --git a/bpkg/build.cxx b/bpkg/build.cxx
index 361cd9a..e9377ec 100644
--- a/bpkg/build.cxx
+++ b/bpkg/build.cxx
@@ -149,7 +149,7 @@ namespace bpkg
// explicitly added to the configuration and their complements,
// recursively.
//
- ap = filter_one (root, db.query<available_package> (q));
+ ap = filter_one (root, db.query<available_package> (q)).first;
}
// Load the package that may have already been selected and
diff --git a/bpkg/package b/bpkg/package
index 6bd68cc..67a80a8 100644
--- a/bpkg/package
+++ b/bpkg/package
@@ -10,6 +10,7 @@
#include <vector>
#include <cstdint> // uint16
#include <ostream>
+#include <utility> // pair
#include <odb/core.hxx>
#include <odb/nested-container.hxx>
@@ -146,7 +147,7 @@ namespace bpkg
complements_type complements;
prerequisites_type prerequisites;
- // Used to detect recursive fecthing. Will probably be replaced
+ // Used to detect recursive fetching. Will probably be replaced
// by the 'repositories' file timestamp or hashsum later.
//
#pragma db transient
@@ -237,6 +238,16 @@ namespace bpkg
// List of repositories to which this package version belongs (yes,
// in our world, it can be in multiple, unrelated repositories).
//
+ // Note that if the repository is the special root repository (its
+ // location is empty), then this is a transient (or "fake") object
+ // for an existing package archive or package directory. In this
+ // case the location is the path to the archive/directory and to
+ // determine which one it is, use file/dir_exists(). While on the
+ // topic of fake available_package objects, when one is created for
+ // a selected package (see make_available()), this list is left empty
+ // with the thinking being that since the package is already in at
+ // least fetched state, we shouldn't be needing its location.
+ //
std::vector<package_location> locations; //@@ Map?
// Package manifest data.
@@ -298,7 +309,7 @@ namespace bpkg
std::vector<shared_ptr<available_package>>
filter (const shared_ptr<repository>&, odb::result<available_package>&&);
- shared_ptr<available_package>
+ std::pair<shared_ptr<available_package>, shared_ptr<repository>>
filter_one (const shared_ptr<repository>&, odb::result<available_package>&&);
// state
@@ -338,6 +349,17 @@ namespace bpkg
version_type version;
state_type state;
+ // Repository from which this package came. Note that it is not
+ // a pointer to the repository object because it could be wiped
+ // out (e.g., as a result of rep-fetch). We call such packages
+ // "orphans". While we can get a list of orphan's prerequisites
+ // (by loading its manifest), we wouldn't know which repository
+ // to use as a base to resolve them. As a result, an orphan that
+ // is not already configured (and thus has all its prerequisites
+ // resolved) is not very useful and can only be purged.
+ //
+ repository_location repository;
+
// Path to the archive of this package, if any. If not absolute,
// then it is relative to the configuration directory. The purge
// flag indicates whether the archive should be removed when the
diff --git a/bpkg/package.cxx b/bpkg/package.cxx
index 02cb49d..e764c3f 100644
--- a/bpkg/package.cxx
+++ b/bpkg/package.cxx
@@ -40,35 +40,54 @@ namespace bpkg
// available_package
//
- // Check if the package is available from the specified repository or
- // one of its complements, recursively. Return the first repository
- // that contains the package or NULL if none are.
+ // Check if the package is available from the specified repository,
+ // its prerequisite repositories, or one of their complements,
+ // recursively. Return the first repository that contains the
+ // package or NULL if none are.
//
static shared_ptr<repository>
find (const shared_ptr<repository>& r,
- const shared_ptr<available_package>& ap)
+ const shared_ptr<available_package>& ap,
+ bool prereq = true)
{
+ const auto& ps (r->prerequisites);
const auto& cs (r->complements);
for (const package_location& pl: ap->locations)
{
+ const lazy_shared_ptr<repository>& lr (pl.repository);
+
// First check the repository itself.
//
- if (pl.repository.object_id () == r->name)
+ if (lr.object_id () == r->name)
return r;
- // Then check all the complements without loading them.
+ // Then check all the complements and prerequisites without
+ // loading them.
//
- if (cs.find (pl.repository) != cs.end ())
- return pl.repository.load ();
+ if (cs.find (lr) != cs.end () || (prereq && ps.find (lr) != ps.end ()))
+ return lr.load ();
- // Finally, load the complements and check them recursively.
+ // Finally, load the complements and prerequisites and check them
+ // recursively.
//
for (const lazy_shared_ptr<repository>& cr: cs)
{
- if (shared_ptr<repository> r = find (cr.load (), ap))
+ // Should we consider prerequisites of our complements as our
+ // prerequisites? I'd say not.
+ //
+ if (shared_ptr<repository> r = find (cr.load (), ap, false))
return r;
}
+
+ if (prereq)
+ {
+ for (const lazy_weak_ptr<repository>& pr: ps)
+ {
+ if (shared_ptr<repository> r = find (pr.load (), ap, false))
+ return r;
+ }
+ }
}
return nullptr;
@@ -88,16 +107,18 @@ namespace bpkg
return aps;
}
- shared_ptr<available_package>
+ pair<shared_ptr<available_package>, shared_ptr<repository>>
filter_one (const shared_ptr<repository>& r, result<available_package>&& apr)
{
+ using result = pair<shared_ptr<available_package>, shared_ptr<repository>>;
+
for (shared_ptr<available_package> ap: pointer_result (apr))
{
- if (find (r, ap) != nullptr)
- return ap;
+ if (shared_ptr<repository> pr = find (r, ap))
+ return result (move (ap), move (pr));
}
- return nullptr;
+ return result ();
}
// state
diff --git a/bpkg/pkg-fetch.cxx b/bpkg/pkg-fetch.cxx
index ca2bada..b1e5253 100644
--- a/bpkg/pkg-fetch.cxx
+++ b/bpkg/pkg-fetch.cxx
@@ -37,6 +37,7 @@ namespace bpkg
path a;
auto_rm arm;
bool purge;
+ repository_location rl;
if (o.existing ())
{
@@ -50,6 +51,11 @@ namespace bpkg
fail << "archive file '" << a << "' does not exist";
purge = o.purge ();
+
+ // Use the special root repository as the repository of this
+ // package.
+ //
+ rl = repository_location ();
}
else
{
@@ -79,7 +85,8 @@ namespace bpkg
if (p == nullptr)
fail << "package " << n << " " << v << " is not available";
- // Pick a repository. Prefer local ones over the remote.
+ // Pick a repository. Preferring local ones over the remote seems
+ // like a sensible thing to do.
//
const package_location* pl (&p->locations.front ());
@@ -96,7 +103,8 @@ namespace bpkg
text << "fetching " << pl->location.leaf () << " "
<< "from " << pl->repository->name;
- a = fetch_archive (o, pl->repository->location, pl->location, c);
+ rl = pl->repository->location;
+ a = fetch_archive (o, rl, pl->location, c);
arm = auto_rm (a);
purge = true;
}
@@ -132,6 +140,7 @@ namespace bpkg
move (m.name),
move (m.version),
state::fetched,
+ move (rl),
move (a),
purge,
nullopt, // No source directory yet.
diff --git a/bpkg/pkg-unpack.cxx b/bpkg/pkg-unpack.cxx
index 5fc5f0b..b6decca 100644
--- a/bpkg/pkg-unpack.cxx
+++ b/bpkg/pkg-unpack.cxx
@@ -57,12 +57,14 @@ namespace bpkg
if (ad.sub (ac))
ad = ad.leaf (ac);
- // Add the package to the configuration.
+ // Add the package to the configuration. Use the special root
+ // repository as the repository of this package.
//
shared_ptr<package> p (new package {
move (m.name),
move (m.version),
state::unpacked,
+ repository_location (),
nullopt, // No archive
false, // Don't purge archive.
move (ad),