Fix check_reverse_dependencies to ignore dependencies of parent packages
that could be uninstalled in order to solve a blocker conflict. This case
is similar to the one from bug 584626, except that the relevant parent
package is in an older slot which is blocked by a newer slot. In this
case, the _upgrade_available method returns False, because the package
in the older slot is the highest version version available for its
slot. Therefore, a new _in_blocker_conflict method is needed to detect
parent packages that cold be uninstalled. The included unit test fails
without this fix.
Since the _in_blocker_conflict method requires information that is
collected by the _validate_blockers method, the _validate_blockers
method now has to be called before the _process_slot_conflict and
_slot_operator_trigger_reinstalls methods.
X-Gentoo-bug: 612772
X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=612772
---
pym/_emerge/depgraph.py| 59 ---
.../resolver/test_slot_operator_exclusive_slots.py | 109 +
2 files changed, 155 insertions(+), 13 deletions(-)
create mode 100644
pym/portage/tests/resolver/test_slot_operator_exclusive_slots.py
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index 1379b05..96b6d5f 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -387,7 +387,10 @@ class _dynamic_depgraph_config(object):
# Contains only unsolvable Package -> Blocker edges
self._unsolvable_blockers = digraph()
# Contains all Blocker -> Blocked Package edges
- self._blocked_pkgs = digraph()
+ # Do not initialized this until the depgraph _validate_blockers
+ # method is called, so that the _in_blocker_conflict method can
+ # assert that _validate_blockers has been called first.
+ self._blocked_pkgs = None
# Contains world packages that have been protected from
# uninstallation but may not have been added to the graph
# if the graph is not complete yet.
@@ -1466,9 +1469,22 @@ class depgraph(object):
self._solve_non_slot_operator_slot_conflicts()
+ if not self._validate_blockers():
+ # Blockers don't trigger the _skip_restart flag, since
+ # backtracking may solve blockers when it solves slot
+ # conflicts (or by blind luck).
+ raise self._unknown_internal_error()
+
+ # Both _process_slot_conflict and
_slot_operator_trigger_reinstalls
+ # can call _slot_operator_update_probe, which requires that
+ # self._dynamic_config._blocked_pkgs has been initialized by a
+ # call to the _validate_blockers method.
for conflict in
self._dynamic_config._package_tracker.slot_conflicts():
self._process_slot_conflict(conflict)
+ if self._dynamic_config._allow_backtracking:
+ self._slot_operator_trigger_reinstalls()
+
def _process_slot_conflict(self, conflict):
"""
Process slot conflict data to identify specific atoms which
@@ -1829,9 +1845,12 @@ class depgraph(object):
not
self._frozen_config.excluded_pkgs.
findAtomForPackage(parent,
modified_use=self._pkg_use_enabled(parent)) and
-
self._upgrade_available(parent)):
+
(self._upgrade_available(parent) or
+ (parent.installed and
self._in_blocker_conflict(parent:
# This parent may be
irrelevant, since an
- # update is available (see bug
584626).
+ # update is available (see bug
584626), or
+ # it could be uninstalled in
order to solve
+ # a blocker conflict (bug
612772).
continue
atom_set =
InternalPackageSet(initial_atoms=(atom,),
@@ -2125,6 +2144,24 @@ class depgraph(object):
self._dynamic_config._need_restart = True
+ def _in_blocker_conflict(self, pkg):
+ """
+ Check if pkg is involved in a blocker conflict. This method
+ only works after the _validate_blockers method has been called.
+ """
+
+ if self._dynamic_config._blocked_pkgs is None:
+ raise AssertionError(
+ '_in_blocker_conflict called