Prefer to install a new package in order to allow upgrade of an installed package. This generalizes the code from bug 635540 so that it both allows desirable upgrades and prevents unwanted downgrades.
Fixes: 7c58e3737616 ("dep_zapdeps: install new package, avoid downgrade (bug 635540)") Bug: https://bugs.gentoo.org/643974 --- pym/portage/dep/dep_check.py | 11 ++- .../tests/resolver/test_or_upgrade_installed.py | 94 ++++++++++++++++++++++ 2 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 pym/portage/tests/resolver/test_or_upgrade_installed.py diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py index 2bb9dc339..291626f56 100644 --- a/pym/portage/dep/dep_check.py +++ b/pym/portage/dep/dep_check.py @@ -366,10 +366,8 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): want_update_pkg = trees[myroot].get("want_update_pkg") downgrade_probe = trees[myroot].get("downgrade_probe") vardb = None - vardb_match_pkgs = None if "vartree" in trees[myroot]: vardb = trees[myroot]["vartree"].dbapi - vardb_match_pkgs = getattr(vardb, 'match_pkgs', None) if use_binaries: mydbapi = trees[myroot]["bintree"].dbapi else: @@ -465,10 +463,11 @@ 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 vardb_match_pkgs is not None and downgrade_probe is not None: - inst_pkg = vardb_match_pkgs(avail_slot) - if (inst_pkg and avail_pkg < inst_pkg[-1] and - not downgrade_probe(inst_pkg[-1])): + if downgrade_probe is not None: + highest_in_slot = mydbapi_match_pkgs(avail_slot) + if (avail_pkg and highest_in_slot and + avail_pkg < highest_in_slot[-1] and + not downgrade_probe(avail_pkg)): 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 new file mode 100644 index 000000000..70703a614 --- /dev/null +++ b/pym/portage/tests/resolver/test_or_upgrade_installed.py @@ -0,0 +1,94 @@ +# Copyright 2018 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 OrUpgradeInstalledTestCase(TestCase): + + def testOrUpgradeInstalled(self): + ebuilds = { + 'net-misc/foo-1': { + 'EAPI': '6', + 'RDEPEND': '|| ( sys-libs/glibc[rpc(-)] net-libs/libtirpc )' + }, + 'net-libs/libtirpc-1': { + 'EAPI': '6', + }, + 'sys-libs/glibc-2.26': { + 'EAPI': '6', + 'IUSE': '' + }, + 'sys-libs/glibc-2.24': { + 'EAPI': '6', + 'IUSE': '+rpc' + }, + } + + installed = { + 'sys-libs/glibc-2.24': { + 'EAPI': '6', + 'IUSE': '+rpc', + 'USE': 'rpc', + }, + } + + world = ['sys-libs/glibc'] + + test_cases = ( + # Test bug 643974, where we need to install libtirpc + # in order to upgrade glibc. + ResolverPlaygroundTestCase( + ['net-misc/foo', '@world'], + options={'--update': True, '--deep': True}, + success=True, + mergelist=['net-libs/libtirpc-1', 'sys-libs/glibc-2.26', 'net-misc/foo-1'] + ), + ) + + 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() + + # In some cases it's necessary to avoid upgrade due to + # the package being masked. + user_config = { + "package.mask" : ( + ">=sys-libs/glibc-2.26", + ), + } + + test_cases = ( + ResolverPlaygroundTestCase( + ['net-misc/foo', '@world'], + options={'--update': True, '--deep': True}, + success=True, + mergelist=[ + 'net-misc/foo-1', + ] + ), + ) + + playground = ResolverPlayground(debug=False, + ebuilds=ebuilds, installed=installed, world=world, + user_config=user_config) + + 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