From 468adcc31f8b97134a5a67a621e1d32a82bc6ffb Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Wed, 13 Feb 2013 20:45:40 -0800 Subject: [PATCH] slot_operator_replace_installed: check available This fixes a case where it could try to pull in an unavailable SLOT. --- pym/_emerge/depgraph.py | 47 +++++++++++++-- ...est_regular_slot_change_without_revbump.py | 59 +++++++++++++++++++ 2 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 pym/portage/tests/resolver/test_regular_slot_change_without_revbump.py diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index e0ea895a7..bab1c32aa 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -1104,7 +1104,9 @@ class depgraph(object): # trigger replacement of installed packages if necessary reinstalls = set() if child.installed: - reinstalls.add((child.root, child.slot_atom)) + replacement_atom = self._replace_installed_atom(child) + if replacement_atom is not None: + reinstalls.add((child.root, replacement_atom)) if reinstalls: config.setdefault("slot_operator_replace_installed", set()).update(reinstalls) @@ -1145,9 +1147,13 @@ class depgraph(object): # trigger replacement of installed packages if necessary abi_reinstalls = set() if dep.parent.installed: - abi_reinstalls.add((dep.parent.root, dep.parent.slot_atom)) + replacement_atom = self._replace_installed_atom(dep.parent) + if replacement_atom is not None: + abi_reinstalls.add((dep.parent.root, replacement_atom)) if new_child_slot is None and child.installed: - abi_reinstalls.add((child.root, child.slot_atom)) + replacement_atom = self._replace_installed_atom(child) + if replacement_atom is not None: + abi_reinstalls.add((child.root, replacement_atom)) if abi_reinstalls: config.setdefault("slot_operator_replace_installed", set()).update(abi_reinstalls) @@ -1363,7 +1369,9 @@ class depgraph(object): # trigger replacement of installed packages if necessary reinstalls = set() if parent.installed: - reinstalls.add((parent.root, parent.slot_atom)) + replacement_atom = self._replace_installed_atom(parent) + if replacement_atom is not None: + reinstalls.add((parent.root, replacement_atom)) if reinstalls: config.setdefault("slot_operator_replace_installed", set()).update(reinstalls) @@ -1421,6 +1429,37 @@ class depgraph(object): continue yield pkg + def _replace_installed_atom(self, inst_pkg): + """ + Given an installed package, generate an atom suitable for + slot_operator_replace_installed backtracking info. The replacement + SLOT may differ from the installed SLOT, so first search by cpv. + """ + built_pkgs = [] + for pkg in self._iter_similar_available(inst_pkg, + Atom("=%s" % inst_pkg.cpv)): + if not pkg.built: + return pkg.slot_atom + elif not pkg.installed: + # avoid using SLOT from a built instance + built_pkgs.append(pkg) + + for pkg in self._iter_similar_available(inst_pkg, inst_pkg.slot_atom): + if not pkg.built: + return pkg.slot_atom + elif not pkg.installed: + # avoid using SLOT from a built instance + built_pkgs.append(pkg) + + if built_pkgs: + best_version = None + for pkg in built_pkgs: + if best_version is None or pkg > best_version: + best_version = pkg + return best_version.slot_atom + + return None + def _slot_operator_trigger_reinstalls(self): """ Search for packages with slot-operator deps on older slots, and schedule diff --git a/pym/portage/tests/resolver/test_regular_slot_change_without_revbump.py b/pym/portage/tests/resolver/test_regular_slot_change_without_revbump.py new file mode 100644 index 000000000..415277bc7 --- /dev/null +++ b/pym/portage/tests/resolver/test_regular_slot_change_without_revbump.py @@ -0,0 +1,59 @@ +# Copyright 2013 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.tests import TestCase +from portage.tests.resolver.ResolverPlayground import (ResolverPlayground, + ResolverPlaygroundTestCase) + +class RegularSlotChangeWithoutRevBumpTestCase(TestCase): + + def testRegularSlotChangeWithoutRevBumpTestCase(self): + + ebuilds = { + "dev-libs/boost-1.52.0" : { + "SLOT": "0" + }, + "app-office/libreoffice-4.0.0.2" : { + "EAPI": "5", + "DEPEND": ">=dev-libs/boost-1.46:=", + "RDEPEND": ">=dev-libs/boost-1.46:=", + }, + } + + binpkgs = { + "dev-libs/boost-1.52.0" : { + "SLOT": "1.52" + }, + } + + installed = { + "dev-libs/boost-1.52.0" : { + "SLOT": "1.52" + }, + } + + world = [] + + test_cases = ( + # Test that @__auto_slot_operator_replace_installed__ + # pulls in the available slot, even though it's + # different from the installed slot (0 instead of 1.52). + ResolverPlaygroundTestCase( + ["app-office/libreoffice"], + options = {"--oneshot": True, "--usepkg": True}, + success = True, + mergelist = [ + 'dev-libs/boost-1.52.0', + 'app-office/libreoffice-4.0.0.2' + ] + ), + ) + + playground = ResolverPlayground(ebuilds=ebuilds, binpkgs=binpkgs, + installed=installed, world=world, debug=False) + try: + for test_case in test_cases: + playground.run_TestCase(test_case) + self.assertEqual(test_case.test_success, True, test_case.fail_msg) + finally: + playground.cleanup() -- 2.26.2