From 2b779f51134c497267a999f1e4b77407e5e8836f Mon Sep 17 00:00:00 2001 From: "Ivan A. Melnikov" Date: Thu, 17 Aug 2023 16:20:20 +0400 Subject: [PATCH] Introduce a separate entity for chroots Holding together a set of binaries turns out to be a nice abstraction. --- repos_cmp/repos.py | 52 +++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/repos_cmp/repos.py b/repos_cmp/repos.py index 4f9793e..1cd4362 100644 --- a/repos_cmp/repos.py +++ b/repos_cmp/repos.py @@ -136,6 +136,33 @@ class Binary: self.name, self.epoch, self.version, self.release) +class Chroot: + '''Set of binary packages''' + + def __init__(self): + self.provides = collections.defaultdict(set) + self.binaries = dict() + + def add(self, binary): + name = binary.name + if name in self.binaries: + LOG.error("Duplicate binaries: %s %s", + binary, self.binaries[name]) + self.binaries[name] = binary + for prov in binary.provides: + self.provides[prov.name].add(prov) + + def unmets(self): + for b in self.binaries.values(): + for dep in b.requires: + if not self.is_provided(dep): + yield dep + + def is_provided(self, dep): + return any(p.is_provide_for(dep) + for p in self.provides.get(dep.name, ())) + + # consider this repository components by default DEFAULT_COMPONENTS = ('classic', 'checkinstall') @@ -246,20 +273,18 @@ class Repository: def chroot_for(self, requires, prefer=()): stack = list(reversed(list(requires))) - chroot_provides = collections.defaultdict(set) - chroot_binaries = [] - unmets = [] + chroot = Chroot() while stack: dep = stack.pop() - if any(p.is_provide_for(dep) for p in chroot_provides[dep.name]): + if chroot.is_provided(dep): continue LOG.debug("looking up %s", dep) providers = set(item[1] for item in self.providers(dep)) if not providers: providers = set(item[1] for item in self.addon_providers(dep)) if not providers: - unmets.append(dep) + LOG.debug("Unmet dependency: %s", dep) continue if len(providers) > 1: preferred = [p for p in providers @@ -272,12 +297,9 @@ class Repository: LOG.warning('Ambiguous provide: %s (%s)', dep, providers) # choose an (almost) random provider p = providers.pop() - LOG.debug(" installing %s", p) - chroot_binaries.append(p) - for prov in p.provides: - chroot_provides[prov.name].add(prov) + chroot.add(p) stack.extend(p.requires) - return unmets, chroot_binaries + return chroot _SPECIAL_DEPS = ( @@ -332,14 +354,14 @@ def _raw_build_report(from_repo, to_repo, source_name, ignore=(), prefer=()): translate = (to_repo.bits != 64) # find what's missing for the build chroot in to_repo - build_unmets, _b = to_repo.chroot_for( + chroot = to_repo.chroot_for( from_repo.sources[source_name].requires, prefer=prefer) # distinguish unmets from build requirements that are missing buildreqs = {dep for dep in from_repo.sources[source_name].requires} missing_buildreqs = ( ((_BUILDREQ if dep in buildreqs else _BUILD_UNMET), dep) - for dep in build_unmets) + for dep in chroot.unmets()) # add requirements for the binary packages this source package # produces in the from_repo; if needed, try to translate from 64 to 32 bits @@ -461,10 +483,10 @@ def recursive_build_report(from_repo, to_repo, *source_names, full_req = {} names = set(build_source_deps) for source in build_source_deps: - _u, bins = from_repo.chroot_for(from_repo.sources[source].requires, - prefer=names) + chroot = from_repo.chroot_for(from_repo.sources[source].requires, + prefer=names) dep_sources = set() - for b in bins: + for b in chroot.binaries.values(): if b.source_name not in build_source_deps: continue if (b.source_name, source) in ignore_sort: