Make InstallabilityTester suite agnostic

Signed-off-by: Niels Thykier <niels@thykier.net>
ubuntu/rebased
Niels Thykier 6 years ago
parent ced7b7b413
commit 7124313aa6
No known key found for this signature in database
GPG Key ID: A65B78DBE67C7AAC

@ -334,7 +334,7 @@ class Britney(object):
if not self.options.nuninst_cache: if not self.options.nuninst_cache:
self.logger.info("Building the list of non-installable packages for the full archive") self.logger.info("Building the list of non-installable packages for the full archive")
self._inst_tester.compute_testing_installability() self._inst_tester.compute_installability()
nuninst = compile_nuninst(target_suite, nuninst = compile_nuninst(target_suite,
self.options.architectures, self.options.architectures,
self.options.nobreakall_arches) self.options.nobreakall_arches)
@ -2110,7 +2110,7 @@ class Britney(object):
self.logger.info("> Update complete - Verifying non-installability counters") self.logger.info("> Update complete - Verifying non-installability counters")
cached_nuninst = self.nuninst_orig cached_nuninst = self.nuninst_orig
self._inst_tester.compute_testing_installability() self._inst_tester.compute_installability()
computed_nuninst = compile_nuninst(self.suite_info.target_suite, computed_nuninst = compile_nuninst(self.suite_info.target_suite,
self.options.architectures, self.options.architectures,
self.options.nobreakall_arches) self.options.nobreakall_arches)

@ -80,7 +80,7 @@ class TargetSuite(Suite):
:param pkg_ids: A set of BinaryPackageId :param pkg_ids: A set of BinaryPackageId
:return: True if any of the packages in pkgs are currently in the suite :return: True if any of the packages in pkgs are currently in the suite
""" """
return self.inst_tester.any_of_these_are_in_testing(pkg_ids) return self.inst_tester.any_of_these_are_in_the_suite(pkg_ids)
def is_pkg_in_the_suite(self, pkg_id): def is_pkg_in_the_suite(self, pkg_id):
"""Test if the package of is in testing """Test if the package of is in testing
@ -88,7 +88,7 @@ class TargetSuite(Suite):
:param pkg_id: A BinaryPackageId :param pkg_id: A BinaryPackageId
:return: True if the pkg is currently in the suite :return: True if the pkg is currently in the suite
""" """
return self.inst_tester.is_pkg_in_testing(pkg_id) return self.inst_tester.is_pkg_in_the_suite(pkg_id)
def is_installable(self, pkg_id): def is_installable(self, pkg_id):
"""Determine whether the given package can be installed in the suite """Determine whether the given package can be installed in the suite

@ -142,7 +142,7 @@ class InstallabilitySolver(object):
self.logger = logging.getLogger(logger_name) self.logger = logging.getLogger(logger_name)
def solve_groups(self, groups): def solve_groups(self, groups):
sat_in_testing = self._inst_tester.any_of_these_are_in_testing sat_in_testing = self._inst_tester.any_of_these_are_in_the_suite
universe = self._universe universe = self._universe
result = [] result = []
emitted = set() emitted = set()

