|
|
@ -328,7 +328,7 @@ class InstallabilityTester(object):
|
|
|
|
#
|
|
|
|
#
|
|
|
|
# * A package is installable if never and musts are disjointed
|
|
|
|
# * A package is installable if never and musts are disjointed
|
|
|
|
# and both check and choices are empty.
|
|
|
|
# and both check and choices are empty.
|
|
|
|
# - exception: resolve_choice may determine the installability
|
|
|
|
# - exception: resolve_choices may determine the installability
|
|
|
|
# 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.
|
|
|
|
|
|
|
|
|
|
|
@ -403,12 +403,12 @@ class InstallabilityTester(object):
|
|
|
|
verdict = False
|
|
|
|
verdict = False
|
|
|
|
break
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
while not check and rebuild:
|
|
|
|
if not check and rebuild:
|
|
|
|
# We have to "guess" now, which is always fun, but not cheap. We
|
|
|
|
# We have to "guess" now, which is always fun, but not cheap. We
|
|
|
|
# stop guessing:
|
|
|
|
# stop guessing:
|
|
|
|
# - once we run out of choices to make (obviously), OR
|
|
|
|
# - once we run out of choices to make (obviously), OR
|
|
|
|
# - if one of the choices exhaust all but one option
|
|
|
|
# - if one of the choices exhaust all but one option
|
|
|
|
if self.resolve_choice(check, musts, never, rebuild):
|
|
|
|
if self.resolve_choices(check, musts, never, rebuild):
|
|
|
|
# The recursive call have already updated the
|
|
|
|
# The recursive call have already updated the
|
|
|
|
# cache so there is not point in doing it again.
|
|
|
|
# cache so there is not point in doing it again.
|
|
|
|
return True
|
|
|
|
return True
|
|
|
@ -423,15 +423,19 @@ class InstallabilityTester(object):
|
|
|
|
|
|
|
|
|
|
|
|
return verdict
|
|
|
|
return verdict
|
|
|
|
|
|
|
|
|
|
|
|
def resolve_choice(self, check, musts, never, choices):
|
|
|
|
def resolve_choices(self, check, musts, never, choices):
|
|
|
|
universe = self._universe
|
|
|
|
universe = self._universe
|
|
|
|
testing = self._testing
|
|
|
|
testing = self._testing
|
|
|
|
eqv_table = self._eqv_table
|
|
|
|
eqv_table = self._eqv_table
|
|
|
|
stats = self._stats
|
|
|
|
stats = self._stats
|
|
|
|
cbroken = self._cache_broken
|
|
|
|
cbroken = self._cache_broken
|
|
|
|
|
|
|
|
|
|
|
|
choice = iter(choices.pop())
|
|
|
|
while choices:
|
|
|
|
|
|
|
|
choice_options = choices.pop()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
choice = iter(choice_options)
|
|
|
|
last = next(choice) # pick one to go last
|
|
|
|
last = next(choice) # pick one to go last
|
|
|
|
|
|
|
|
solved = False
|
|
|
|
for p in choice:
|
|
|
|
for p in choice:
|
|
|
|
musts_copy = musts.copy()
|
|
|
|
musts_copy = musts.copy()
|
|
|
|
never_tmp = set()
|
|
|
|
never_tmp = set()
|
|
|
@ -450,13 +454,10 @@ class InstallabilityTester(object):
|
|
|
|
# we can pick p without picking up new conflicts
|
|
|
|
# we can pick p without picking up new conflicts
|
|
|
|
# or unresolved choices. Therefore we commit to
|
|
|
|
# or unresolved choices. Therefore we commit to
|
|
|
|
# using p.
|
|
|
|
# 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)
|
|
|
|
musts.update(musts_copy)
|
|
|
|
stats.choice_resolved_without_restore_point += 1
|
|
|
|
stats.choice_resolved_without_restore_point += 1
|
|
|
|
return False
|
|
|
|
solved = True
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
if not musts.isdisjoint(never_tmp):
|
|
|
|
if not musts.isdisjoint(never_tmp):
|
|
|
|
# If we pick p, we will definitely end up making
|
|
|
|
# If we pick p, we will definitely end up making
|
|
|
@ -482,6 +483,7 @@ class InstallabilityTester(object):
|
|
|
|
never.add(p)
|
|
|
|
never.add(p)
|
|
|
|
stats.backtrace_restore_point_used += 1
|
|
|
|
stats.backtrace_restore_point_used += 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not solved:
|
|
|
|
# Optimization for the last case; avoid the recursive call
|
|
|
|
# Optimization for the last case; avoid the recursive call
|
|
|
|
# and just assume the last will lead to a solution. If it
|
|
|
|
# and just assume the last will lead to a solution. If it
|
|
|
|
# doesn't there is no solution and if it does, we don't
|
|
|
|
# doesn't there is no solution and if it does, we don't
|
|
|
|