Fix the code from bug 643974 to set the installed_downgrade flag only if the selected newer package is either installed or in the graph. This is currently needed for appropriate handling of virtual/rust-1.19.0, since there's an upgrade to dev-lang/rust-1.23.0 available which may not be desired since it would mean that dev-lang/rust-bin-1.19.0 has to be installed in order to satisfy virtual/rust-1.19.0:
|| ( =dev-lang/rust-1.19.0* =dev-lang/rust-bin-1.19.0* ) So, the rust-bin choice is desirable only if the rust-1.23.0 package is already installed or in the graph. Fixes: 86ba22da7a2f ("dep_zapdeps: install new package, allow upgrade (bug 643974)") Bug: https://bugs.gentoo.org/645416 --- pym/portage/dep/dep_check.py | 10 ++-- .../tests/resolver/test_or_upgrade_installed.py | 59 ++++++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py index c56f545ec..7e5a3186e 100644 --- a/pym/portage/dep/dep_check.py +++ b/pym/portage/dep/dep_check.py @@ -463,11 +463,15 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): avail_pkg = avail_pkg_use avail_slot = Atom("%s:%s" % (atom.cp, avail_pkg.slot)) - if downgrade_probe is not None: + if downgrade_probe is not None and graph is not None: highest_in_slot = mydbapi_match_pkgs(avail_slot) + highest_in_slot = (highest_in_slot[-1] + if highest_in_slot else None) if (avail_pkg and highest_in_slot and - avail_pkg < highest_in_slot[-1] and - not downgrade_probe(avail_pkg)): + avail_pkg < highest_in_slot and + not downgrade_probe(avail_pkg) and + (highest_in_slot.installed or + highest_in_slot in graph)): installed_downgrade = True slot_map[avail_slot] = avail_pkg diff --git a/pym/portage/tests/resolver/test_or_upgrade_installed.py b/pym/portage/tests/resolver/test_or_upgrade_installed.py index 6e01d321d..7018e08de 100644 --- a/pym/portage/tests/resolver/test_or_upgrade_installed.py +++ b/pym/portage/tests/resolver/test_or_upgrade_installed.py @@ -99,3 +99,62 @@ class OrUpgradeInstalledTestCase(TestCase): finally: playground.debug = False playground.cleanup() + + def testVirtualRust(self): + ebuilds = { + 'dev-lang/rust-1.19.0': {}, + 'dev-lang/rust-1.23.0': {}, + 'dev-lang/rust-bin-1.19.0': {}, + 'virtual/rust-1.19.0': { + 'RDEPEND': '|| ( =dev-lang/rust-1.19.0* =dev-lang/rust-bin-1.19.0* )' + }, + } + + installed = { + 'dev-lang/rust-1.19.0': {}, + 'virtual/rust-1.19.0': { + 'RDEPEND': '|| ( =dev-lang/rust-1.19.0* =dev-lang/rust-bin-1.19.0* )' + }, + } + + world = ['virtual/rust'] + + test_cases = ( + # Test bug 645416, where rust-bin-1.19.0 was pulled in + # inappropriately due to the rust-1.23.0 update being + # available. + ResolverPlaygroundTestCase( + ['virtual/rust'], + options={'--update': True, '--deep': True}, + success=True, + mergelist=[] + ), + # Test upgrade to rust-1.23.0, which is only possible + # if rust-bin-1.19.0 is installed in order to satisfy + # virtual/rust-1.19.0. + ResolverPlaygroundTestCase( + ['=dev-lang/rust-1.23.0', 'virtual/rust'], + options={'--update': True, '--deep': True}, + all_permutations=True, + success=True, + ambiguous_merge_order=True, + mergelist=( + ( + 'dev-lang/rust-1.23.0', + 'dev-lang/rust-bin-1.19.0', + ), + ), + ), + ) + + playground = ResolverPlayground(debug=False, + ebuilds=ebuilds, installed=installed, world=world) + + 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() -- 2.13.6