commit: d1e8d3468d0cee24480f6cbe16b2ca82ec7dc9fa Author: Zac Medico <zmedico <AT> gentoo <DOT> org> AuthorDate: Sat Sep 13 00:32:53 2014 +0000 Commit: Brian Dolbec <brian.dolbec <AT> gmail <DOT> com> CommitDate: Mon Sep 15 04:00:15 2014 +0000 URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=d1e8d346
dep_zapdeps: fix bug #522652 For cases such as || ( X <A-2 ), where X is unsatisfiable and A-1 is installed, fix dep_zapdeps to make the correct choice. --- pym/portage/dep/dep_check.py | 10 ++++ pym/portage/tests/resolver/test_or_choices.py | 73 +++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py index 22eed96..4386b5e 100644 --- a/pym/portage/dep/dep_check.py +++ b/pym/portage/dep/dep_check.py @@ -287,6 +287,7 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): unsat_use_non_installed = [] other_installed = [] other_installed_some = [] + other_installed_any_slot = [] other = [] # unsat_use_* must come after preferred_non_installed @@ -301,6 +302,7 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): unsat_use_non_installed, other_installed, other_installed_some, + other_installed_any_slot, other, ) @@ -504,6 +506,14 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): other_installed.append(this_choice) elif some_installed: other_installed_some.append(this_choice) + + # Use Atom(atom.cp) for a somewhat "fuzzy" match, since + # the whole atom may be too specific. For example, see + # bug #522652, where using the whole atom leads to an + # unsatisfiable choice. + elif any(vardb.match(Atom(atom.cp)) for atom in atoms + if not atom.blocker): + other_installed_any_slot.append(this_choice) else: other.append(this_choice) diff --git a/pym/portage/tests/resolver/test_or_choices.py b/pym/portage/tests/resolver/test_or_choices.py index 90e6814..d9d14f0 100644 --- a/pym/portage/tests/resolver/test_or_choices.py +++ b/pym/portage/tests/resolver/test_or_choices.py @@ -132,3 +132,76 @@ class OrChoicesTestCase(TestCase): self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup() + + + def testInitiallyUnsatisfied(self): + + ebuilds = { + + "app-misc/A-1" : { + "EAPI": "5", + "SLOT": "0/1" + }, + + "app-misc/A-2" : { + "EAPI": "5", + "SLOT": "0/2" + }, + + "app-misc/B-0" : { + "EAPI": "5", + "RDEPEND": "app-misc/A:=" + }, + + "app-misc/C-0" : { + "EAPI": "5", + "RDEPEND": "|| ( app-misc/X <app-misc/A-2 )" + }, + + } + + installed = { + + "app-misc/A-1" : { + "EAPI": "5", + "SLOT": "0/1" + }, + + "app-misc/B-0" : { + "EAPI": "5", + "RDEPEND": "app-misc/A:0/1=" + }, + + "app-misc/C-0" : { + "EAPI": "5", + "RDEPEND": "|| ( app-misc/X <app-misc/A-2 )" + }, + + } + + world = ["app-misc/B", "app-misc/C"] + + test_cases = ( + + # Test bug #522652, where the unsatisfiable app-misc/X + # atom is selected, and the dependency is placed into + # _initially_unsatisfied_deps where it is ignored, causing + # upgrade to app-misc/A-2 (breaking a dependency of + # app-misc/C-0). + ResolverPlaygroundTestCase( + ["app-misc/A"], + options = {}, + success = True, + mergelist = ['app-misc/A-1'] + ), + + ) + + 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()