mirror of
https://git.launchpad.net/~ubuntu-release/britney/+git/britney2-ubuntu
synced 2025-05-16 04:51:32 +00:00
inst-tester: Attempt to avoid needing to backtrack
When trying to break a choice, try the candidate out and see if we can pick it without any consequences. Basically, if the candidate causes no new conflicts or choices, we can safely pick it. Signed-off-by: Niels Thykier <niels@thykier.net>
This commit is contained in:
parent
b68b77f73e
commit
d5384f03ff
@ -207,6 +207,7 @@ class InstallabilityTester(object):
|
|||||||
testing = self._testing
|
testing = self._testing
|
||||||
cbroken = self._cache_broken
|
cbroken = self._cache_broken
|
||||||
safe_set = self._safe_set
|
safe_set = self._safe_set
|
||||||
|
eqv_table = self._eqv_table
|
||||||
|
|
||||||
# Our installability verdict - start with "yes" and change if
|
# Our installability verdict - start with "yes" and change if
|
||||||
# prove otherwise.
|
# prove otherwise.
|
||||||
@ -248,7 +249,7 @@ class InstallabilityTester(object):
|
|||||||
|
|
||||||
# curry check_loop
|
# curry check_loop
|
||||||
check_loop = partial(self._check_loop, universe, testing,
|
check_loop = partial(self._check_loop, universe, testing,
|
||||||
self._eqv_table, musts, never, choices,
|
eqv_table, musts, never, choices,
|
||||||
cbroken)
|
cbroken)
|
||||||
|
|
||||||
|
|
||||||
@ -271,7 +272,7 @@ class InstallabilityTester(object):
|
|||||||
# of t via recursion (calls _check_inst). In this case
|
# of t via recursion (calls _check_inst). In this case
|
||||||
# check and choices are not (always) empty.
|
# check and choices are not (always) empty.
|
||||||
|
|
||||||
def _pick_choice(rebuild):
|
def _pick_choice(rebuild, set=set, len=len):
|
||||||
"""Picks a choice from choices and updates rebuild.
|
"""Picks a choice from choices and updates rebuild.
|
||||||
|
|
||||||
Prunes the choices and updates "rebuild" to reflect the
|
Prunes the choices and updates "rebuild" to reflect the
|
||||||
@ -330,18 +331,55 @@ class InstallabilityTester(object):
|
|||||||
last = next(choice) # pick one to go last
|
last = next(choice) # pick one to go last
|
||||||
for p in choice:
|
for p in choice:
|
||||||
musts_copy = musts.copy()
|
musts_copy = musts.copy()
|
||||||
never_copy = never.copy()
|
never_tmp = set()
|
||||||
choices_copy = choices.copy()
|
choices_tmp = set()
|
||||||
if self._check_inst(p, musts_copy, never_copy, choices_copy):
|
check_tmp = set([p])
|
||||||
|
if not self._check_loop(universe, testing, eqv_table,
|
||||||
|
musts_copy, never_tmp,
|
||||||
|
choices_tmp, cbroken,
|
||||||
|
check_tmp):
|
||||||
|
# p cannot be chosen/is broken (unlikely, but ...)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Test if we can pick p without any consequences.
|
||||||
|
# - when we can, we avoid a backtrack point.
|
||||||
|
if never_tmp <= never and choices_tmp <= rebuild:
|
||||||
|
# we can pick p without picking up new conflicts
|
||||||
|
# or unresolved choices. Therefore we commit to
|
||||||
|
# using p.
|
||||||
|
#
|
||||||
|
# NB: Optimally, we would go to the start of this
|
||||||
|
# routine, but to conserve stack-space, we return
|
||||||
|
# and expect to be called again later.
|
||||||
|
musts.update(musts_copy)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not musts.isdisjoint(never_tmp):
|
||||||
|
# If we pick p, we will definitely end up making
|
||||||
|
# t uninstallable, so p is a no-go.
|
||||||
|
continue
|
||||||
|
|
||||||
|
# We are not sure that p is safe, setup a backtrack
|
||||||
|
# point and recurse.
|
||||||
|
never_tmp |= never
|
||||||
|
choices_tmp |= rebuild
|
||||||
|
if self._check_inst(p, musts_copy, never_tmp,
|
||||||
|
choices_tmp):
|
||||||
|
# Success, p was a valid choice and made it all
|
||||||
|
# installable
|
||||||
return True
|
return True
|
||||||
# If we get here, we failed to find something that would satisfy choice (without breaking
|
|
||||||
# the installability of t). This means p cannot be used to satisfy the dependencies, so
|
# If we get here, we failed to find something that
|
||||||
# pretend to conflict with it - hopefully it will reduce future choices.
|
# would satisfy choice (without breaking the
|
||||||
|
# installability of t). This means p cannot be used
|
||||||
|
# to satisfy the dependencies, so pretend to conflict
|
||||||
|
# with it - hopefully it will reduce future choices.
|
||||||
never.add(p)
|
never.add(p)
|
||||||
|
|
||||||
# Optimization for the last case; avoid the recursive call and just
|
# Optimization for the last case; avoid the recursive call
|
||||||
# assume the last will lead to a solution. If it doesn't there is
|
# and just assume the last will lead to a solution. If it
|
||||||
# no solution and if it does, we don't have to back-track anyway.
|
# doesn't there is no solution and if it does, we don't
|
||||||
|
# have to back-track anyway.
|
||||||
check.add(last)
|
check.add(last)
|
||||||
musts.add(last)
|
musts.add(last)
|
||||||
return False
|
return False
|
||||||
|
Loading…
x
Reference in New Issue
Block a user