commit:     c01f3fbd23def329eb1d1b0fc8f79959119a8a82
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Wed Mar  8 22:25:56 2017 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Thu Mar  9 19:33:54 2017 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=c01f3fbd

depgraph: fix runtime package mask interaction with slot operator rebuilds (bug 
612094)

In some cases the backtracking runtime package mask can interact badly
with slot operator rebuilds, preventing a solution from being found.
This patch fixes the problem, which is demonstrated by the included
unit test.

X-Gentoo-bug: 612094
X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=612094
Acked-by: Brian Dolbec <dolsen <AT> gentoo.org>

 pym/_emerge/depgraph.py                            |  28 +++--
 .../test_slot_operator_runtime_pkg_mask.py         | 136 +++++++++++++++++++++
 2 files changed, 152 insertions(+), 12 deletions(-)

diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index bb3e307f0..1379b0563 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -1597,9 +1597,6 @@ class depgraph(object):
                                atom.package and atom.slot_operator_built):
                                continue
 
-                       if pkg not in conflict_pkgs:
-                               continue
-
                        for other_pkg in slot_nodes:
                                if other_pkg in conflict_pkgs:
                                        continue
@@ -2569,18 +2566,25 @@ class depgraph(object):
                        # runtime_pkg_mask, since that would trigger an
                        # infinite backtracking loop.
                        if self._dynamic_config._allow_backtracking:
-                               if dep.parent in 
self._dynamic_config._runtime_pkg_mask:
-                                       if debug:
-                                               writemsg(
-                                                       "!!! backtracking loop 
detected: %s %s\n" % \
-                                                       (dep.parent,
-                                                       
self._dynamic_config._runtime_pkg_mask[
-                                                       dep.parent]), 
noiselevel=-1)
-                               elif dep.atom.package and 
dep.atom.slot_operator_built and \
-                                       
self._slot_operator_unsatisfied_probe(dep):
+                               if (dep.parent not in 
self._dynamic_config._runtime_pkg_mask and
+                                       dep.atom.package and 
dep.atom.slot_operator_built and
+                                       
self._slot_operator_unsatisfied_probe(dep)):
                                        
self._slot_operator_unsatisfied_backtrack(dep)
                                        return 1
                                else:
+                                       # This is for backward-compatibility 
with previous
+                                       # behavior, so that installed packages 
with unsatisfied
+                                       # dependencies trigger an error message 
but do not
+                                       # cause the dependency calculation to 
fail. Only do
+                                       # this if the parent is already in the 
runtime package
+                                       # mask, since otherwise we need to 
backtrack.
+                                       if (dep.parent.installed and
+                                               dep.parent in 
self._dynamic_config._runtime_pkg_mask and
+                                               not 
any(self._iter_match_pkgs_any(
+                                               dep.parent.root_config, 
dep.atom))):
+                                               
self._dynamic_config._initially_unsatisfied_deps.append(dep)
+                                               return 1
+
                                        # Do not backtrack if only USE have to 
be changed in
                                        # order to satisfy the dependency. Note 
that when
                                        # want_restart_for_use_change sets the 
need_restart

