repos: Prefer requested sources for recursive report

This commit is contained in:
Ivan A. Melnikov 2023-08-03 18:21:09 +04:00
parent 79a92c2358
commit fe17158f69

View File

@ -227,7 +227,7 @@ class Repository:
del self.binaries[name]
self.update_indexes()
def chroot_for(self, requires):
def chroot_for(self, requires, prefer=()):
stack = list(reversed(list(requires)))
chroot_provides = collections.defaultdict(set)
chroot_binaries = []
@ -242,9 +242,16 @@ class Repository:
if not providers:
unmets.append(dep)
continue
if len(providers) > 1:
preferred = [p for p in providers
if p.source_name in prefer]
if preferred and len(preferred) < len(providers):
LOG.info("Using preferred providers: %s %s",
dep, preferred)
providers = preferred
if len(providers) > 1:
LOG.warning('Ambiguous provide: %s (%s)', dep, providers)
# that's almost random if ambigous:
# choose an (almost) random provider
p = providers.pop()
LOG.debug(" installing %s", p)
chroot_binaries.append(p)
@ -290,16 +297,7 @@ def have_same_source(repoA, repoB, source_name):
_BUILDREQ = '0000-BR'
def _missing_requires(from_repo, to_repo, requires, kind, ignore):
missing_buidreqs = (dep for dep in requires
if not any(to_repo.providers(dep)))
for dep in missing_buidreqs:
for _dep, provider in from_repo.providers(dep):
if provider.source_name not in ignore:
yield kind, dep, provider
def _raw_build_report(from_repo, to_repo, source_name, ignore=()):
def _raw_build_report(from_repo, to_repo, source_name, ignore=(), prefer=()):
"""Build report for one source, by name
Returns an iterable over tuples (kind, dep, provider).
@ -308,36 +306,50 @@ def _raw_build_report(from_repo, to_repo, source_name, ignore=()):
assert from_repo.bits == 64
translate = (to_repo.bits != 64)
result = set(_missing_requires(
from_repo, to_repo, from_repo.sources[source_name].requires,
_BUILDREQ, ignore))
missing_buildreqs = ((_BUILDREQ, dep)
for dep in from_repo.sources[source_name].requires)
missing_binreqs = itertools.chain.from_iterable(
((b.name.decode(), dep) for dep in b.requires)
for b in from_repo.binaries_from(source_name))
result = set()
for b in from_repo.binaries_from(source_name):
for dep in b.requires:
# skip some platform-specific stuff
if any(x in dep.name for x in _SPECIAL_DEPS):
continue
# if needed, try to translate from 64 to 32 bits
the_dep = _from_64bit_dep(dep) if translate else dep
# skip dependencies already present in to_repo
if any(to_repo.providers(the_dep)):
continue
# skip inter-sub-package dependencies
if any(p.source_name == source_name
for kind, dep in itertools.chain(missing_buildreqs, missing_binreqs):
# skip some platform-specific stuff
if any(x in dep.name for x in _SPECIAL_DEPS):
continue
# if needed, try to translate from 64 to 32 bits
the_dep = _from_64bit_dep(dep) if translate else dep
# skip dependencies already present in to_repo
if any(to_repo.providers(the_dep)):
continue
# skip inter-sub-package dependencies
if any(p.source_name == source_name
for _d, p in from_repo.providers(dep)):
continue
# set-versions may be platform-dependent.
# double-check that if have the same source
if (dep.is_setversion()
or _GHC_HASHLIB.match(dep.name)
or _GHC_HASHDEP.fullmatch(dep.name)):
if any(have_same_source(from_repo, to_repo, p.source_name)
for _d, p in from_repo.providers(dep)):
continue
# set-versions may be platform-dependent.
# double-check that if have the same source
if (dep.is_setversion()
or _GHC_HASHLIB.match(dep.name)
or _GHC_HASHDEP.fullmatch(dep.name)):
if any(have_same_source(from_repo, to_repo, p.source_name)
for _d, p in from_repo.providers(dep)):
continue
# ok, it's true missing dependency
for _dep, provider in from_repo.providers(dep):
if provider.source_name not in ignore:
result.add((b.name.decode(), dep, provider))
# ok, it's true missing dependency
# let's look up providers
providers = set(provider
for _dep, provider in from_repo.providers(dep)
if provider.source_name not in ignore)
if not providers:
LOG.warning("No providers for %s", dep)
elif len(providers) > 1:
LOG.warning("%d provider(s) for %s: %s",
len(providers), dep, list(providers))
preferred = [p for p in providers
if p.source_name in prefer]
if preferred and len(preferred) < len(providers):
LOG.info("Using preferred providers: %s", preferred)
providers = preferred
result.update((kind, dep, provider) for provider in providers)
return result
@ -387,7 +399,8 @@ def recursive_build_report(from_repo, to_repo, *source_names,
while stack:
cur = stack.pop()
report = _raw_build_report(from_repo, to_repo, cur, ignore)
report = _raw_build_report(from_repo, to_repo, cur,
ignore, prefer=seen)
cur_in_to = to_repo.sources.get(cur)
cur_source_srpm = cur_in_to.source_rpm if cur_in_to else b'NONE'
reports.append('\n== %s ==\n%s has %s\n' % (
@ -408,8 +421,10 @@ def recursive_build_report(from_repo, to_repo, *source_names,
# expand the build requires with the pkg reqs of dependencies:
full_req = {}
names = set(build_source_deps)
for source in build_source_deps:
_u, bins = from_repo.chroot_for(from_repo.sources[source].requires)
_u, bins = from_repo.chroot_for(from_repo.sources[source].requires,
prefer=names)
dep_sources = set()
for b in bins:
if b.source_name not in build_source_deps:
@ -472,20 +487,6 @@ def recursive_build_report(from_repo, to_repo, *source_names,
return '\n'.join(reports)
def requires_build_report(from_repo, to_repo, *requires,
ignore=(), ignore_sort=()):
missing_reqs = list(_missing_requires(
from_repo, to_repo,
[Dependency.wrap(r) for r in requires],
ignore, ignore_sort))
reports = [format_triplet_report(missing_reqs, 'Requested')]
source_names = set(p.source_name for _k, _d, p in missing_reqs)
reports.append(recursive_build_report(
from_repo, to_repo, *source_names,
ignore=ignore, ignore_sort=ignore_sort))
return '\n'.join(reports)
def _unmets_without(repo, kind, *source_names):
next_repo = repo.copy('removal_test_' + repo.name)
next_repo.delete_sources(*source_names)