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


Reply via email to