diff --git a/pym/portage/tests/resolver/test_slot_operator_runtime_pkg_mask.py 
b/pym/portage/tests/resolver/test_slot_operator_runtime_pkg_mask.py
new file mode 100644
index 000000000..0a5a7fa78
--- /dev/null
+++ b/pym/portage/tests/resolver/test_slot_operator_runtime_pkg_mask.py
@@ -0,0 +1,136 @@
+# Copyright 2017 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 SlotOperatorRuntimePkgMaskTestCase(TestCase):
+
+       def testSlotOperatorRuntimePkgMask(self):
+
+               ebuilds = {
+                       "app-misc/meta-pkg-2" : {
+                               "EAPI": "6",
+                               "DEPEND": "=app-misc/B-2 =app-misc/C-1  
=app-misc/D-1 =dev-libs/foo-2",
+                               "RDEPEND": "=app-misc/B-2 =app-misc/C-1 
=app-misc/D-1 =dev-libs/foo-2",
+                       },
+
+                       "app-misc/meta-pkg-1" : {
+                               "EAPI": "6",
+                               "DEPEND": "=app-misc/B-1 =app-misc/C-1  
=app-misc/D-1 =dev-libs/foo-1",
+                               "RDEPEND": "=app-misc/B-1 =app-misc/C-1 
=app-misc/D-1 =dev-libs/foo-1",
+                       },
+
+                       "app-misc/B-1" : {
+                               "EAPI": "6",
+                               "DEPEND": "dev-libs/foo:=",
+                               "RDEPEND": "dev-libs/foo:=",
+                       },
+
+                       "app-misc/B-2" : {
+                               "EAPI": "6",
+                               "DEPEND": "dev-libs/foo:=",
+                               "RDEPEND": "dev-libs/foo:=",
+                       },
+
+                       "app-misc/C-1" : {
+                               "EAPI": "6",
+                               "DEPEND": "dev-libs/foo:=",
+                               "RDEPEND": "dev-libs/foo:=",
+                       },
+
+                       "app-misc/C-2" : {
+                               "EAPI": "6",
+                               "DEPEND": "dev-libs/foo:=",
+                               "RDEPEND": "dev-libs/foo:=",
+                       },
+
+                       "app-misc/D-1" : {
+                               "EAPI": "6",
+                               "DEPEND": "dev-libs/foo:=",
+                               "RDEPEND": "dev-libs/foo:=",
+                       },
+
+                       "app-misc/D-2" : {
+                               "EAPI": "6",
+                               "DEPEND": "dev-libs/foo:=",
+                               "RDEPEND": "dev-libs/foo:=",
+                       },
+
+                       "dev-libs/foo-1" : {
+                               "EAPI": "6",
+                               "SLOT": "0/1",
+                       },
+
+                       "dev-libs/foo-2" : {
+                               "EAPI": "6",
+                               "SLOT": "0/2",
+                       },
+               }
+
+               installed = {
+                       "app-misc/meta-pkg-1" : {
+                               "EAPI": "6",
+                               "DEPEND": "=app-misc/B-1 =app-misc/C-1  
=app-misc/D-1 =dev-libs/foo-1",
+                               "RDEPEND": "=app-misc/B-1 =app-misc/C-1 
=app-misc/D-1 =dev-libs/foo-1",
+                       },
+
+                       "app-misc/B-1" : {
+                               "EAPI": "6",
+                               "DEPEND": "dev-libs/foo:0/1=",
+                               "RDEPEND": "dev-libs/foo:0/1=",
+                       },
+
+                       "app-misc/C-1" : {
+                               "EAPI": "6",
+                               "DEPEND": "dev-libs/foo:0/1=",
+                               "RDEPEND": "dev-libs/foo:0/1=",
+                       },
+
+                       "app-misc/D-1" : {
+                               "EAPI": "6",
+                               "DEPEND": "dev-libs/foo:0/1=",
+                               "RDEPEND": "dev-libs/foo:0/1=",
+                       },
+
+                       "dev-libs/foo-1" : {
+                               "EAPI": "6",
+                               "SLOT": "0/1",
+                       },
+               }
+
+               world = (
+                       "app-misc/meta-pkg",
+               )
+
+               test_cases = (
+                       ResolverPlaygroundTestCase(
+                               ["=app-misc/meta-pkg-2"],
+                               options = {
+                                       "--backtrack": 5,
+                               },
+                               success = True,
+                               ambiguous_merge_order = True,
+                               mergelist = [
+                                       'dev-libs/foo-2',
+                                       ('app-misc/D-1', 'app-misc/C-1', 
'app-misc/B-2'),
+                                       'app-misc/meta-pkg-2',
+                               ]
+                       ),
+               )
+
+               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:
+                       # Disable debug so that cleanup works.
+                       playground.debug = False
+                       playground.cleanup()

Reply via email to