Use autounmask for subslot conflict, bug #461464.
authorZac Medico <zmedico@gentoo.org>
Tue, 19 Mar 2013 21:05:57 +0000 (14:05 -0700)
committerZac Medico <zmedico@gentoo.org>
Tue, 19 Mar 2013 21:05:57 +0000 (14:05 -0700)
pym/_emerge/depgraph.py
pym/portage/tests/resolver/test_slot_operator_autounmask.py [new file with mode: 0644]

index a17398c92cbb9ef1ad2673c7d39c415a87521963..308c583156195bb18cf2c1b2bf089004edef89cc 100644 (file)
@@ -1032,8 +1032,11 @@ class depgraph(object):
                                dep = Dependency(atom=atom, child=other_pkg,
                                        parent=parent, root=pkg.root)
 
-                               if self._slot_operator_update_probe(dep, slot_conflict=True):
-                                       self._slot_operator_update_backtrack(dep)
+                               new_dep = \
+                                       self._slot_operator_update_probe_slot_conflict(dep)
+                               if new_dep is not None:
+                                       self._slot_operator_update_backtrack(dep,
+                                               new_dep=new_dep)
                                        found_update = True
 
                return found_update
@@ -1117,7 +1120,8 @@ class depgraph(object):
 
                self._dynamic_config._need_restart = True
 
-       def _slot_operator_update_backtrack(self, dep, new_child_slot=None):
+       def _slot_operator_update_backtrack(self, dep, new_child_slot=None,
+               new_dep=None):
                if new_child_slot is None:
                        child = dep.child
                else:
@@ -1131,6 +1135,8 @@ class depgraph(object):
                        if new_child_slot is not None:
                                msg.append("   new child slot package:  %s" % new_child_slot)
                        msg.append("   parent package: %s" % dep.parent)
+                       if new_dep is not None:
+                               msg.append("   new parent pkg: %s" % new_dep.parent)
                        msg.append("   atom: %s" % dep.atom)
                        msg.append("")
                        writemsg_level("\n".join(msg),
@@ -1151,7 +1157,10 @@ class depgraph(object):
                # trigger replacement of installed packages if necessary
                abi_reinstalls = set()
                if dep.parent.installed:
-                       replacement_atom = self._replace_installed_atom(dep.parent)
+                       if new_dep is not None:
+                               replacement_atom = new_dep.parent.slot_atom
+                       else:
+                               replacement_atom = self._replace_installed_atom(dep.parent)
                        if replacement_atom is not None:
                                abi_reinstalls.add((dep.parent.root, replacement_atom))
                if new_child_slot is None and child.installed:
@@ -1164,8 +1173,26 @@ class depgraph(object):
 
                self._dynamic_config._need_restart = True
 
+       def _slot_operator_update_probe_slot_conflict(self, dep):
+               new_dep = self._slot_operator_update_probe(dep, slot_conflict=True)
+
+               if new_dep is not None:
+                       return new_dep
+
+               if self._dynamic_config._autounmask is True:
+
+                       for autounmask_level in self._autounmask_levels():
+
+                               new_dep = self._slot_operator_update_probe(dep,
+                                       slot_conflict=True, autounmask_level=autounmask_level)
+
+                               if new_dep is not None:
+                                       return new_dep
+
+               return None
+
        def _slot_operator_update_probe(self, dep, new_child_slot=False,
-               slot_conflict=False):
+               slot_conflict=False, autounmask_level=None):
                """
                slot/sub-slot := operators tend to prevent updates from getting pulled in,
                since installed packages pull in packages with the slot/sub-slot that they
@@ -1191,7 +1218,7 @@ class depgraph(object):
                want_downgrade = None
 
                for replacement_parent in self._iter_similar_available(dep.parent,
-                       dep.parent.slot_atom):
+                       dep.parent.slot_atom, autounmask_level=autounmask_level):
 
                        selected_atoms = None
 
@@ -1283,7 +1310,8 @@ class depgraph(object):
                                        if insignificant:
                                                return None
 
-                                       return pkg
+                                       return Dependency(parent=replacement_parent,
+                                               child=pkg, atom=unevaluated_atom)
 
                if debug:
                        msg = []
@@ -1423,7 +1451,7 @@ class depgraph(object):
                return frozenset(x.unevaluated_atom for
                        x in selected_atoms)
 
-       def _iter_similar_available(self, graph_pkg, atom):
+       def _iter_similar_available(self, graph_pkg, atom, autounmask_level=None):
                """
                Given a package that's in the graph, do a rough check to
                see if a similar package is available to install. The given
@@ -1447,16 +1475,18 @@ class depgraph(object):
                        if self._frozen_config.excluded_pkgs.findAtomForPackage(pkg,
                                modified_use=self._pkg_use_enabled(pkg)):
                                continue
-                       if not self._pkg_visibility_check(pkg):
+                       if pkg.built and self._equiv_binary_installed(pkg):
                                continue
                        if pkg.built:
-                               if self._equiv_binary_installed(pkg):
-                                       continue
                                if not (not use_ebuild_visibility and
                                        (usepkgonly or useoldpkg_atoms.findAtomForPackage(
                                        pkg, modified_use=self._pkg_use_enabled(pkg)))) and \
-                                       not self._equiv_ebuild_visible(pkg):
+                                       not self._equiv_ebuild_visible(pkg,
+                                       autounmask_level=autounmask_level):
                                        continue
