Introduce a separate entity for chroots

Holding together a set of binaries turns out
to be a nice abstraction.
This commit is contained in:
Ivan A. Melnikov 2023-08-17 16:20:20 +04:00
parent ec92670e48
commit 2b779f5113

View File

@ -136,6 +136,33 @@ class Binary:
self.name, self.epoch, self.version, self.release) 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 # consider this repository components by default
DEFAULT_COMPONENTS = ('classic', 'checkinstall') DEFAULT_COMPONENTS = ('classic', 'checkinstall')
@ -246,20 +273,18 @@ class Repository:
def chroot_for(self, requires, prefer=()): def chroot_for(self, requires, prefer=()):
stack = list(reversed(list(requires))) stack = list(reversed(list(requires)))
chroot_provides = collections.defaultdict(set) chroot = Chroot()
chroot_binaries = []
unmets = []
while stack: while stack:
dep = stack.pop() dep = stack.pop()
if any(p.is_provide_for(dep) for p in chroot_provides[dep.name]): if chroot.is_provided(dep):
continue continue
LOG.debug("looking up %s", dep) LOG.debug("looking up %s", dep)
providers = set(item[1] for item in self.providers(dep)) providers = set(item[1] for item in self.providers(dep))
if not providers: if not providers:
providers = set(item[1] for item in self.addon_providers(dep)) providers = set(item[1] for item in self.addon_providers(dep))
if not providers: if not providers:
unmets.append(dep) LOG.debug("Unmet dependency: %s", dep)
continue continue
if len(providers) > 1: if len(providers) > 1:
preferred = [p for p in providers preferred = [p for p in providers
@ -272,12 +297,9 @@ class Repository:
LOG.warning('Ambiguous provide: %s (%s)', dep, providers) LOG.warning('Ambiguous provide: %s (%s)', dep, providers)
# choose an (almost) random provider # choose an (almost) random provider
p = providers.pop() p = providers.pop()
LOG.debug(" installing %s", p) chroot.add(p)
chroot_binaries.append(p)
for prov in p.provides:
chroot_provides[prov.name].add(prov)
stack.extend(p.requires) stack.extend(p.requires)
return unmets, chroot_binaries return chroot
_SPECIAL_DEPS = ( _SPECIAL_DEPS = (
@ -332,14 +354,14 @@ def _raw_build_report(from_repo, to_repo, source_name, ignore=(), prefer=()):
translate = (to_repo.bits != 64) translate = (to_repo.bits != 64)
# find what's missing for the build chroot in to_repo # 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) from_repo.sources[source_name].requires, prefer=prefer)
# distinguish unmets from build requirements that are missing # distinguish unmets from build requirements that are missing
buildreqs = {dep for dep in from_repo.sources[source_name].requires} buildreqs = {dep for dep in from_repo.sources[source_name].requires}
missing_buildreqs = ( missing_buildreqs = (
((_BUILDREQ if dep in buildreqs else _BUILD_UNMET), dep) ((_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 # add requirements for the binary packages this source package
# produces in the from_repo; if needed, try to translate from 64 to 32 bits # 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 = {} full_req = {}
names = set(build_source_deps) names = set(build_source_deps)
for source in build_source_deps: for source in build_source_deps:
_u, bins = from_repo.chroot_for(from_repo.sources[source].requires, chroot = from_repo.chroot_for(from_repo.sources[source].requires,
prefer=names) prefer=names)
dep_sources = set() dep_sources = set()
for b in bins: for b in chroot.binaries.values():
if b.source_name not in build_source_deps: if b.source_name not in build_source_deps:
continue continue
if (b.source_name, source) in ignore_sort: if (b.source_name, source) in ignore_sort: