From 8a23eb70eb289fc84d77754447b5f9a84b94b4e1 Mon Sep 17 00:00:00 2001 From: Sebastian Luther Date: Thu, 28 Nov 2013 11:34:09 +0100 Subject: [PATCH] Another slot operator bug (bug 486580, try 2) This time rebuilds are scheduled properly, but we might still forget to install the package that caused the rebuild. URL: https://bugs.gentoo.org/486580 --- pym/_emerge/depgraph.py | 48 +++++++++----- .../resolver/test_slot_conflict_rebuild.py | 63 +++++++++++++++++++ 2 files changed, 95 insertions(+), 16 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index b02d3473d..622d28841 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -2266,6 +2266,36 @@ class depgraph(object): finally: self._dynamic_config._autounmask = _autounmask_backup + def _ignore_dependency(self, atom, pkg, child, dep, mypriority, recurse_satisfied): + """ + In some cases, dep_check will return deps that shouldn't + be proccessed any further, so they are identified and + discarded here. Try to discard as few as possible since + discarded dependencies reduce the amount of information + available for optimization of merge order. + Don't ignore dependencies if pkg has a slot operator dependency on the child + and the child has changed slot/sub_slot. + """ + slot_operator_rebuild = False + if atom.slot_operator == '=' and \ + (pkg.root, pkg.slot_atom) in self._dynamic_config._slot_operator_replace_installed and \ + mypriority.satisfied and \ + mypriority.satisfied is not child and \ + mypriority.satisfied.installed and \ + not child.installed and \ + (child.slot != mypriority.satisfied.slot or child.sub_slot != mypriority.satisfied.sub_slot): + slot_operator_rebuild = True + + return not atom.blocker and \ + not recurse_satisfied and \ + mypriority.satisfied and \ + mypriority.satisfied.visible and \ + dep.child is not None and \ + not dep.child.installed and \ + self._dynamic_config._slot_pkg_map[dep.child.root].get( + dep.child.slot_atom) is None and \ + not slot_operator_rebuild + def _wrapped_add_pkg_dep_string(self, pkg, dep_root, dep_priority, dep_string, allow_unsatisfied): depth = pkg.depth + 1 @@ -2355,14 +2385,7 @@ class depgraph(object): # discarded dependencies reduce the amount of information # available for optimization of merge order. ignored = False - if not atom.blocker and \ - not recurse_satisfied and \ - mypriority.satisfied and \ - mypriority.satisfied.visible and \ - dep.child is not None and \ - not dep.child.installed and \ - self._dynamic_config._slot_pkg_map[dep.child.root].get( - dep.child.slot_atom) is None: + if self._ignore_dependency(atom, pkg, child, dep, mypriority, recurse_satisfied): myarg = None try: myarg = next(self._iter_atoms_for_pkg(dep.child), None) @@ -2465,14 +2488,7 @@ class depgraph(object): collapsed_parent=pkg, collapsed_priority=dep_priority) ignored = False - if not atom.blocker and \ - not recurse_satisfied and \ - mypriority.satisfied and \ - mypriority.satisfied.visible and \ - dep.child is not None and \ - not dep.child.installed and \ - self._dynamic_config._slot_pkg_map[dep.child.root].get( - dep.child.slot_atom) is None: + if self._ignore_dependency(atom, pkg, child, dep, mypriority, recurse_satisfied): myarg = None try: myarg = next(self._iter_atoms_for_pkg(dep.child), None) diff --git a/pym/portage/tests/resolver/test_slot_conflict_rebuild.py b/pym/portage/tests/resolver/test_slot_conflict_rebuild.py index 74f5cc146..e3c517d0c 100644 --- a/pym/portage/tests/resolver/test_slot_conflict_rebuild.py +++ b/pym/portage/tests/resolver/test_slot_conflict_rebuild.py @@ -181,6 +181,69 @@ class SlotConflictRebuildTestCase(TestCase): finally: playground.cleanup() + def testSlotConflictForgottenChild(self): + """ + Similar to testSlotConflictMassRebuild above, but this time the rebuilds are scheduled, + but the package causing the rebuild (the child) is not installed. + """ + ebuilds = { + + "app-misc/A-2" : { + "EAPI": "5", + "DEPEND": "app-misc/B:= app-misc/C", + "RDEPEND": "app-misc/B:= app-misc/C", + }, + + "app-misc/B-2" : { + "EAPI": "5", + "SLOT": "2" + }, + + "app-misc/C-1": { + "EAPI": "5", + "DEPEND": "app-misc/B:=", + "RDEPEND": "app-misc/B:=" + }, + } + + installed = { + "app-misc/A-1" : { + "EAPI": "5", + "DEPEND": "app-misc/B:1/1= app-misc/C", + "RDEPEND": "app-misc/B:1/1= app-misc/C", + }, + + "app-misc/B-1" : { + "EAPI": "5", + "SLOT": "1" + }, + + "app-misc/C-1": { + "EAPI": "5", + "DEPEND": "app-misc/B:1/1=", + "RDEPEND": "app-misc/B:1/1=" + }, + } + + test_cases = ( + ResolverPlaygroundTestCase( + ["app-misc/A"], + success = True, + mergelist = ['app-misc/B-2', 'app-misc/C-1', 'app-misc/A-2']), + ) + + world = [] + + playground = ResolverPlayground(ebuilds=ebuilds, + 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() + + def testSlotConflictDepChange(self): """ Bug 490362 -- 2.26.2