Allow new uninstallables from allow-uninst hint

When an allow-uninst hint is added for an unversioned binary package, items
are allowed to migrate, even if they make that binary package uninstallable
(on the architecture specified in the hint, if one was specified, or on all
architectures otherwise).

Using this hint should avoid using force-hint to allow specific breakage.

Signed-off-by: Ivo De Decker <ivodd@debian.org>
ubuntu/rebased
Ivo De Decker 5 years ago
parent 988b33d0ba
commit 93b46dde0d

@ -330,7 +330,7 @@ class Britney(object):
self._migration_item_factory = MigrationItemFactory(self.suite_info) self._migration_item_factory = MigrationItemFactory(self.suite_info)
self._hint_parser = HintParser(self._migration_item_factory) self._hint_parser = HintParser(self._migration_item_factory)
self._migration_manager = MigrationManager(self.options, self.suite_info, self.all_binaries, self.pkg_universe, self._migration_manager = MigrationManager(self.options, self.suite_info, self.all_binaries, self.pkg_universe,
self.constraints, self._migration_item_factory) self.constraints, self.allow_uninst, self._migration_item_factory)
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")
@ -1071,6 +1071,7 @@ class Britney(object):
# This usually only happens with hints # This usually only happens with hints
break_arches = set() break_arches = set()
better = is_nuninst_asgood_generous(self.constraints, better = is_nuninst_asgood_generous(self.constraints,
self.allow_uninst,
self.options.architectures, self.options.architectures,
self.nuninst_orig, self.nuninst_orig,
nuninst_end, nuninst_end,

@ -25,8 +25,9 @@ def compute_eqv_set(pkg_universe, updates, rms):
return eqv_set return eqv_set
def is_nuninst_worse(must_be_installable, nuninst_now_arch, nuninst_after_arch): def is_nuninst_worse(must_be_installable, nuninst_now_arch, nuninst_after_arch, allow_uninst):
if len(nuninst_after_arch) > len(nuninst_now_arch): if len(nuninst_after_arch - allow_uninst) > \
len(nuninst_now_arch - allow_uninst):
return True return True
regression = nuninst_after_arch - nuninst_now_arch regression = nuninst_after_arch - nuninst_now_arch
@ -37,12 +38,13 @@ def is_nuninst_worse(must_be_installable, nuninst_now_arch, nuninst_after_arch):
class MigrationManager(object): class MigrationManager(object):
def __init__(self, options, suite_info, all_binaries, pkg_universe, constraints, migration_item_factory): def __init__(self, options, suite_info, all_binaries, pkg_universe, constraints, allow_uninst, migration_item_factory):
self.options = options self.options = options
self.suite_info = suite_info self.suite_info = suite_info
self.all_binaries = all_binaries self.all_binaries = all_binaries
self.pkg_universe = pkg_universe self.pkg_universe = pkg_universe
self.constraints = constraints self.constraints = constraints
self.allow_uninst = allow_uninst
self._transactions = [] self._transactions = []
self._all_architectures = frozenset(self.options.architectures) self._all_architectures = frozenset(self.options.architectures)
self._migration_item_factory = migration_item_factory self._migration_item_factory = migration_item_factory
@ -450,7 +452,7 @@ class MigrationManager(object):
# if the uninstallability counter is worse than before, break the loop # if the uninstallability counter is worse than before, break the loop
if stop_on_first_regression: if stop_on_first_regression:
worse = is_nuninst_worse(must_be_installable, nuninst_now[arch], nuninst_after[arch]) worse = is_nuninst_worse(must_be_installable, nuninst_now[arch], nuninst_after[arch], self.allow_uninst[arch])
# ... except for a few special cases # ... except for a few special cases
if worse and ((not is_source_migration and arch not in new_arches) or if worse and ((not is_source_migration and arch not in new_arches) or

@ -334,7 +334,7 @@ def old_libraries(mi_factory, suite_info, outofsync_arches=frozenset()):
return removals return removals
def is_nuninst_asgood_generous(constraints, architectures, old, new, break_arches=frozenset()): def is_nuninst_asgood_generous(constraints, allow_uninst, architectures, old, new, break_arches=frozenset()):
"""Compares the nuninst counters and constraints to see if they improved """Compares the nuninst counters and constraints to see if they improved
Given a list of architectures, the previous and the current nuninst Given a list of architectures, the previous and the current nuninst
@ -355,7 +355,9 @@ def is_nuninst_asgood_generous(constraints, architectures, old, new, break_arche
for arch in architectures: for arch in architectures:
if arch in break_arches: if arch in break_arches:
continue continue
diff = diff + (len(new[arch]) - len(old[arch])) diff = diff + \
(len(new[arch] - allow_uninst[arch])
- len(old[arch] - allow_uninst[arch]))
if diff > 0: if diff > 0:
return False return False
must_be_installable = constraints['keep-installable'] must_be_installable = constraints['keep-installable']

Loading…
Cancel
Save