autounmask: Ensure a suitable parent is displayed in the dep chain
authorSebastian Luther <SebastianLuther@gmx.de>
Sun, 18 Sep 2011 19:30:46 +0000 (21:30 +0200)
committerZac Medico <zmedico@gentoo.org>
Sun, 18 Sep 2011 20:02:19 +0000 (13:02 -0700)
Fixes bug 375265.

pym/_emerge/depgraph.py
pym/portage/tests/resolver/test_autounmask.py

index fbbae1e29451fedf38db3878493d4726a568127f..400207e4efa578362f3d151c4f629751ee4262b9 100644 (file)
@@ -18,7 +18,8 @@ from portage import os, OrderedDict
 from portage import _unicode_decode, _unicode_encode, _encodings
 from portage.const import PORTAGE_PACKAGE_ATOM, USER_CONFIG_PATH
 from portage.dbapi import dbapi
-from portage.dep import Atom, extract_affecting_use, check_required_use, human_readable_required_use, _repo_separator
+from portage.dep import Atom, best_match_to_list, extract_affecting_use, \
+       check_required_use, human_readable_required_use, _repo_separator
 from portage.eapi import eapi_has_strong_blocks, eapi_has_required_use
 from portage.exception import InvalidAtom, InvalidDependString, PortageException
 from portage.output import colorize, create_color_func, \
@@ -2694,6 +2695,37 @@ class depgraph(object):
 
                        dep_chain.append((pkg_name, node.type_name))
 
+
+               # To build a dep chain for the given package we take
+               # "random" parents form the digraph, except for the
+               # first package, because we want a parent that forced
+               # the corresponding change (i.e '>=foo-2', instead 'foo').
+
+               traversed_nodes.add(start_node)
+
+               start_node_parent_atoms = {}
+               for ppkg, patom in all_parents[node]:
+                       # Get a list of suitable atoms. For use deps
+                       # (aka unsatisfied_dependency is not None) we
+                       # need that the start_node doesn't match the atom.
+                       if not unsatisfied_dependency or \
+                               not InternalPackageSet(initial_atoms=(patom,)).findAtomForPackage(start_node):
+                               start_node_parent_atoms.setdefault(patom, []).append(ppkg)
+
+               if start_node_parent_atoms:
+                       # If there are parents in all_parents then use one of them.
+                       # If not, then this package got pulled in by an Arg and
+                       # will be correctly handled by the code that handles later
+                       # packages in the dep chain.
+                       best_match = best_match_to_list(node.cpv, start_node_parent_atoms)
+
+                       child = node
+                       for ppkg in start_node_parent_atoms[best_match]:
+                               node = ppkg
+                               if ppkg in self._dynamic_config._initial_arg_list:
+                                       # Stop if reached the top level of the dep chain.
+                                       break
+
                while node is not None:
                        traversed_nodes.add(node)
 
index 54c435f56216c7e83318096a2a94b05d610fd3b9..ff13789dc31585e628038427a0a284c413884b5c 100644 (file)
@@ -1,6 +1,7 @@
 # Copyright 2010-2011 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
+from portage.const import _ENABLE_SET_CONFIG
 from portage.tests import TestCase
 from portage.tests.resolver.ResolverPlayground import ResolverPlayground, ResolverPlaygroundTestCase
 
@@ -324,3 +325,66 @@ class AutounmaskTestCase(TestCase):
                                self.assertEqual(test_case.test_success, True, test_case.fail_msg)
                finally:
                        playground.cleanup()
+
+
+       def testAutounmaskAndSets(self):
+
+               if not _ENABLE_SET_CONFIG:
+                       return
+
+               ebuilds = {
+                       #ebuilds to test use changes
+                       "dev-libs/A-1": { },
+                       "dev-libs/A-2": { "KEYWORDS": "~x86" },
+                       "dev-libs/B-1": { "DEPEND": "dev-libs/A" },
+                       "dev-libs/C-1": { "DEPEND": ">=dev-libs/A-2" },
+                       "dev-libs/D-1": { "DEPEND": "dev-libs/A" },
+                       }
+
+               world_sets = [ "@test-set" ]
+               sets = {
+                       "test-set": (
+                                       "dev-libs/A", "dev-libs/B", "dev-libs/C", "dev-libs/D",
+                               ),
+                       }
+
+               test_cases = (
+                               #Test USE changes.
+                               #The simple case.
+
+                               ResolverPlaygroundTestCase(
+                                       ["dev-libs/B", "dev-libs/C", "dev-libs/D"],
+                                       all_permutations=True,
+                                       options = {"--autounmask": "y"},
+                                       mergelist=["dev-libs/A-2", "dev-libs/B-1", "dev-libs/C-1", "dev-libs/D-1"],
+                                       ignore_mergelist_order=True,
+                                       unstable_keywords = ["dev-libs/A-2"],
+                                       success = False),
+
+                               ResolverPlaygroundTestCase(
+                                       ["@test-set"],
+                                       all_permutations=True,
+                                       options = {"--autounmask": "y"},
+                                       mergelist=["dev-libs/A-2", "dev-libs/B-1", "dev-libs/C-1", "dev-libs/D-1"],
+                                       ignore_mergelist_order=True,
+                                       unstable_keywords = ["dev-libs/A-2"],
+                                       success = False),
+
+                               ResolverPlaygroundTestCase(
+                                       ["@world"],
+                                       all_permutations=True,
+                                       options = {"--autounmask": "y"},
+                                       mergelist=["dev-libs/A-2", "dev-libs/B-1", "dev-libs/C-1", "dev-libs/D-1"],
+                                       ignore_mergelist_order=True,
+                                       unstable_keywords = ["dev-libs/A-2"],
+                                       success = False),
+                       )
+
+
+               playground = ResolverPlayground(ebuilds=ebuilds, world_sets=world_sets, sets=sets)
+               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()