Gentoo Archives: gentoo-commits

From: Brian Dolbec <dolsen@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:repoman commit in: pym/_emerge/, pym/portage/tests/resolver/
Date: Tue, 27 Jun 2017 20:06:17
Message-Id: 1496381882.60af7e2696b96b47b0cd9e70caabd10546206b8b.dolsen@gentoo
1 commit: 60af7e2696b96b47b0cd9e70caabd10546206b8b
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Mon May 29 08:22:40 2017 +0000
4 Commit: Brian Dolbec <dolsen <AT> gentoo <DOT> org>
5 CommitDate: Fri Jun 2 05:38:02 2017 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=60af7e26
7
8 depgraph: prune unnecessary rebuilds for --autounmask-continue (bug 619626)
9
10 When there are autounmask USE changes, avoid unnecessary rebuilds
11 by accepting binary packages that were rejected due to the preexisting
12 USE configuration. This reuses the prune_rebuilds backtracker support
13 which was added for bug 439688.
14
15 X-Gentoo-bug: 619626
16 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=619626
17 Acked-by: Brian Dolbec <dolsen <AT> gentoo.org>
18
19 pym/_emerge/depgraph.py | 96 ++++++++++++++++++----
20 .../tests/resolver/test_autounmask_binpkg_use.py | 64 +++++++++++++++
21 2 files changed, 142 insertions(+), 18 deletions(-)
22
23 diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
24 index 2dc432431..abe2cb1bd 100644
25 --- a/pym/_emerge/depgraph.py
26 +++ b/pym/_emerge/depgraph.py
27 @@ -5,6 +5,7 @@ from __future__ import division, print_function, unicode_literals
28
29 import collections
30 import errno
31 +import functools
32 import io
33 import logging
34 import stat
35 @@ -856,17 +857,11 @@ class depgraph(object):
36 for parent in self._forced_rebuilds[root][child]:
37 writemsg_stdout(" %s\n" % (parent,), noiselevel=-1)
38
39 - def _show_ignored_binaries(self):
40 + def _eliminate_ignored_binaries(self):
41 """
42 - Show binaries that have been ignored because their USE didn't
43 - match the user's config.
44 + Eliminate any package from self._dynamic_config.ignored_binaries
45 + for which a more optimal alternative exists.
46 """
47 - if not self._dynamic_config.ignored_binaries \
48 - or '--quiet' in self._frozen_config.myopts:
49 - return
50 -
51 - ignored_binaries = {}
52 -
53 for pkg in list(self._dynamic_config.ignored_binaries):
54
55 for selected_pkg in self._dynamic_config._package_tracker.match(
56 @@ -894,10 +889,67 @@ class depgraph(object):
57 self._dynamic_config.ignored_binaries.pop(pkg)
58 break
59
60 - else:
61 - for reason, info in self._dynamic_config.\
62 - ignored_binaries[pkg].items():
63 - ignored_binaries.setdefault(reason, {})[pkg] = info
64 + def _ignored_binaries_autounmask_backtrack(self):
65 + """
66 + Check if there are ignored binaries that would have been
67 + accepted with the current autounmask USE changes.
68 +
69 + @rtype: bool
70 + @return: True if there are unnecessary rebuilds that
71 + can be avoided by backtracking
72 + """
73 + if not all([
74 + self._dynamic_config._allow_backtracking,
75 + self._dynamic_config._needed_use_config_changes,
76 + self._dynamic_config.ignored_binaries]):
77 + return False
78 +
79 + self._eliminate_ignored_binaries()
80 +
81 + # _eliminate_ignored_binaries may have eliminated
82 + # all of the ignored binaries
83 + if not self._dynamic_config.ignored_binaries:
84 + return False
85 +
86 + use_changes = collections.defaultdict(
87 + functools.partial(collections.defaultdict, dict))
88 + for pkg, (new_use, changes) in self._dynamic_config._needed_use_config_changes.items():
89 + if pkg in self._dynamic_config.digraph:
90 + use_changes[pkg.root][pkg.slot_atom] = (pkg, new_use)
91 +
92 + for pkg in self._dynamic_config.ignored_binaries:
93 + selected_pkg, new_use = use_changes[pkg.root].get(
94 + pkg.slot_atom, (None, None))
95 + if new_use is None:
96 + continue
97 +
98 + if new_use != pkg.use.enabled:
99 + continue
100 +
101 + if selected_pkg > pkg:
102 + continue
103 +
104 + return True
105 +
106 + return False
107 +
108 + def _show_ignored_binaries(self):
109 + """
110 + Show binaries that have been ignored because their USE didn't
111 + match the user's config.
112 + """
113 + if not self._dynamic_config.ignored_binaries \
114 + or '--quiet' in self._frozen_config.myopts:
115 + return
116 +
117 + self._eliminate_ignored_binaries()
118 +
119 + ignored_binaries = {}
120 +
121 + for pkg in self._dynamic_config.ignored_binaries:
122 + for reason, info in self._dynamic_config.\
123 + ignored_binaries[pkg].items():
124 + ignored_binaries.setdefault(reason, {})[pkg] = info
125
126 if self._dynamic_config.myparams.get(
127 "binpkg_respect_use") in ("y", "n"):
128 @@ -4254,6 +4306,13 @@ class depgraph(object):
129 self._dynamic_config._skip_restart = True
130 return False, myfavorites
131
132 + if (not self._dynamic_config._prune_rebuilds and
133 + self._ignored_binaries_autounmask_backtrack()):
134 + config = self._dynamic_config._backtrack_infos.setdefault("config", {})
135 + config["prune_rebuilds"] = True
136 + self._dynamic_config._need_restart = True
137 + return False, myfavorites
138 +
139 # Any failures except those due to autounmask *alone* should return
140 # before this point, since the success_without_autounmask flag that's
141 # set below is reserved for cases where there are *zero* other
142 @@ -6233,13 +6292,14 @@ class depgraph(object):
143 iuses = pkg.iuse.all
144 old_use = self._pkg_use_enabled(pkg)
145 if myeb:
146 - pkgsettings.setcpv(myeb)
147 + now_use = self._pkg_use_enabled(myeb)
148 + forced_flags = set(chain(
149 + myeb.use.force, myeb.use.mask))
150 else:
151 pkgsettings.setcpv(pkg)
152 - now_use = pkgsettings["PORTAGE_USE"].split()
153 - forced_flags = set()
154 - forced_flags.update(pkgsettings.useforce)
155 - forced_flags.update(pkgsettings.usemask)
156 + now_use = pkgsettings["PORTAGE_USE"].split()
157 + forced_flags = set(chain(
158 + pkgsettings.useforce, pkgsettings.usemask))
159 cur_iuse = iuses
160 if myeb and not usepkgonly and not useoldpkg:
161 cur_iuse = myeb.iuse.all
162
163 diff --git a/pym/portage/tests/resolver/test_autounmask_binpkg_use.py b/pym/portage/tests/resolver/test_autounmask_binpkg_use.py
164 new file mode 100644
165 index 000000000..1ca4bf3d9
166 --- /dev/null
167 +++ b/pym/portage/tests/resolver/test_autounmask_binpkg_use.py
168 @@ -0,0 +1,64 @@
169 +# Copyright 2017 Gentoo Foundation
170 +# Distributed under the terms of the GNU General Public License v2
171 +
172 +from portage.tests import TestCase
173 +from portage.tests.resolver.ResolverPlayground import ResolverPlayground, ResolverPlaygroundTestCase
174 +
175 +class AutounmaskBinpkgUseTestCase(TestCase):
176 +
177 + def testAutounmaskBinpkgUse(self):
178 + ebuilds = {
179 + "dev-libs/A-1": {
180 + "EAPI": "6",
181 + "DEPEND": "dev-libs/B[foo]",
182 + "RDEPEND": "dev-libs/B[foo]",
183 + },
184 + "dev-libs/B-1": {
185 + "EAPI": "6",
186 + "IUSE": "foo",
187 + },
188 + }
189 + binpkgs = {
190 + "dev-libs/A-1": {
191 + "EAPI": "6",
192 + "DEPEND": "dev-libs/B[foo]",
193 + "RDEPEND": "dev-libs/B[foo]",
194 + },
195 + "dev-libs/B-1": {
196 + "EAPI": "6",
197 + "IUSE": "foo",
198 + "USE": "foo",
199 + },
200 + }
201 + installed = {
202 + }
203 +
204 + test_cases = (
205 + # Bug 619626: Test for unnecessary rebuild due
206 + # to rejection of binary packages that would
207 + # be acceptable after appplication of autounmask
208 + # USE changes.
209 + ResolverPlaygroundTestCase(
210 + ["dev-libs/A"],
211 + all_permutations = True,
212 + success = True,
213 + options = {
214 + "--usepkg": True,
215 + },
216 + mergelist = [
217 + "[binary]dev-libs/B-1",
218 + "[binary]dev-libs/A-1",
219 + ],
220 + use_changes = {"dev-libs/B-1": {"foo": True}}
221 + ),
222 + )
223 +
224 + playground = ResolverPlayground(ebuilds=ebuilds,
225 + binpkgs=binpkgs, installed=installed, debug=False)
226 + try:
227 + for test_case in test_cases:
228 + playground.run_TestCase(test_case)
229 + self.assertEqual(test_case.test_success, True, test_case.fail_msg)
230 + finally:
231 + playground.debug = False
232 + playground.cleanup()