From a2b084651909929d58f6b4bc0f3c742d87ee31f6 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 27 Apr 2018 15:53:00 +0300 Subject: Add support for repository fragments --- bpkg/package.cxx | 143 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 56 deletions(-) (limited to 'bpkg/package.cxx') diff --git a/bpkg/package.cxx b/bpkg/package.cxx index 2880368..4880623 100644 --- a/bpkg/package.cxx +++ b/bpkg/package.cxx @@ -29,81 +29,110 @@ 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 fragment, + // its prerequisite repositories, or one of their complements, recursively. + // Return the first repository fragment 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. + // root repository can be the default complement for dir and git + // repositories (see rep_fetch() implementation for details). Thus we need + // to make sure that the repository fragment is not in the dependency chain + // yet. // - using repositories = vector>>; + using repository_fragments = + vector>>; - static shared_ptr - find (const shared_ptr& r, + static shared_ptr + find (const shared_ptr& rf, const shared_ptr& ap, - repositories& chain, + repository_fragments& chain, bool prereq) { // Prerequisites are not searched through recursively. // assert (!prereq || chain.empty ()); - auto pr = [&r] (const shared_ptr& i) -> bool {return i == r;}; - auto i (find_if (chain.begin (), chain.end (), pr)); + auto i (find_if (chain.begin (), chain.end (), + [&rf] (const shared_ptr& i) -> bool + { + return i == rf; + })); if (i != chain.end ()) return nullptr; - chain.emplace_back (r); + chain.emplace_back (rf); - unique_ptr deleter ( - &chain, [] (repositories* r) {r->pop_back ();}); + unique_ptr deleter ( + &chain, [] (repository_fragments* rf) {rf->pop_back ();}); - const auto& ps (r->prerequisites); - const auto& cs (r->complements); + const auto& cs (rf->complements); + const auto& ps (rf->prerequisites); - // @@ The same repository can be present in the location set multiple times - // with different fragment values. Given that we may traverse the same - // repository tree multiple times, which is inefficient but harmless. - // Let's leave it this way for now as it likely to be changed with - // adding support for repository fragment objects. - // for (const package_location& pl: ap->locations) { - const lazy_shared_ptr& lr (pl.repository); + const lazy_shared_ptr& lrf (pl.repository_fragment); // First check the repository itself. // - if (lr.object_id () == r->name) - return r; + if (lrf.object_id () == rf->name) + return rf; - // Then check all the complements and prerequisites without - // loading them. + // Then check all the complements and prerequisites repository fragments + // without loading them. Though, we still need to load complement and + // prerequisite repositories. // - if (cs.find (lr) != cs.end () || (prereq && ps.find (lr) != ps.end ())) - return lr.load (); + auto pr = [&lrf] (const repository::fragment_type& i) + { + return i.fragment == lrf; + }; + + for (const lazy_shared_ptr& r: cs) + { + const auto& frs (r.load ()->fragments); + + if (find_if (frs.begin (), frs.end (), pr) != frs.end ()) + return lrf.load (); + } + + if (prereq) + { + for (const lazy_weak_ptr& r: ps) + { + const auto& frs (r.load ()->fragments); + + if (find_if (frs.begin (), frs.end (), pr) != frs.end ()) + return lrf.load (); + } + } // Finally, load the complements and prerequisites and check them // recursively. // for (const lazy_shared_ptr& cr: cs) { - // Should we consider prerequisites of our complements as our - // prerequisites? I'd say not. - // - if (shared_ptr r = find (cr.load (), ap, chain, false)) - return r; + for (const auto& fr: cr.load ()->fragments) + { + // Should we consider prerequisites of our complements as our + // prerequisites? I'd say not. + // + if (shared_ptr r = + find (fr.fragment.load (), ap, chain, false)) + return r; + } } if (prereq) { for (const lazy_weak_ptr& pr: ps) { - if (shared_ptr r = find (pr.load (), ap, chain, false)) - return r; + for (const auto& fr: pr.load ()->fragments) + { + if (shared_ptr r = + find (fr.fragment.load (), ap, chain, false)) + return r; + } } } } @@ -111,17 +140,17 @@ namespace bpkg return nullptr; } - shared_ptr - filter (const shared_ptr& r, + shared_ptr + filter (const shared_ptr& r, const shared_ptr& ap, bool prereq) { - repositories chain; + repository_fragments chain; return find (r, ap, chain, prereq); } vector> - filter (const shared_ptr& r, + filter (const shared_ptr& r, result&& apr, bool prereq) { @@ -136,34 +165,36 @@ namespace bpkg return aps; } - pair, shared_ptr> - filter_one (const shared_ptr& r, + pair, shared_ptr> + filter_one (const shared_ptr& r, result&& apr, bool prereq) { - using result = pair, shared_ptr>; + using result = pair, + shared_ptr>; for (shared_ptr ap: pointer_result (apr)) { - if (shared_ptr pr = filter (r, ap, prereq)) + if (shared_ptr pr = filter (r, ap, prereq)) return result (move (ap), move (pr)); } return result (); } - vector, shared_ptr>> - filter (const vector>& rps, + vector, shared_ptr>> + filter (const vector>& rps, odb::result&& apr, bool prereq) { - vector, shared_ptr>> aps; + vector, + shared_ptr>> aps; for (shared_ptr ap: pointer_result (apr)) { - for (const shared_ptr r: rps) + for (const shared_ptr r: rps) { - shared_ptr ar (filter (r, ap, prereq)); + shared_ptr ar (filter (r, ap, prereq)); if (ar != nullptr) { @@ -235,20 +266,20 @@ namespace bpkg if (check_external) { - using query = query; + using query = query; query q ( query::package::id.name == n && compare_version_eq (query::package::id.version, v, true, false)); - for (const auto& pr: db.query (q)) + for (const auto& prf: db.query (q)) { - const shared_ptr& r (pr.repository); + const shared_ptr& rf (prf.repository_fragment); - if (r->location.directory_based ()) + if (rf->location.directory_based ()) fail << "external package " << n << '/' << v << " is already available from " - << r->location.canonical_name (); + << rf->location.canonical_name (); } } -- cgit v1.1