aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2012-10-26 07:43:20 (GMT)
committerZac Medico <zmedico@gentoo.org>2012-10-26 07:43:20 (GMT)
commit222dfa56e8fb311f4bea54012bdfd5d1a474d56c (patch)
treed393e941291ceaf2595ef68948734ff35a3ef596
parentAdd test case for bug #439688. (diff)
downloadportage-222dfa56e8fb311f4bea54012bdfd5d1a474d56c.zip
portage-222dfa56e8fb311f4bea54012bdfd5d1a474d56c.tar.gz
portage-222dfa56e8fb311f4bea54012bdfd5d1a474d56c.tar.bz2
backtracking: discard extra rebuilds, bug #439688
-rw-r--r--pym/_emerge/depgraph.py26
-rw-r--r--pym/_emerge/resolver/backtracking.py26
-rw-r--r--pym/portage/tests/resolver/test_slot_conflict_rebuild.py6
3 files changed, 50 insertions, 8 deletions
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index e129a81..fd5dfe8 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -415,6 +415,7 @@ class _dynamic_depgraph_config(object):
self._needed_use_config_changes = backtrack_parameters.needed_use_config_changes
self._runtime_pkg_mask = backtrack_parameters.runtime_pkg_mask
self._slot_operator_replace_installed = backtrack_parameters.slot_operator_replace_installed
+ self._prune_rebuilds = backtrack_parameters.prune_rebuilds
self._need_restart = False
# For conditions that always require user intervention, such as
# unsatisfied REQUIRED_USE (currently has no autounmask support).
@@ -633,7 +634,7 @@ class depgraph(object):
line = colorize("INFORM", line)
writemsg(line + "\n", noiselevel=-1)
- def _show_missed_update(self):
+ def _get_missed_updates(self):
# In order to minimize noise, show only the highest
# missed update from each SLOT.
@@ -659,6 +660,12 @@ class depgraph(object):
missed_updates[k] = (pkg, mask_type, parent_atoms)
break
+ return missed_updates
+
+ def _show_missed_update(self):
+
+ missed_updates = self._get_missed_updates()
+
if not missed_updates:
return
@@ -2737,6 +2744,23 @@ class depgraph(object):
self.need_restart():
return False, myfavorites
+ if not self._dynamic_config._prune_rebuilds and \
+ self._dynamic_config._slot_operator_replace_installed and \
+ self._get_missed_updates():
+ # When there are missed updates, we might have triggered
+ # some unnecessary rebuilds (see bug #439688). So, prune
+ # all the rebuilds and backtrack with the problematic
+ # updates masked. The next backtrack run should pull in
+ # any rebuilds that are really needed, and this
+ # prune_rebuilds path should never be entered more than
+ # once in a series of backtracking nodes (in order to
+ # avoid a backtracking loop).
+ backtrack_infos = self._dynamic_config._backtrack_infos
+ config = backtrack_infos.setdefault("config", {})
+ config["prune_rebuilds"] = True
+ self._dynamic_config._need_restart = True
+ return False, myfavorites
+
# Any failures except those due to autounmask *alone* should return
# before this point, since the success_without_autounmask flag that's
# set below is reserved for cases where there are *zero* other
diff --git a/pym/_emerge/resolver/backtracking.py b/pym/_emerge/resolver/backtracking.py
index 5456ea4..c29b9d4 100644
--- a/pym/_emerge/resolver/backtracking.py
+++ b/pym/_emerge/resolver/backtracking.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2011 Gentoo Foundation
+# Copyright 2010-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
import copy
@@ -7,8 +7,8 @@ class BacktrackParameter(object):
__slots__ = (
"needed_unstable_keywords", "runtime_pkg_mask", "needed_use_config_changes", "needed_license_changes",
- "rebuild_list", "reinstall_list", "needed_p_mask_changes",
- "slot_operator_replace_installed"
+ "prune_rebuilds", "rebuild_list", "reinstall_list", "needed_p_mask_changes",
+ "slot_operator_mask_built", "slot_operator_replace_installed"
)
def __init__(self):
@@ -20,6 +20,8 @@ class BacktrackParameter(object):
self.rebuild_list = set()
self.reinstall_list = set()
self.slot_operator_replace_installed = set()
+ self.slot_operator_mask_built = set()
+ self.prune_rebuilds = False
def __deepcopy__(self, memo=None):
if memo is None:
@@ -36,6 +38,8 @@ class BacktrackParameter(object):
result.rebuild_list = copy.copy(self.rebuild_list)
result.reinstall_list = copy.copy(self.reinstall_list)
result.slot_operator_replace_installed = copy.copy(self.slot_operator_replace_installed)
+ result.slot_operator_mask_built = self.slot_operator_mask_built.copy()
+ result.prune_rebuilds = self.prune_rebuilds
# runtime_pkg_mask contains nested dicts that must also be copied
result.runtime_pkg_mask = {}
@@ -52,7 +56,9 @@ class BacktrackParameter(object):
self.needed_license_changes == other.needed_license_changes and \
self.rebuild_list == other.rebuild_list and \
self.reinstall_list == other.reinstall_list and \
- self.slot_operator_replace_installed == other.slot_operator_replace_installed
+ self.slot_operator_replace_installed == other.slot_operator_replace_installed and \
+ self.slot_operator_mask_built == other.slot_operator_mask_built and \
+ self.prune_rebuilds == other.prune_rebuilds
class _BacktrackNode(object):
@@ -193,6 +199,7 @@ class Backtracker(object):
elif change == "slot_conflict_abi":
new_node.terminal = False
elif change == "slot_operator_mask_built":
+ para.slot_operator_mask_built.update(data)
for pkg, mask_reasons in data.items():
para.runtime_pkg_mask.setdefault(pkg,
{}).update(mask_reasons)
@@ -202,6 +209,17 @@ class Backtracker(object):
para.rebuild_list.update(data)
elif change == "reinstall_list":
para.reinstall_list.update(data)
+ elif change == "prune_rebuilds":
+ para.prune_rebuilds = True
+ para.slot_operator_replace_installed.clear()
+ for pkg in para.slot_operator_mask_built:
+ runtime_masks = para.runtime_pkg_mask.get(pkg)
+ if runtime_masks is None:
+ continue
+ runtime_masks.pop("slot_operator_mask_built", None)
+ if not runtime_masks:
+ para.runtime_pkg_mask.pop(pkg)
+ para.slot_operator_mask_built.clear()
self._add(new_node, explore=explore)
self._current_node = new_node
diff --git a/pym/portage/tests/resolver/test_slot_conflict_rebuild.py b/pym/portage/tests/resolver/test_slot_conflict_rebuild.py
index e255e2a..5ce2329 100644
--- a/pym/portage/tests/resolver/test_slot_conflict_rebuild.py
+++ b/pym/portage/tests/resolver/test_slot_conflict_rebuild.py
@@ -60,13 +60,13 @@ class SlotConflictRebuildTestCase(TestCase):
test_cases = (
- # Demonstrate bug #439688, where a slot conflict prevents
- # an upgrade and triggers unnecessary rebuilds.
+ # Test bug #439688, where a slot conflict prevents an
+ # upgrade and we don't want to trigger unnecessary rebuilds.
ResolverPlaygroundTestCase(
["@world"],
options = {"--update": True, "--deep": True},
success = True,
- mergelist = ["app-misc/A-1", "app-misc/B-0"]),
+ mergelist = []),
)