mirror of
https://git.launchpad.net/~ubuntu-release/britney/+git/britney2-ubuntu
synced 2025-05-13 03:21:34 +00:00
Make InstallabilityTester suite agnostic
Signed-off-by: Niels Thykier <niels@thykier.net>
This commit is contained in:
parent
ced7b7b413
commit
7124313aa6
@ -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…
x
Reference in New Issue
Block a user