emerge: add --complete-graph-if-new-use < y | n >
authorZac Medico <zmedico@gentoo.org>
Tue, 10 Jul 2012 22:45:12 +0000 (15:45 -0700)
committerZac Medico <zmedico@gentoo.org>
Tue, 10 Jul 2012 22:45:12 +0000 (15:45 -0700)
Trigger the --complete-graph behavior if USE or IUSE will change for
an installed package. This option is enabled by default. This will fix
bug #425558.

man/emerge.1
pym/_emerge/create_depgraph_params.py
pym/_emerge/depgraph.py
pym/_emerge/main.py
pym/portage/tests/resolver/test_complete_graph.py

index b45e41b5a426f60360f043064acde011ac09f0de..7aa46226cbc4e73d68c342b0ac68c0e567a4bdcf 100644 (file)
@@ -396,6 +396,10 @@ be updated than would have otherwise been updated with the option disabled.
 Using \fB\-\-with\-bdeps=y\fR together with \fB\-\-complete\-graph\fR makes
 the graph as complete as possible.
 .TP
+.BR "\-\-complete\-graph\-if\-new\-use < y | n >"
+Trigger the \fB\-\-complete\-graph\fR behavior if USE or IUSE will
+change for an installed package. This option is enabled by default.
+.TP
 .BR "\-\-complete\-graph\-if\-new\-ver < y | n >"
 Trigger the \fB\-\-complete\-graph\fR behavior if an installed package
 version will change (upgrade or downgrade). This option is enabled by default.
index 33d413aa317b1ec29d944c9117757a481b928722..2838e93c3d7949ae0619919401d8f0e4cc667a5b 100644 (file)
@@ -56,6 +56,11 @@ def create_depgraph_params(myopts, myaction):
        if deep is not None and deep != 0:
                myparams["deep"] = deep
 
+       complete_if_new_use = \
+               myopts.get("--complete-graph-if-new-use")
+       if complete_if_new_use is not None:
+               myparams["complete_if_new_use"] = complete_if_new_use
+
        complete_if_new_ver = \
                myopts.get("--complete-graph-if-new-ver")
        if complete_if_new_ver is not None:
index f819aef3d17607e7b50c421bc3ef9dd639ecd515..703720cf0852e28040970c3ff22b5499c62238fe 100644 (file)
@@ -4643,6 +4643,8 @@ class depgraph(object):
                        "recurse" not in self._dynamic_config.myparams:
                        return 1
 