+                       if not self._pkg_visibility_check(pkg,
+                               autounmask_level=autounmask_level):
+                               continue
                        yield pkg
 
        def _replace_installed_atom(self, inst_pkg):
@@ -1521,11 +1551,11 @@ class depgraph(object):
                                # trigger reinstall of the child package when a newer
                                # slot will be used instead.
                                if rebuild_if_new_slot:
-                                       new_child = self._slot_operator_update_probe(dep,
+                                       new_dep = self._slot_operator_update_probe(dep,
                                                new_child_slot=True)
-                                       if new_child:
+                                       if new_dep is not None:
                                                self._slot_operator_update_backtrack(dep,
-                                                       new_child_slot=new_child)
+                                                       new_child_slot=new_dep.child)
                                                break
 
                                if dep.want_update:
diff --git a/pym/portage/tests/resolver/test_slot_operator_autounmask.py b/pym/portage/tests/resolver/test_slot_operator_autounmask.py
new file mode 100644 (file)
index 0000000..624271b
--- /dev/null
@@ -0,0 +1,120 @@
+# Copyright 2013 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 SlotOperatorAutoUnmaskTestCase(TestCase):
+
+       def __init__(self, *args, **kwargs):
+               super(SlotOperatorAutoUnmaskTestCase, self).__init__(*args, **kwargs)
+
+       def testSubSlot(self):
+               ebuilds = {
+                       "dev-libs/icu-49" : {
+                               "EAPI": "4-slot-abi",
+                               "SLOT": "0/49"
+                       },
+                       "dev-libs/icu-4.8" : {
+                               "EAPI": "4-slot-abi",
+                               "SLOT": "0/48"
+                       },
+                       "dev-libs/libxml2-2.7.8" : {
+                               "EAPI": "4-slot-abi",
+                               "DEPEND":  "dev-libs/icu:=",
+                               "RDEPEND": "dev-libs/icu:=",
+                               "KEYWORDS": "~x86"
+                       },
+               }
+               binpkgs = {
+                       "dev-libs/icu-49" : {
+                               "EAPI": "4-slot-abi",
+                               "SLOT": "0/49"
+                       },
+                       "dev-libs/icu-4.8" : {
+                               "EAPI": "4-slot-abi",
+                               "SLOT": "0/48"
+                       },
+                       "dev-libs/libxml2-2.7.8" : {
+                               "EAPI": "4-slot-abi",
+                               "DEPEND":  "dev-libs/icu:0/48=",
+                               "RDEPEND": "dev-libs/icu:0/48="
+                       },
+               }
+               installed = {
+                       "dev-libs/icu-4.8" : {
+                               "EAPI": "4-slot-abi",
+                               "SLOT": "0/48"
+                       },
+                       "dev-libs/libxml2-2.7.8" : {
+                               "EAPI": "4-slot-abi",
+                               "DEPEND":  "dev-libs/icu:0/48=",
+                               "RDEPEND": "dev-libs/icu:0/48="
+                       },
+               }
+
+               world = ["dev-libs/libxml2"]
+
+               test_cases = (
+
+                       ResolverPlaygroundTestCase(
+                               ["dev-libs/icu"],
+                               options = {"--autounmask": True, "--oneshot": True},
+                               success = False,
+                               mergelist = ["dev-libs/icu-49", "dev-libs/libxml2-2.7.8" ],
+                               unstable_keywords = ['dev-libs/libxml2-2.7.8']),
+
+                       ResolverPlaygroundTestCase(
+                               ["dev-libs/icu"],
+                               options = {"--oneshot": True, "--ignore-built-slot-operator-deps": "y"},
+                               success = True,
+                               mergelist = ["dev-libs/icu-49"]),
+
+                       ResolverPlaygroundTestCase(
+                               ["dev-libs/icu"],
+                               options = {"--oneshot": True, "--usepkg": True},
+                               success = False,
+                               mergelist = ["[binary]dev-libs/icu-49", "dev-libs/libxml2-2.7.8" ],
+                               unstable_keywords = ['dev-libs/libxml2-2.7.8']),
+
+                       ResolverPlaygroundTestCase(
+                               ["dev-libs/icu"],
+                               options = {"--oneshot": True, "--usepkgonly": True},
+                               success = True,
+                               mergelist = ["[binary]dev-libs/icu-4.8"]),
+
+                       ResolverPlaygroundTestCase(
+                               ["dev-libs/icu"],
+                               options = {"--oneshot": True, "--usepkgonly": True, "--ignore-built-slot-operator-deps": "y"},
+                               success = True,
+                               mergelist = ["[binary]dev-libs/icu-49"]),
+
+                       ResolverPlaygroundTestCase(
+                               ["@world"],
+                               options = {"--update": True, "--deep": True, "--ignore-built-slot-operator-deps": "y"},
+                               success = True,
+                               mergelist = ["dev-libs/icu-49"]),
+
+                       ResolverPlaygroundTestCase(
+                               ["@world"],
+                               options = {"--update": True, "--deep": True, "--usepkgonly": True},
+                               success = True,
+                               mergelist = []),
+
+                       ResolverPlaygroundTestCase(
+                               ["@world"],
+                               options = {"--update": True, "--deep": True, "--usepkgonly": True, "--ignore-built-slot-operator-deps": "y"},
+                               success = True,
+                               mergelist = ["[binary]dev-libs/icu-49"]),
+
+               )
+
+               playground = ResolverPlayground(ebuilds=ebuilds, binpkgs=binpkgs,
+                       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()