Improve cache invalidation of (pseudo-)essential set

If a new pseudo-essential package was added to testing *and* it is
mutually-exclusive with an existing member, britney would incorrectly
flag it as uninstallable (unless another change triggered a cache
invalidation of the pseudo-essential set).

With this commit, the cache invalidation is now done based on whether
we add something that *might* be in the (effective) pseudo-essential
set.  It is an overapproximation as there are cases where the
invalidation is unnecessary, but at the moment it is not a performance
concern.

Closes: https://bugs.debian.org/944190
Signed-off-by: Niels Thykier <niels@thykier.net>
ubuntu/rebased
Niels Thykier 5 years ago
parent c3ca2bc703
commit 0d5ea5eb8c
No known key found for this signature in database
GPG Key ID: A65B78DBE67C7AAC

@ -17,7 +17,7 @@ from functools import partial
import logging
from itertools import chain, filterfalse
from britney2.utils import iter_except
from britney2.utils import iter_except, add_transitive_dependencies_flatten
class InstallabilityTester(object):
@ -52,12 +52,16 @@ class InstallabilityTester(object):
# are essential and packages that will always follow.
#
# It may not be a complete essential set, since alternatives
# are not always resolved. Noticably cases like "awk" may be
# are not always resolved. Noticeably cases like "awk" may be
# left out (since it could be either gawk, mawk or
# original-awk) unless something in this sets depends strictly
# on one of them
self._cache_ess = {}
essential_w_transitive_deps = set(universe.essential_packages)
add_transitive_dependencies_flatten(universe, essential_w_transitive_deps)
self._cache_essential_transitive_dependencies = essential_w_transitive_deps
def compute_installability(self):
"""Computes the installability of all the packages in the suite
@ -137,8 +141,8 @@ class InstallabilityTester(object):
# Re-add broken packages as some of them may now be installable
self._suite_contents |= self._cache_broken
self._cache_broken = set()
if pkg_id in self._universe.essential_packages and pkg_id.architecture in self._cache_ess:
# Adds new essential => "pseudo-essential" set needs to be
if pkg_id in self._cache_essential_transitive_dependencies and pkg_id.architecture in self._cache_ess:
# Adds new possibly pseudo-essential => "pseudo-essential" set needs to be
# recomputed
del self._cache_ess[pkg_id.architecture]

@ -30,7 +30,7 @@ import time
from collections import defaultdict
from datetime import datetime
from functools import partial
from itertools import filterfalse
from itertools import filterfalse, chain
import yaml
@ -127,6 +127,25 @@ def compute_reverse_tree(pkg_universe, affected):
return None
def add_transitive_dependencies_flatten(pkg_universe, initial_set):
"""Find and include all transitive dependencies
This method updates the initial_set parameter to include all transitive
dependencies. The first argument is an instance of the BinaryPackageUniverse
and the second argument are a set of BinaryPackageId.
The set of initial packages will be updated in place and must
therefore be mutable.
"""
remain = list(initial_set)
while remain:
pkg_id = remain.pop()
new_pkg_ids = [x for x in chain.from_iterable(pkg_universe.dependencies_of(pkg_id)) if x not in initial_set]
initial_set.update(new_pkg_ids)
remain.extend(new_pkg_ids)
return None
def write_nuninst(filename, nuninst):
"""Write the non-installable report

Loading…
Cancel
Save