@ -58,51 +58,51 @@ class InstallabilityTester(object):
# on one of them # on one of them
self._cache_ess = {} self._cache_ess = {}
def compute_testing_installability(self): def compute_installability(self):
"""Computes the installability of packages in testing """Computes the installability of all the packages in the suite
This method computes the installability of all packages in This method computes the installability of all packages in
testing and caches the result. This has the advantage of the suite and caches the result. This has the advantage of
making "is_installable" queries very fast for all packages making "is_installable" queries very fast for all packages
in testing. in the suite.
""" """
universe = self._universe universe = self._universe
check_inst = self._check_inst check_inst = self._check_inst
cbroken = self._cache_broken cbroken = self._cache_broken
cache_inst = self._cache_inst cache_inst = self._cache_inst
testing = self._suite_contents suite_contents = self._suite_contents
tcopy = [x for x in testing] tcopy = [x for x in suite_contents]
for t in filterfalse(cache_inst.__contains__, tcopy): for t in filterfalse(cache_inst.__contains__, tcopy):
if t in cbroken: if t in cbroken:
continue continue
res = check_inst(t) res = check_inst(t)
if t in universe.equivalent_packages: if t in universe.equivalent_packages:
eqv = (x for x in universe.packages_equivalent_to(t) if x in testing) eqv = (x for x in universe.packages_equivalent_to(t) if x in suite_contents)
if res: if res:
cache_inst.update(eqv) cache_inst.update(eqv)
else: else:
eqv_set = frozenset(eqv) eqv_set = frozenset(eqv)
testing -= eqv_set suite_contents -= eqv_set
cbroken |= eqv_set cbroken |= eqv_set
@property @property
def stats(self): def stats(self):
return self._stats return self._stats
def any_of_these_are_in_testing(self, pkgs): def any_of_these_are_in_the_suite(self, pkgs):
"""Test if at least one package of a given set is in testing """Test if at least one package of a given set is in the suite
:param pkgs: A set of package ids (as defined in the constructor) :param pkgs: A set of package ids (as defined in the constructor)
:return: True if any of the packages in pkgs are currently in testing :return: True if any of the packages in pkgs are currently in the suite
""" """
return not self._suite_contents.isdisjoint(pkgs) return not self._suite_contents.isdisjoint(pkgs)
def is_pkg_in_testing(self, pkg_id): def is_pkg_in_the_suite(self, pkg_id):
"""Test if the package of is in testing """Test if the package of is in the suite
:param pkg_id: A package id (as defined in the constructor) :param pkg_id: A package id (as defined in the constructor)
:return: True if the pkg is currently in testing :return: True if the pkg is currently in the suite
""" """
return pkg_id in self._suite_contents return pkg_id in self._suite_contents
@ -168,8 +168,8 @@ class InstallabilityTester(object):
def is_installable(self, pkg_id): def is_installable(self, pkg_id):
"""Test if a package is installable in this package set """Test if a package is installable in this package set
The package is assumed to be in "testing" and only packages in The package is assumed to be in the suite and only packages in
"testing" can be used to satisfy relations. the suite can be used to satisfy relations.
:param pkg_id The id of the package :param pkg_id The id of the package
Returns True iff the package is installable. Returns True iff the package is installable.
@ -196,7 +196,7 @@ class InstallabilityTester(object):
# See the explanation of musts, never and choices below. # See the explanation of musts, never and choices below.
stats = self._stats stats = self._stats
universe = self._universe universe = self._universe
testing = self._suite_contents suite_contents = self._suite_contents
cbroken = self._cache_broken cbroken = self._cache_broken
# Our installability verdict - start with "yes" and change if # Our installability verdict - start with "yes" and change if
@ -220,7 +220,7 @@ class InstallabilityTester(object):
check = [t] check = [t]
if len(musts) == 1: if len(musts) == 1:
# Include the essential packages in testing as a starting point. # Include the essential packages in the suite as a starting point.
if t.architecture not in self._cache_ess: if t.architecture not in self._cache_ess:
# The minimal essential set cache is not present - # The minimal essential set cache is not present -
# compute it now. # compute it now.
@ -232,7 +232,7 @@ class InstallabilityTester(object):
# t conflicts with something in the essential set or the essential # t conflicts with something in the essential set or the essential
# set conflicts with t - either way, t is f***ed # set conflicts with t - either way, t is f***ed
cbroken.add(t) cbroken.add(t)
testing.remove(t) suite_contents.remove(t)
stats.conflicts_essential += 1 stats.conflicts_essential += 1
return False return False
musts.update(start) musts.update(start)
@ -240,7 +240,7 @@ class InstallabilityTester(object):
choices.update(ess_choices) choices.update(ess_choices)
# curry check_loop # curry check_loop
check_loop = partial(self._check_loop, universe, testing, check_loop = partial(self._check_loop, universe, suite_contents,
stats, musts, never, cbroken) stats, musts, never, cbroken)
# Useful things to remember: # Useful things to remember:
@ -281,7 +281,7 @@ class InstallabilityTester(object):
for choice in filter(musts.isdisjoint, choices): for choice in filter(musts.isdisjoint, choices):
# cbroken is needed here because (in theory) it could # cbroken is needed here because (in theory) it could
# have changed since the choice was discovered and it # have changed since the choice was discovered and it
# is smaller than testing (so presumably faster) # is smaller than suite_contents (so presumably faster)
remain = choice - never - cbroken remain = choice - never - cbroken
if len(remain) == 1: if len(remain) == 1:
@ -338,7 +338,7 @@ class InstallabilityTester(object):
def resolve_choices(self, check, musts, never, choices): def resolve_choices(self, check, musts, never, choices):
universe = self._universe universe = self._universe
testing = self._suite_contents suite_contents = self._suite_contents
stats = self._stats stats = self._stats
cbroken = self._cache_broken cbroken = self._cache_broken
@ -355,7 +355,7 @@ class InstallabilityTester(object):
check_tmp = [p] check_tmp = [p]
# _check_loop assumes that "musts" is up to date # _check_loop assumes that "musts" is up to date
musts_copy.add(p) musts_copy.add(p)
if not self._check_loop(universe, testing, if not self._check_loop(universe, suite_contents,
stats, musts_copy, never_tmp, stats, musts_copy, never_tmp,
cbroken, choices_tmp, cbroken, choices_tmp,
check_tmp): check_tmp):
@ -407,7 +407,7 @@ class InstallabilityTester(object):
stats.backtrace_last_option += 1 stats.backtrace_last_option += 1
return False return False
def _check_loop(self, universe, testing, stats, musts, never, def _check_loop(self, universe, suite_contents, stats, musts, never,
cbroken, choices, check, len=len, cbroken, choices, check, len=len,
frozenset=frozenset): frozenset=frozenset):
"""Finds all guaranteed dependencies via "check". """Finds all guaranteed dependencies via "check".
@ -437,7 +437,7 @@ class InstallabilityTester(object):
return False return False
# We must install cur for the package to be installable, # We must install cur for the package to be installable,
# so "obviously" we can never choose any of its conflicts # so "obviously" we can never choose any of its conflicts
never.update(relations.negative_dependencies & testing) never.update(relations.negative_dependencies & suite_contents)
# depgroup can be satisfied by picking something that is # depgroup can be satisfied by picking something that is
# already in musts - lets pick that (again). :) # already in musts - lets pick that (again). :)
@ -445,20 +445,20 @@ class InstallabilityTester(object):
# Of all the packages listed in the relation remove those that # Of all the packages listed in the relation remove those that
# are either: # are either:
# - not in testing # - not in the suite
# - known to be broken (by cache) # - known to be broken (by cache)
# - in never # - in never
candidates = (depgroup & testing) - never candidates = (depgroup & suite_contents) - never
if not candidates: if not candidates:
# We got no candidates to satisfy it - this # We got no candidates to satisfy it - this
# package cannot be installed with the current # package cannot be installed with the current
# testing # (version of the) suite
if cur not in cbroken and depgroup.isdisjoint(never): if cur not in cbroken and depgroup.isdisjoint(never):
# cur's dependency cannot be satisfied even if never was empty. # cur's dependency cannot be satisfied even if never was empty.
# This means that cur itself is broken (as well). # This means that cur itself is broken (as well).
cbroken.add(cur) cbroken.add(cur)
testing.remove(cur) suite_contents.remove(cur)
return False return False
if len(candidates) == 1: if len(candidates) == 1:
# only one possible solution to this choice and we # only one possible solution to this choice and we
@ -504,19 +504,19 @@ class InstallabilityTester(object):
if arch not in self._cache_ess: if arch not in self._cache_ess:
# The minimal essential set cache is not present - # The minimal essential set cache is not present -
# compute it now. # compute it now.
testing = self._suite_contents suite_contents = self._suite_contents
cbroken = self._cache_broken cbroken = self._cache_broken
universe = self._universe universe = self._universe
stats = self._stats stats = self._stats
ess_base = [x for x in self._universe.essential_packages if x.architecture == arch and x in testing] ess_base = [x for x in self._universe.essential_packages if x.architecture == arch and x in suite_contents]
start = set(ess_base) start = set(ess_base)
ess_never = set() ess_never = set()
ess_choices = set() ess_choices = set()
not_satisfied = partial(filter, start.isdisjoint) not_satisfied = partial(filter, start.isdisjoint)
while ess_base: while ess_base:
self._check_loop(universe, testing, stats, self._check_loop(universe, suite_contents, stats,
start, ess_never, cbroken, start, ess_never, cbroken,
ess_choices, ess_base) ess_choices, ess_base)
if ess_choices: if ess_choices:

