commit:     beecd610f21497609679a08f867fd88090c71fb7
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Fri Sep 19 09:16:32 2014 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Fri Sep 19 09:16:32 2014 +0000
URL:        
http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=beecd610

_backtrack_depgraph: fix bug #523048

This fixes _backtrack_depgraph to immediately report necessary
REQUIRED_USE changes instead of discarding the graph. This is
accomplished by replacing the depgraph.success_without_autounmask
method with a new need_config_change method that accounts for both
autounmask and REQUIRED_USE changes.

X-Gentoo-Bug: 523048
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=523048
Acked-by: Brian Dolbec <dolsen <AT> gentoo.org>
Acked-by: Alexander Berntsen <bernalex <AT> gentoo.org>

---
 pym/_emerge/depgraph.py                            | 11 ++--
 pym/portage/tests/resolver/ResolverPlayground.py   | 19 +++++-
 .../resolver/test_slot_operator_required_use.py    | 72 ++++++++++++++++++++++
 3 files changed, 95 insertions(+), 7 deletions(-)

diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index 6332733..e7ae720 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -421,6 +421,7 @@ class _dynamic_depgraph_config(object):
                self._buildpkgonly_deps_unsatisfied = False
                self._autounmask = 
depgraph._frozen_config.myopts.get('--autounmask') != 'n'
                self._success_without_autounmask = False
+               self._required_use_unsatisfied = False
                self._traverse_ignored_deps = False
                self._complete_mode = False
                self._slot_operator_deps = {}
@@ -2461,6 +2462,7 @@ class depgraph(object):
                                
self._dynamic_config._unsatisfied_deps_for_display.append(
                                        ((pkg.root, atom),
                                        {"myparent" : dep.parent, 
"show_req_use" : pkg}))
+                               self._dynamic_config._required_use_unsatisfied 
= True
                                self._dynamic_config._skip_restart = True
                                return 0
 
@@ -8390,8 +8392,9 @@ class depgraph(object):
                return self._dynamic_config._need_restart and \
                        not self._dynamic_config._skip_restart
 
-       def success_without_autounmask(self):
-               return self._dynamic_config._success_without_autounmask
+       def need_config_change(self):
+               return self._dynamic_config._success_without_autounmask or \
+                       self._dynamic_config._required_use_unsatisfied
 
        def autounmask_breakage_detected(self):
                try:
@@ -8665,7 +8668,7 @@ def _backtrack_depgraph(settings, trees, myopts, 
myparams, myaction, myfiles, sp
                        backtrack_parameters=backtrack_parameters)
                success, favorites = mydepgraph.select_files(myfiles)
 
-               if success or mydepgraph.success_without_autounmask():
+               if success or mydepgraph.need_config_change():
                        break
                elif not allow_backtracking:
                        break
@@ -8677,7 +8680,7 @@ def _backtrack_depgraph(settings, trees, myopts, 
myparams, myaction, myfiles, sp
                else:
                        break
 
-       if not (success or mydepgraph.success_without_autounmask()) and 
backtracked:
+       if not (success or mydepgraph.need_config_change()) and backtracked:
 
                if debug:
                        writemsg_level(

diff --git a/pym/portage/tests/resolver/ResolverPlayground.py 
b/pym/portage/tests/resolver/ResolverPlayground.py
index d74a410..2d16251 100644
--- a/pym/portage/tests/resolver/ResolverPlayground.py
+++ b/pym/portage/tests/resolver/ResolverPlayground.py
@@ -674,7 +674,8 @@ class ResolverPlaygroundTestCase(object):
                                                expected = x
                                                break
                        elif key in ("unstable_keywords", 
"needed_p_mask_changes",
-                               "unsatisfied_deps") and expected is not None:
+                               "unsatisfied_deps", "required_use_unsatisfied") 
and \
+                               expected is not None:
                                expected = set(expected)
 
                        elif key == "forced_rebuilds" and expected is not None:
@@ -692,11 +693,14 @@ class ResolverPlaygroundTestCase(object):
 class ResolverPlaygroundResult(object):
 
        checks = (
-               "success", "mergelist", "use_changes", "license_changes", 
"unstable_keywords", "slot_collision_solutions",
-               "circular_dependency_solutions", "needed_p_mask_changes", 
"unsatisfied_deps", "forced_rebuilds"
+               "success", "mergelist", "use_changes", "license_changes",
+               "unstable_keywords", "slot_collision_solutions",
+               "circular_dependency_solutions", "needed_p_mask_changes",
+               "unsatisfied_deps", "forced_rebuilds", 
"required_use_unsatisfied"
                )
        optional_checks = (
                "forced_rebuilds",
+               "required_use_unsatisfied",
                "unsatisfied_deps"
                )
 
@@ -714,6 +718,7 @@ class ResolverPlaygroundResult(object):
                self.circular_dependency_solutions = None
                self.unsatisfied_deps = frozenset()
                self.forced_rebuilds = None
+               self.required_use_unsatisfied = None
 
                if self.depgraph._dynamic_config._serialized_tasks_cache is not 
None:
                        self.mergelist = []
@@ -783,6 +788,14 @@ class ResolverPlaygroundResult(object):
                                for child_dict in 
self.depgraph._forced_rebuilds.values()
                                for child, parents in child_dict.items())
 
+               required_use_unsatisfied = []
+               for pargs, kwargs in \
+                       
self.depgraph._dynamic_config._unsatisfied_deps_for_display:
+                       if "show_req_use" in kwargs:
+                               required_use_unsatisfied.append(pargs[1])
+               if required_use_unsatisfied:
+                       self.required_use_unsatisfied = 
set(required_use_unsatisfied)
+
 class ResolverPlaygroundDepcleanResult(object):
 
        checks = (

diff --git a/pym/portage/tests/resolver/test_slot_operator_required_use.py 
b/pym/portage/tests/resolver/test_slot_operator_required_use.py
new file mode 100644
index 0000000..9cc6dba
--- /dev/null
+++ b/pym/portage/tests/resolver/test_slot_operator_required_use.py
@@ -0,0 +1,72 @@
+# Copyright 2014 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 SlotOperatorRequiredUseTestCase(TestCase):
+
+       def testSlotOperatorRequiredUse(self):
+
+               ebuilds = {
+
+                       "app-misc/A-1" : {
+                               "EAPI": "5",
+                               "SLOT": "0/1"
+                       },
+
+                       "app-misc/A-2" : {
+                               "EAPI": "5",
+                               "SLOT": "0/2"
+                       },
+
+                       "app-misc/B-0" : {
+                               "EAPI": "5",
+                               "RDEPEND": "app-misc/A:=",
+                               "IUSE": "x y",
+                               "REQUIRED_USE": "|| ( x y )"
+                       },
+
+               }
+
+               installed = {
+
+                       "app-misc/A-1" : {
+                               "EAPI": "5",
+                               "SLOT": "0/1"
+                       },
+
+                       "app-misc/B-0" : {
+                               "EAPI": "5",
+                               "RDEPEND": "app-misc/A:0/1=",
+                               "IUSE": "x y",
+                               "USE": "x"
+                       },
+
+               }
+
+               world = ["app-misc/B"]
+
+               test_cases = (
+
+                       # bug 523048
+                       # Ensure that unsatisfied REQUIRED_USE is reported when
+                       # it blocks necessary slot-operator rebuilds.
+                       ResolverPlaygroundTestCase(
+                               ["app-misc/A"],
+                               success = False,
+                               required_use_unsatisfied = ['app-misc/B:0']
+                       ),
+
+               )
+
+               playground = ResolverPlayground(ebuilds=ebuilds,
+                       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()

Reply via email to