commit: e2134e9f72a86734552bb67e9414a017cfc4ea51 Author: Zac Medico <zmedico <AT> gentoo <DOT> org> AuthorDate: Sat Jan 20 00:28:42 2018 +0000 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> CommitDate: Sat Jan 20 23:08:42 2018 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=e2134e9f
dep_zapdeps: prefer choices with fewer new slots (bug 645002) Prefer choices with fewer new slots, rather than choices with the lowest total number of slots. This fixes a case triggered by the catalyst stage1 build, where paludis was selected to satisfy perl-cleaner dependencies because that choice happened to have a smaller number of slots: || ( ( sys-apps/portage app-portage/portage-utils ) sys-apps/pkgcore sys-apps/paludis ) Bug: https://bugs.gentoo.org/645002 Fixes: 9fdaf9bdbdf5 ("dep_check: use DNF to optimize overlapping virtual || deps (bug 632026)") Tested-by: Ben Kohler <bkohler <AT> gmail.com> pym/portage/dep/dep_check.py | 14 ++-- .../resolver/test_virtual_minimize_children.py | 85 +++++++++++++++++++++- 2 files changed, 93 insertions(+), 6 deletions(-) diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py index 291626f56..7cf338819 100644 --- a/pym/portage/dep/dep_check.py +++ b/pym/portage/dep/dep_check.py @@ -1,4 +1,4 @@ -# Copyright 2010-2015 Gentoo Foundation +# Copyright 2010-2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from __future__ import unicode_literals @@ -296,7 +296,7 @@ def dep_eval(deplist): class _dep_choice(SlotObject): __slots__ = ('atoms', 'slot_map', 'cp_map', 'all_available', - 'all_installed_slots') + 'all_installed_slots', 'new_slot_count') def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): """ @@ -498,9 +498,13 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): if current_higher or (all_match_current and not all_match_previous): cp_map[avail_pkg.cp] = avail_pkg + new_slot_count = (len(slot_map) if graph_db is None else + sum(not graph_db.match_pkgs(slot_atom) for slot_atom in slot_map)) + this_choice = _dep_choice(atoms=atoms, slot_map=slot_map, cp_map=cp_map, all_available=all_available, - all_installed_slots=False) + all_installed_slots=False, + new_slot_count=new_slot_count) if all_available: # The "all installed" criterion is not version or slot specific. # If any version of a package is already in the graph then we @@ -655,8 +659,8 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): if len(choices) < 2: continue # Prefer choices with all_installed_slots for bug #480736, and - # choices with a smaller number of packages for bug #632026. - choices.sort(key=lambda x: (not x.all_installed_slots, len(x.slot_map))) + # choices with a smaller number of new slots for bug #632026. + choices.sort(key=lambda x: (not x.all_installed_slots, x.new_slot_count)) for choice_1 in choices[1:]: cps = set(choice_1.cp_map) for choice_2 in choices: diff --git a/pym/portage/tests/resolver/test_virtual_minimize_children.py b/pym/portage/tests/resolver/test_virtual_minimize_children.py index 83ae34e77..6eb0409f2 100644 --- a/pym/portage/tests/resolver/test_virtual_minimize_children.py +++ b/pym/portage/tests/resolver/test_virtual_minimize_children.py @@ -1,4 +1,4 @@ -# Copyright 2017 Gentoo Foundation +# Copyright 2017-2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from portage.tests import TestCase @@ -143,3 +143,86 @@ class VirtualMinimizeChildrenTestCase(TestCase): finally: playground.debug = False playground.cleanup() + + def testVirtualPackageManager(self): + ebuilds = { + 'app-admin/perl-cleaner-2.25': { + 'RDEPEND': ''' + || ( + ( sys-apps/portage app-portage/portage-utils ) + sys-apps/pkgcore + sys-apps/paludis + )''' + }, + 'app-portage/portage-utils-0.64': {}, + 'sys-apps/paludis-2.6.0': {}, + 'sys-apps/portage-2.3.19-r1': {}, + 'virtual/package-manager-0': { + 'RDEPEND': ''' + || ( + sys-apps/portage + sys-apps/paludis + sys-apps/pkgcore + )''' + }, + } + + test_cases = ( + # Test bug 645002, where we want to prefer choices + # based on the number of new slots rather than the total + # number of slots. This is necessary so that perl-cleaner's + # deps are satisfied by the ( portage portage-utils ) + # choice which has a larger total number of slots than the + # paludis choice. + ResolverPlaygroundTestCase( + [ + 'app-admin/perl-cleaner', + 'virtual/package-manager', + 'app-portage/portage-utils', + ], + all_permutations=True, + success=True, + ambiguous_merge_order=True, + mergelist=( + ( + 'sys-apps/portage-2.3.19-r1', + 'app-portage/portage-utils-0.64', + 'app-admin/perl-cleaner-2.25', + 'virtual/package-manager-0', + ), + ) + ), + # Test paludis preference. In this case, if paludis is not + # included in the argument atoms then the result varies + # depending on whether the app-admin/perl-cleaner or + # virtual/package-manager dependencies are evaluated first! + # Therefore, include paludis in the argument atoms. + ResolverPlaygroundTestCase( + [ + 'app-admin/perl-cleaner', + 'virtual/package-manager', + 'sys-apps/paludis', + ], + all_permutations=True, + success=True, + ambiguous_merge_order=True, + mergelist=( + 'sys-apps/paludis-2.6.0', + ( + 'app-admin/perl-cleaner-2.25', + 'virtual/package-manager-0', + ), + ) + ), + ) + + playground = ResolverPlayground(debug=False, ebuilds=ebuilds) + + 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.debug = False + playground.cleanup()