1 |
commit: 02bcf332a88bbf25b9e0391b1a6d781ab4bbe0b9 |
2 |
Author: Zac Medico <zmedico <AT> gentoo <DOT> org> |
3 |
AuthorDate: Thu Jul 5 03:16:40 2012 +0000 |
4 |
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> |
5 |
CommitDate: Thu Jul 5 03:16:40 2012 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=02bcf332 |
7 |
|
8 |
Rebuild for slot-abi downgrades, bug #424651. |
9 |
|
10 |
--- |
11 |
pym/_emerge/depgraph.py | 109 +++++++--- |
12 |
.../tests/resolver/test_slot_abi_downgrade.py | 225 ++++++++++++++++++++ |
13 |
2 files changed, 298 insertions(+), 36 deletions(-) |
14 |
|
15 |
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py |
16 |
index 480cb90..f819aef 100644 |
17 |
--- a/pym/_emerge/depgraph.py |
18 |
+++ b/pym/_emerge/depgraph.py |
19 |
@@ -24,7 +24,8 @@ from portage.dep import Atom, best_match_to_list, extract_affecting_use, \ |
20 |
_repo_separator |
21 |
from portage.dep._slot_abi import ignore_built_slot_abi_deps |
22 |
from portage.eapi import eapi_has_strong_blocks, eapi_has_required_use |
23 |
-from portage.exception import InvalidAtom, InvalidDependString, PortageException |
24 |
+from portage.exception import (InvalidAtom, InvalidDependString, |
25 |
+ PackageNotFound, PortageException) |
26 |
from portage.output import colorize, create_color_func, \ |
27 |
darkgreen, green |
28 |
bad = create_color_func("BAD") |
29 |
@@ -1047,6 +1048,7 @@ class depgraph(object): |
30 |
return None |
31 |
|
32 |
debug = "--debug" in self._frozen_config.myopts |
33 |
+ want_downgrade = None |
34 |
|
35 |
for replacement_parent in self._iter_similar_available(dep.parent, |
36 |
dep.parent.slot_atom): |
37 |
@@ -1087,10 +1089,13 @@ class depgraph(object): |
38 |
if pkg.slot != dep.child.slot: |
39 |
continue |
40 |
if pkg < dep.child: |
41 |
+ if want_downgrade is None: |
42 |
+ want_downgrade = self._downgrade_probe(dep.child) |
43 |
# be careful not to trigger a rebuild when |
44 |
# the only version available with a |
45 |
# different slot_abi is an older version |
46 |
- continue |
47 |
+ if not want_downgrade: |
48 |
+ continue |
49 |
|
50 |
if debug: |
51 |
msg = [] |
52 |
@@ -1122,12 +1127,33 @@ class depgraph(object): |
53 |
|
54 |
return None |
55 |
|
56 |
+ def _downgrade_probe(self, pkg): |
57 |
+ """ |
58 |
+ Detect cases where a downgrade of the given package is considered |
59 |
+ desirable due to the current version being masked or unavailable. |
60 |
+ """ |
61 |
+ available_pkg = None |
62 |
+ for available_pkg in self._iter_similar_available(pkg, |
63 |
+ pkg.slot_atom): |
64 |
+ if available_pkg >= pkg: |
65 |
+ # There's an available package of the same or higher |
66 |
+ # version, so downgrade seems undesirable. |
67 |
+ return False |
68 |
+ |
69 |
+ return available_pkg is not None |
70 |
+ |
71 |
def _iter_similar_available(self, graph_pkg, atom): |
72 |
""" |
73 |
Given a package that's in the graph, do a rough check to |
74 |
see if a similar package is available to install. The given |
75 |
graph_pkg itself may be yielded only if it's not installed. |
76 |
""" |
77 |
+ |
78 |
+ usepkgonly = "--usepkgonly" in self._frozen_config.myopts |
79 |
+ useoldpkg_atoms = self._frozen_config.useoldpkg_atoms |
80 |
+ use_ebuild_visibility = self._frozen_config.myopts.get( |
81 |
+ '--use-ebuild-visibility', 'n') != 'n' |
82 |
+ |
83 |
for pkg in self._iter_match_pkgs_any( |
84 |
graph_pkg.root_config, atom): |
85 |
if pkg.cp != graph_pkg.cp: |
86 |
@@ -1142,6 +1168,14 @@ class depgraph(object): |
87 |
continue |
88 |
if not self._pkg_visibility_check(pkg): |
89 |
continue |
90 |
+ if pkg.built: |
91 |
+ if self._equiv_binary_installed(pkg): |
92 |
+ continue |
93 |
+ if not (not use_ebuild_visibility and |
94 |
+ (usepkgonly or useoldpkg_atoms.findAtomForPackage( |
95 |
+ pkg, modified_use=self._pkg_use_enabled(pkg)))) and \ |
96 |
+ not self._equiv_ebuild_visible(pkg): |
97 |
+ continue |
98 |
yield pkg |
99 |
|
100 |
def _slot_abi_trigger_reinstalls(self): |
101 |
@@ -3811,6 +3845,38 @@ class depgraph(object): |
102 |
|
103 |
return not arg |
104 |
|
105 |
+ def _equiv_ebuild_visible(self, pkg, autounmask_level=None): |
106 |
+ try: |
107 |
+ pkg_eb = self._pkg( |
108 |
+ pkg.cpv, "ebuild", pkg.root_config, myrepo=pkg.repo) |
109 |
+ except portage.exception.PackageNotFound: |
110 |
+ pkg_eb_visible = False |
111 |
+ for pkg_eb in self._iter_match_pkgs(pkg.root_config, |
112 |
+ "ebuild", Atom("=%s" % (pkg.cpv,))): |
113 |
+ if self._pkg_visibility_check(pkg_eb, autounmask_level): |
114 |
+ pkg_eb_visible = True |
115 |
+ break |
116 |
+ if not pkg_eb_visible: |
117 |
+ return False |
118 |
+ else: |
119 |
+ if not self._pkg_visibility_check(pkg_eb, autounmask_level): |
120 |
+ return False |
121 |
+ |
122 |
+ return True |
123 |
+ |
124 |
+ def _equiv_binary_installed(self, pkg): |
125 |
+ build_time = pkg.metadata.get('BUILD_TIME') |
126 |
+ if not build_time: |
127 |
+ return False |
128 |
+ |
129 |
+ try: |
130 |
+ inst_pkg = self._pkg(pkg.cpv, "installed", |
131 |
+ pkg.root_config, installed=True) |
132 |
+ except PackageNotFound: |
133 |
+ return False |
134 |
+ |
135 |
+ return build_time == inst_pkg.metadata.get('BUILD_TIME') |
136 |
+ |
137 |
class _AutounmaskLevel(object): |
138 |
__slots__ = ("allow_use_changes", "allow_unstable_keywords", "allow_license_changes", \ |
139 |
"allow_missing_keywords", "allow_unmasks") |
140 |
@@ -4241,22 +4307,9 @@ class depgraph(object): |
141 |
if not use_ebuild_visibility and (usepkgonly or useoldpkg): |
142 |
if pkg.installed and pkg.masks: |
143 |
continue |
144 |
- else: |
145 |
- try: |
146 |
- pkg_eb = self._pkg( |
147 |
- pkg.cpv, "ebuild", root_config, myrepo=pkg.repo) |
148 |
- except portage.exception.PackageNotFound: |
149 |
- pkg_eb_visible = False |
150 |
- for pkg_eb in self._iter_match_pkgs(pkg.root_config, |
151 |
- "ebuild", Atom("=%s" % (pkg.cpv,))): |
152 |
- if self._pkg_visibility_check(pkg_eb, autounmask_level): |
153 |
- pkg_eb_visible = True |
154 |
- break |
155 |
- if not pkg_eb_visible: |
156 |
- continue |
157 |
- else: |
158 |
- if not self._pkg_visibility_check(pkg_eb, autounmask_level): |
159 |
- continue |
160 |
+ elif not self._equiv_ebuild_visible(pkg, |
161 |
+ autounmask_level=autounmask_level): |
162 |
+ continue |
163 |
|
164 |
# Calculation of USE for unbuilt ebuilds is relatively |
165 |
# expensive, so it is only performed lazily, after the |
166 |
@@ -7137,24 +7190,8 @@ class _dep_check_composite_db(dbapi): |
167 |
if not avoid_update: |
168 |
if not use_ebuild_visibility and usepkgonly: |
169 |
return False |
170 |
- else: |
171 |
- try: |
172 |
- pkg_eb = self._depgraph._pkg( |
173 |
- pkg.cpv, "ebuild", pkg.root_config, |
174 |
- myrepo=pkg.repo) |
175 |
- except portage.exception.PackageNotFound: |
176 |
- pkg_eb_visible = False |
177 |
- for pkg_eb in self._depgraph._iter_match_pkgs( |
178 |
- pkg.root_config, "ebuild", |
179 |
- Atom("=%s" % (pkg.cpv,))): |
180 |
- if self._depgraph._pkg_visibility_check(pkg_eb): |
181 |
- pkg_eb_visible = True |
182 |
- break |
183 |
- if not pkg_eb_visible: |
184 |
- return False |
185 |
- else: |
186 |
- if not self._depgraph._pkg_visibility_check(pkg_eb): |
187 |
- return False |
188 |
+ elif not self._depgraph._equiv_ebuild_visible(pkg): |
189 |
+ return False |
190 |
|
191 |
in_graph = self._depgraph._dynamic_config._slot_pkg_map[ |
192 |
self._root].get(pkg.slot_atom) |
193 |
|
194 |
diff --git a/pym/portage/tests/resolver/test_slot_abi_downgrade.py b/pym/portage/tests/resolver/test_slot_abi_downgrade.py |
195 |
new file mode 100644 |
196 |
index 0000000..45a7555 |
197 |
--- /dev/null |
198 |
+++ b/pym/portage/tests/resolver/test_slot_abi_downgrade.py |
199 |
@@ -0,0 +1,225 @@ |
200 |
+# Copyright 2012 Gentoo Foundation |
201 |
+# Distributed under the terms of the GNU General Public License v2 |
202 |
+ |
203 |
+from portage.tests import TestCase |
204 |
+from portage.tests.resolver.ResolverPlayground import (ResolverPlayground, |
205 |
+ ResolverPlaygroundTestCase) |
206 |
+ |
207 |
+class SlotAbiDowngradeTestCase(TestCase): |
208 |
+ |
209 |
+ def __init__(self, *args, **kwargs): |
210 |
+ super(SlotAbiDowngradeTestCase, self).__init__(*args, **kwargs) |
211 |
+ |
212 |
+ def testSubSlot(self): |
213 |
+ ebuilds = { |
214 |
+ "dev-libs/icu-4.8" : { |
215 |
+ "EAPI": "4-slot-abi", |
216 |
+ "SLOT": "0/48" |
217 |
+ }, |
218 |
+ "dev-libs/libxml2-2.7.8" : { |
219 |
+ "EAPI": "4-slot-abi", |
220 |
+ "DEPEND": "dev-libs/icu:=", |
221 |
+ "RDEPEND": "dev-libs/icu:=" |
222 |
+ }, |
223 |
+ } |
224 |
+ binpkgs = { |
225 |
+ "dev-libs/icu-49" : { |
226 |
+ "EAPI": "4-slot-abi", |
227 |
+ "SLOT": "0/49" |
228 |
+ }, |
229 |
+ "dev-libs/icu-4.8" : { |
230 |
+ "EAPI": "4-slot-abi", |
231 |
+ "SLOT": "0/48" |
232 |
+ }, |
233 |
+ "dev-libs/libxml2-2.7.8" : { |
234 |
+ "EAPI": "4-slot-abi", |
235 |
+ "DEPEND": "dev-libs/icu:0/49=", |
236 |
+ "RDEPEND": "dev-libs/icu:0/49=" |
237 |
+ }, |
238 |
+ } |
239 |
+ installed = { |
240 |
+ "dev-libs/icu-49" : { |
241 |
+ "EAPI": "4-slot-abi", |
242 |
+ "SLOT": "0/49" |
243 |
+ }, |
244 |
+ "dev-libs/libxml2-2.7.8" : { |
245 |
+ "EAPI": "4-slot-abi", |
246 |
+ "DEPEND": "dev-libs/icu:0/49=", |
247 |
+ "RDEPEND": "dev-libs/icu:0/49=" |
248 |
+ }, |
249 |
+ } |
250 |
+ |
251 |
+ world = ["dev-libs/libxml2"] |
252 |
+ |
253 |
+ test_cases = ( |
254 |
+ |
255 |
+ ResolverPlaygroundTestCase( |
256 |
+ ["dev-libs/icu"], |
257 |
+ options = {"--oneshot": True}, |
258 |
+ success = True, |
259 |
+ mergelist = ["dev-libs/icu-4.8", "dev-libs/libxml2-2.7.8" ]), |
260 |
+ |
261 |
+ ResolverPlaygroundTestCase( |
262 |
+ ["dev-libs/icu"], |
263 |
+ options = {"--oneshot": True, "--ignore-built-slot-abi-deps": "y"}, |
264 |
+ success = True, |
265 |
+ mergelist = ["dev-libs/icu-4.8"]), |
266 |
+ |
267 |
+ ResolverPlaygroundTestCase( |
268 |
+ ["dev-libs/icu"], |
269 |
+ options = {"--oneshot": True, "--usepkg": True}, |
270 |
+ success = True, |
271 |
+ mergelist = ["[binary]dev-libs/icu-4.8", "dev-libs/libxml2-2.7.8" ]), |
272 |
+ |
273 |
+ ResolverPlaygroundTestCase( |
274 |
+ ["dev-libs/icu"], |
275 |
+ options = {"--oneshot": True, "--usepkgonly": True}, |
276 |
+ success = True, |
277 |
+ mergelist = ["[binary]dev-libs/icu-49"]), |
278 |
+ |
279 |
+ ResolverPlaygroundTestCase( |
280 |
+ ["@world"], |
281 |
+ options = {"--update": True, "--deep": True}, |
282 |
+ success = True, |
283 |
+ mergelist = ["dev-libs/icu-4.8", "dev-libs/libxml2-2.7.8" ]), |
284 |
+ |
285 |
+ ResolverPlaygroundTestCase( |
286 |
+ ["@world"], |
287 |
+ options = {"--update": True, "--deep": True, "--ignore-built-slot-abi-deps": "y"}, |
288 |
+ success = True, |
289 |
+ mergelist = ["dev-libs/icu-4.8"]), |
290 |
+ |
291 |
+ ResolverPlaygroundTestCase( |
292 |
+ ["@world"], |
293 |
+ options = {"--update": True, "--deep": True, "--usepkg": True}, |
294 |
+ success = True, |
295 |
+ mergelist = ["[binary]dev-libs/icu-4.8", "dev-libs/libxml2-2.7.8" ]), |
296 |
+ |
297 |
+ ResolverPlaygroundTestCase( |
298 |
+ ["@world"], |
299 |
+ options = {"--update": True, "--deep": True, "--usepkgonly": True}, |
300 |
+ success = True, |
301 |
+ mergelist = []), |
302 |
+ |
303 |
+ ) |
304 |
+ |
305 |
+ playground = ResolverPlayground(ebuilds=ebuilds, binpkgs=binpkgs, |
306 |
+ installed=installed, world=world, debug=False) |
307 |
+ try: |
308 |
+ for test_case in test_cases: |
309 |
+ playground.run_TestCase(test_case) |
310 |
+ self.assertEqual(test_case.test_success, True, test_case.fail_msg) |
311 |
+ finally: |
312 |
+ playground.cleanup() |
313 |
+ |
314 |
+ def testWholeSlotSubSlotMix(self): |
315 |
+ ebuilds = { |
316 |
+ "dev-libs/glib-1.2.10" : { |
317 |
+ "SLOT": "1" |
318 |
+ }, |
319 |
+ "dev-libs/glib-2.30.2" : { |
320 |
+ "EAPI": "4-slot-abi", |
321 |
+ "SLOT": "2/2.30" |
322 |
+ }, |
323 |
+ "dev-libs/dbus-glib-0.98" : { |
324 |
+ "EAPI": "4-slot-abi", |
325 |
+ "DEPEND": "dev-libs/glib:2=", |
326 |
+ "RDEPEND": "dev-libs/glib:2=" |
327 |
+ }, |
328 |
+ } |
329 |
+ binpkgs = { |
330 |
+ "dev-libs/glib-1.2.10" : { |
331 |
+ "SLOT": "1" |
332 |
+ }, |
333 |
+ "dev-libs/glib-2.30.2" : { |
334 |
+ "EAPI": "4-slot-abi", |
335 |
+ "SLOT": "2/2.30" |
336 |
+ }, |
337 |
+ "dev-libs/glib-2.32.3" : { |
338 |
+ "EAPI": "4-slot-abi", |
339 |
+ "SLOT": "2/2.32" |
340 |
+ }, |
341 |
+ "dev-libs/dbus-glib-0.98" : { |
342 |
+ "EAPI": "4-slot-abi", |
343 |
+ "DEPEND": "dev-libs/glib:2/2.32=", |
344 |
+ "RDEPEND": "dev-libs/glib:2/2.32=" |
345 |
+ }, |
346 |
+ } |
347 |
+ installed = { |
348 |
+ "dev-libs/glib-1.2.10" : { |
349 |
+ "EAPI": "4-slot-abi", |
350 |
+ "SLOT": "1" |
351 |
+ }, |
352 |
+ "dev-libs/glib-2.32.3" : { |
353 |
+ "EAPI": "4-slot-abi", |
354 |
+ "SLOT": "2/2.32" |
355 |
+ }, |
356 |
+ "dev-libs/dbus-glib-0.98" : { |
357 |
+ "EAPI": "4-slot-abi", |
358 |
+ "DEPEND": "dev-libs/glib:2/2.32=", |
359 |
+ "RDEPEND": "dev-libs/glib:2/2.32=" |
360 |
+ }, |
361 |
+ } |
362 |
+ |
363 |
+ world = ["dev-libs/glib:1", "dev-libs/dbus-glib"] |
364 |
+ |
365 |
+ test_cases = ( |
366 |
+ |
367 |
+ ResolverPlaygroundTestCase( |
368 |
+ ["dev-libs/glib"], |
369 |
+ options = {"--oneshot": True}, |
370 |
+ success = True, |
371 |
+ mergelist = ["dev-libs/glib-2.30.2", "dev-libs/dbus-glib-0.98" ]), |
372 |
+ |
373 |
+ ResolverPlaygroundTestCase( |
374 |
+ ["dev-libs/glib"], |
375 |
+ options = {"--oneshot": True, "--ignore-built-slot-abi-deps": "y"}, |
376 |
+ success = True, |
377 |
+ mergelist = ["dev-libs/glib-2.30.2"]), |
378 |
+ |
379 |
+ ResolverPlaygroundTestCase( |
380 |
+ ["dev-libs/glib"], |
381 |
+ options = {"--oneshot": True, "--usepkg": True}, |
382 |
+ success = True, |
383 |
+ mergelist = ["[binary]dev-libs/glib-2.30.2", "dev-libs/dbus-glib-0.98" ]), |
384 |
+ |
385 |
+ ResolverPlaygroundTestCase( |
386 |
+ ["dev-libs/glib"], |
387 |
+ options = {"--oneshot": True, "--usepkgonly": True}, |
388 |
+ success = True, |
389 |
+ mergelist = ["[binary]dev-libs/glib-2.32.3"]), |
390 |
+ |
391 |
+ ResolverPlaygroundTestCase( |
392 |
+ ["@world"], |
393 |
+ options = {"--update": True, "--deep": True}, |
394 |
+ success = True, |
395 |
+ mergelist = ["dev-libs/glib-2.30.2", "dev-libs/dbus-glib-0.98" ]), |
396 |
+ |
397 |
+ ResolverPlaygroundTestCase( |
398 |
+ ["@world"], |
399 |
+ options = {"--update": True, "--deep": True, "--ignore-built-slot-abi-deps": "y"}, |
400 |
+ success = True, |
401 |
+ mergelist = ["dev-libs/glib-2.30.2"]), |
402 |
+ |
403 |
+ ResolverPlaygroundTestCase( |
404 |
+ ["@world"], |
405 |
+ options = {"--update": True, "--deep": True, "--usepkg": True}, |
406 |
+ success = True, |
407 |
+ mergelist = ["[binary]dev-libs/glib-2.30.2", "dev-libs/dbus-glib-0.98" ]), |
408 |
+ |
409 |
+ ResolverPlaygroundTestCase( |
410 |
+ ["@world"], |
411 |
+ options = {"--update": True, "--deep": True, "--usepkgonly": True}, |
412 |
+ success = True, |
413 |
+ mergelist = []), |
414 |
+ |
415 |
+ ) |
416 |
+ |
417 |
+ playground = ResolverPlayground(ebuilds=ebuilds, binpkgs=binpkgs, |
418 |
+ installed=installed, world=world, debug=False) |
419 |
+ try: |
420 |
+ for test_case in test_cases: |
421 |
+ playground.run_TestCase(test_case) |
422 |
+ self.assertEqual(test_case.test_success, True, test_case.fail_msg) |
423 |
+ finally: |
424 |
+ playground.cleanup() |