@ -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