@ -25,14 +25,14 @@ class TestInstTester(unittest.TestCase):
pkg_perl_base = builder.pkg_id('perl-base') pkg_perl_base = builder.pkg_id('perl-base')
assert inst_tester.is_installable(pkg_lintian) assert inst_tester.is_installable(pkg_lintian)
assert inst_tester.is_installable(pkg_perl) assert inst_tester.is_installable(pkg_perl)
assert inst_tester.any_of_these_are_in_testing((pkg_lintian, pkg_perl)) assert inst_tester.any_of_these_are_in_the_suite((pkg_lintian, pkg_perl))
assert not inst_tester.is_installable(pkg_awk) assert not inst_tester.is_installable(pkg_awk)
assert not inst_tester.any_of_these_are_in_testing((pkg_awk,)) assert not inst_tester.any_of_these_are_in_the_suite((pkg_awk,))
inst_tester.remove_binary(pkg_perl) inst_tester.remove_binary(pkg_perl)
assert not inst_tester.any_of_these_are_in_testing((pkg_perl,)) assert not inst_tester.any_of_these_are_in_the_suite((pkg_perl,))
assert inst_tester.any_of_these_are_in_testing((pkg_lintian,)) assert inst_tester.any_of_these_are_in_the_suite((pkg_lintian,))
assert not inst_tester.is_pkg_in_testing(pkg_perl) assert not inst_tester.is_pkg_in_the_suite(pkg_perl)
assert inst_tester.is_pkg_in_testing(pkg_lintian) assert inst_tester.is_pkg_in_the_suite(pkg_lintian)
assert not inst_tester.is_installable(pkg_lintian) assert not inst_tester.is_installable(pkg_lintian)
assert not inst_tester.is_installable(pkg_perl) assert not inst_tester.is_installable(pkg_perl)
inst_tester.add_binary(pkg_perl) inst_tester.add_binary(pkg_perl)

@ -124,7 +124,7 @@ def build_sources_from_universe_and_inst_tester(policy, pkg_universe, inst_teste
pkg_name = pkg_id.package_name pkg_name = pkg_id.package_name
src_universe[pkg_id] = create_source_package(pkg_id.version, binaries=[pkg_id]) src_universe[pkg_id] = create_source_package(pkg_id.version, binaries=[pkg_id])
bin_universe[pkg_id] = create_bin_package(pkg_id) bin_universe[pkg_id] = create_bin_package(pkg_id)
if inst_tester.is_pkg_in_testing(pkg_id): if inst_tester.is_pkg_in_the_suite(pkg_id):
if pkg_name in suite_info.target_suite.sources: if pkg_name in suite_info.target_suite.sources:
# sanity check, this shouldn't happen # sanity check, this shouldn't happen
raise(KeyError) raise(KeyError)

Loading…
Cancel
Save