From 11dfd8bc4022b6596c2158594f18544a1f7ffa3e Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Sat, 17 Feb 2018 16:04:58 +0300 Subject: Use root repository as a default complement for git repository --- bpkg/package.cxx | 41 ++++++++++++++++++++++++++++++++++------- bpkg/rep-fetch.cxx | 14 ++++++++++++++ 2 files changed, 48 insertions(+), 7 deletions(-) (limited to 'bpkg') 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>>; + static shared_ptr find (const shared_ptr& r, const shared_ptr& ap, - bool prereq = true) + repositories& chain) { + auto pr = [&r] (const shared_ptr& 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 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 r = find (cr.load (), ap, false)) + if (shared_ptr r = find (cr.load (), ap, chain)) return r; } @@ -68,7 +87,7 @@ namespace bpkg { for (const lazy_weak_ptr& pr: ps) { - if (shared_ptr r = find (pr.load (), ap, false)) + if (shared_ptr r = find (pr.load (), ap, chain)) return r; } } @@ -77,6 +96,14 @@ namespace bpkg return nullptr; } + static inline shared_ptr + find (const shared_ptr& r, + const shared_ptr& ap) + { + repositories chain; + return find (r, ap, chain); + } + vector> filter (const shared_ptr& r, result&& apr) { diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx index 029db1d..e78ae064 100644 --- a/bpkg/rep-fetch.cxx +++ b/bpkg/rep-fetch.cxx @@ -367,6 +367,7 @@ namespace bpkg case repository_type::git: return rep_fetch_git (co, conf, rl, iu); } + assert (false); // Can't be here. return rep_fetch_data (); } @@ -500,6 +501,19 @@ namespace bpkg } } + // For git repositories that have neither prerequisites nor complements + // we use the root repository as the default complement. + // + // This supports the common use case where the user has a single-package + // git repository and doesn't want to bother with the repositories file. + // This way their package will still pick up its dependencies from the + // configuration, without regards from which repositories they came from. + // + if (rl.type () == repository_type::git && + r->complements.empty () && + r->prerequisites.empty ()) + r->complements.insert (lazy_shared_ptr (db, root)); + // "Suspend" session while persisting packages to reduce memory // consumption. // -- cgit v1.1