repos.recursive_build_report: Sort summary topologically
... if possible. If not, summary is sorted alphabetically and the first cycle found is reported to logs. Dependencies for sorting use very strong model: A should be rebuild before B if any packages built from A are in the build chroot for B. Of course, our rudimentary implementation of chroot_for does not mimic real apt packages selecting logic, so it gives us just an approximation, but hopefully a useful one.
This commit is contained in:
parent
bfce854471
commit
048ed5fe6c
@ -1,8 +1,9 @@
|
||||
|
||||
# This is Python3
|
||||
# This is Python3.9
|
||||
# This module does not use str: use bytes everywhere.
|
||||
|
||||
import collections
|
||||
import graphlib
|
||||
import itertools
|
||||
import logging
|
||||
|
||||
@ -269,7 +270,7 @@ def have_same_source(repoA, repoB, source_name):
|
||||
_BUILDREQ = '0000-BR'
|
||||
|
||||
|
||||
def _raw_build_report(from_repo, to_repo, source_name):
|
||||
def _raw_build_report(from_repo, to_repo, source_name, ignore=()):
|
||||
"""Build report for one source, by name
|
||||
|
||||
Returns an iterable over tuples (kind, dep, provider).
|
||||
@ -284,7 +285,8 @@ def _raw_build_report(from_repo, to_repo, source_name):
|
||||
if not any(to_repo.providers(dep)))
|
||||
for dep in missing_buidreqs:
|
||||
for _dep, provider in from_repo.providers(dep):
|
||||
result.add((_BUILDREQ, dep, provider))
|
||||
if provider.source_name not in ignore:
|
||||
result.add((_BUILDREQ, dep, provider))
|
||||
|
||||
for b in from_repo.binaries_from(source_name):
|
||||
for dep in b.requires:
|
||||
@ -308,7 +310,8 @@ def _raw_build_report(from_repo, to_repo, source_name):
|
||||
continue
|
||||
# ok, it's true missing dependency
|
||||
for _dep, provider in from_repo.providers(dep):
|
||||
result.add((b.name.decode(), dep, provider))
|
||||
if provider.source_name not in ignore:
|
||||
result.add((b.name.decode(), dep, provider))
|
||||
return result
|
||||
|
||||
|
||||
@ -347,7 +350,8 @@ def _src_name(source):
|
||||
return source
|
||||
|
||||
|
||||
def recursive_build_report(from_repo, to_repo, *source_names):
|
||||
def recursive_build_report(from_repo, to_repo, *source_names,
|
||||
ignore=(), ignore_sort=()):
|
||||
reports = []
|
||||
build_source_deps = {}
|
||||
pkg_source_deps = {}
|
||||
@ -357,7 +361,7 @@ def recursive_build_report(from_repo, to_repo, *source_names):
|
||||
|
||||
while stack:
|
||||
cur = stack.pop()
|
||||
report = _raw_build_report(from_repo, to_repo, cur)
|
||||
report = _raw_build_report(from_repo, to_repo, cur, ignore)
|
||||
reports.append(format_triplet_report(report, cur.decode()))
|
||||
|
||||
# find all sources in the report
|
||||
@ -372,12 +376,55 @@ def recursive_build_report(from_repo, to_repo, *source_names):
|
||||
seen.update(unseen)
|
||||
stack.extend(unseen)
|
||||
|
||||
# expand the build requires with the pkg reqs of dependencies:
|
||||
full_req = {}
|
||||
self_dependent = set()
|
||||
for source in build_source_deps:
|
||||
_u, bins = from_repo.chroot_for(from_repo.sources[source].requires)
|
||||
dep_sources = set()
|
||||
for b in bins:
|
||||
if b.source_name not in build_source_deps:
|
||||
continue
|
||||
if b.source_name == source:
|
||||
self_dependent.add(source)
|
||||
continue
|
||||
if (b.source_name, source) in ignore_sort:
|
||||
continue
|
||||
dep_sources.add(b.source_name)
|
||||
full_req[source] = dep_sources
|
||||
|
||||
try:
|
||||
order = list(graphlib.TopologicalSorter(full_req).static_order())
|
||||
except graphlib.CycleError as ex:
|
||||
LOG.error("Cycle detected: %s", ex)
|
||||
order = sorted(build_source_deps)
|
||||
|
||||
reports.append('\n== SUMMARY ==\n')
|
||||
for source in sorted(build_source_deps):
|
||||
reports.append('{}\t{}: {} :: {}'.format(
|
||||
'' if source in requested_source_names else 'N', source.decode(),
|
||||
for source in order:
|
||||
reports.append('{}\t{:50} {} :: {}'.format(
|
||||
'' if source in requested_source_names else 'N',
|
||||
from_repo.sources[source].source_rpm.decode(),
|
||||
b' '.join(build_source_deps[source]).decode(),
|
||||
b' '.join(pkg_source_deps[source]).decode()))
|
||||
|
||||
if self_dependent:
|
||||
reports.append('\nSelf-dependant packages:')
|
||||
reports.extend('\t %s' % source.decode()
|
||||
for source in sorted(self_dependent))
|
||||
|
||||
special = set()
|
||||
for source_name in order:
|
||||
source = to_repo.sources.get(source_name)
|
||||
if not source:
|
||||
continue
|
||||
if b'.mips' in source.release or b'.rv64' in source.release:
|
||||
special.add(source.source_rpm)
|
||||
|
||||
if special:
|
||||
reports.append('\nThe followng packages are special:')
|
||||
reports.extend('\t %s' % source.decode()
|
||||
for source in sorted(special))
|
||||
|
||||
return '\n'.join(reports)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user