aboutsummaryrefslogtreecommitdiff
path: root/bpkg/package.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2018-02-17 16:04:58 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2018-02-19 14:28:57 +0300
commit11dfd8bc4022b6596c2158594f18544a1f7ffa3e (patch)
tree0b88ccc3b977d43a40fb0937d6d34fedcb05a927 /bpkg/package.cxx
parent3d4838d3706de2ba0045dc9f99a3dc96398def64 (diff)
Use root repository as a default complement for git repository
Diffstat (limited to 'bpkg/package.cxx')
-rw-r--r--bpkg/package.cxx41
1 files changed, 34 insertions, 7 deletions
diff --git a/bpkg/package.cxx b/bpkg/package.cxx
index 1c98f42..c7c40a1 100644
--- a/bpkg/package.cxx
+++ b/bpkg/package.cxx
@@ -24,16 +24,35 @@ namespace bpkg
// available_package
//
- // 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.
+ // 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.
//
+ // Note that we can end up with a repository dependency cycle since the
+ // root repository can be the default complement for git repositories (see
+ // rep_fetch() implementation for details). Thus we need to make sure that
+ // the repository is not in the dependency chain yet.
+ //
+ using repositories = vector<reference_wrapper<const shared_ptr<repository>>>;
+
static shared_ptr<repository>
find (const shared_ptr<repository>& r,
const shared_ptr<available_package>& ap,
- bool prereq = true)
+ repositories& chain)
{
+ auto pr = [&r] (const shared_ptr<repository>& i) -> bool {return i == r;};
+ auto i (find_if (chain.begin (), chain.end (), pr));
+
+ if (i != chain.end ())
+ return nullptr;
+
+ bool prereq (chain.empty ()); // Check prerequisites in top-level only.
+ chain.emplace_back (r);
+
+ unique_ptr<repositories, void (*)(repositories*)> deleter (
+ &chain, [] (repositories* r) {r->pop_back ();});
+
const auto& ps (r->prerequisites);
const auto& cs (r->complements);
@@ -60,7 +79,7 @@ namespace bpkg
// Should we consider prerequisites of our complements as our
// prerequisites? I'd say not.
//
- if (shared_ptr<repository> r = find (cr.load (), ap, false))
+ if (shared_ptr<repository> r = find (cr.load (), ap, chain))
return r;
}
@@ -68,7 +87,7 @@ namespace bpkg
{
for (const lazy_weak_ptr<repository>& pr: ps)
{
- if (shared_ptr<repository> r = find (pr.load (), ap, false))
+ if (shared_ptr<repository> r = find (pr.load (), ap, chain))
return r;
}
}
@@ -77,6 +96,14 @@ namespace bpkg
return nullptr;
}
+ static inline shared_ptr<repository>
+ find (const shared_ptr<repository>& r,
+ const shared_ptr<available_package>& ap)
+ {
+ repositories chain;
+ return find (r, ap, chain);
+ }
+
vector<shared_ptr<available_package>>
filter (const shared_ptr<repository>& r, result<available_package>&& apr)
{