+               complete_if_new_use = self._dynamic_config.myparams.get(
+                       "complete_if_new_use", "y") == "y"
                complete_if_new_ver = self._dynamic_config.myparams.get(
                        "complete_if_new_ver", "y") == "y"
                rebuild_if_new_slot_abi = self._dynamic_config.myparams.get(
@@ -4650,8 +4652,10 @@ class depgraph(object):
                complete_if_new_slot = rebuild_if_new_slot_abi
 
                if "complete" not in self._dynamic_config.myparams and \
-                       (complete_if_new_ver or complete_if_new_slot):
-                       # Enable complete mode if an installed package version will change.
+                       (complete_if_new_use or
+                       complete_if_new_ver or complete_if_new_slot):
+                       # Enable complete mode if an installed package will change somehow.
+                       use_change = False
                        version_change = False
                        for node in self._dynamic_config.digraph:
                                if not isinstance(node, Package) or \
@@ -4660,14 +4664,26 @@ class depgraph(object):
                                vardb = self._frozen_config.roots[
                                        node.root].trees["vartree"].dbapi
 
-                               if complete_if_new_ver:
+                               if complete_if_new_use or complete_if_new_ver:
                                        inst_pkg = vardb.match_pkgs(node.slot_atom)
                                        if inst_pkg and inst_pkg[0].cp == node.cp:
                                                inst_pkg = inst_pkg[0]
-                                               if inst_pkg < node or node < inst_pkg:
+                                               if complete_if_new_ver and \
+                                                       (inst_pkg < node or node < inst_pkg):
                                                        version_change = True
                                                        break
 
+                                               # Intersect enabled USE with IUSE, in order to
+                                               # ignore forced USE from implicit IUSE flags, since
+                                               # they're probably irrelevant and they are sensitive
+                                               # to use.mask/force changes in the profile.
+                                               if complete_if_new_use and \
+                                                       (node.iuse.all != inst_pkg.iuse.all or
+                                                       node.use.enabled.intersection(node.iuse.all) !=
+                                                       inst_pkg.use.enabled.intersection(inst_pkg.iuse.all)):
+                                                       use_change = True
+                                                       break
+
                                if complete_if_new_slot:
                                        cp_list = vardb.match_pkgs(Atom(node.cp))
                                        if (cp_list and cp_list[0].cp == node.cp and
@@ -4675,7 +4691,7 @@ class depgraph(object):
                                                version_change = True
                                                break
 
-                       if version_change:
+                       if use_change or version_change:
                                self._dynamic_config.myparams["complete"] = True
 
                if "complete" not in self._dynamic_config.myparams:
index 2a0e67f1d358efd2c6999aea7991f5181769a0cb..640f320fdd586de275ec3e6e27ba9d096e297169 100644 (file)
@@ -703,6 +703,12 @@ def parse_opts(tmpcmdline, silent=False):
                        "choices" : true_y_or_n
                },
 
+               "--complete-graph-if-new-use": {
+                       "help"    : "trigger --complete-graph behavior if USE or IUSE will change for an installed package",
+                       "type"    : "choice",
+                       "choices" : y_or_n
+               },
+
                "--complete-graph-if-new-ver": {
                        "help"    : "trigger --complete-graph behavior if an installed package version will change (upgrade or downgrade)",
                        "type"    : "choice",
index 850b883b4380fc8768d8a697872ac68c2b83f238..1b0342c673acd4ca686f4dd01beee1048e115178 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2011 Gentoo Foundation
+# Copyright 2011-2012 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 from portage.tests import TestCase
@@ -7,6 +7,70 @@ from portage.tests.resolver.ResolverPlayground import (ResolverPlayground,
 
 class CompleteGraphTestCase(TestCase):
 
+       def testCompleteGraphUseChange(self):
+               """
+               Prevent reverse dependency breakage triggered by USE changes.
+               """
+
+               ebuilds = {
+                       "dev-libs/libxml2-2.8.0": {
+                               "EAPI": "2",
+                               "IUSE": "+icu",
+                               "SLOT": "2",
+                       },
+                       "x11-libs/qt-webkit-4.8.2": {
+                               "EAPI": "2",
+                               "IUSE": "icu",
+                               "RDEPEND" : "dev-libs/libxml2:2[!icu?]",
+                       },
+               }
+
+               installed = {
+                       "dev-libs/libxml2-2.8.0": {
+                               "EAPI": "2",
+                               "IUSE": "+icu",
+                               "USE": "",
+                               "SLOT": "2",
+                       },
+                       "x11-libs/qt-webkit-4.8.2": {
+                               "EAPI": "2",
+                               "IUSE": "icu",
+                               "RDEPEND" : "dev-libs/libxml2:2[-icu]",
+                               "USE": "",
+                       }
+               }
+
+               world = ["x11-libs/qt-webkit"]
+
+               test_cases = (
+
+                       ResolverPlaygroundTestCase(
+                               ["dev-libs/libxml2"],
+                               options = {"--complete-graph-if-new-use" : "y" },
+                               mergelist = ["dev-libs/libxml2-2.8.0"],
+                               slot_collision_solutions = [{'dev-libs/libxml2-2.8.0': {'icu': False}}],
+                               success = False,
+                       ),
+
+                       ResolverPlaygroundTestCase(
+                               ["dev-libs/libxml2"],
+                               options = {"--complete-graph-if-new-use" : "n" },
+                               mergelist = ["dev-libs/libxml2-2.8.0"],
+                               success = True,
+                       ),
+
+               )
+
+               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()
+
        def testCompleteGraphVersionChange(self):
                """
                Prevent reverse dependency breakage triggered by version changes.