1 |
The fixes various forms of buggy behavior involving virtuals handling |
2 |
and EAPI 5 subslots. The code at fault is part of the support for |
3 |
bug #141118 (virtuals lookahead). This code was written long before |
4 |
subslots existed, and because of them it needs to be updated now. |
5 |
|
6 |
Previously, the relevant virtuals code would only select one virtual |
7 |
from each slot for lookahead. Now, it needs to select one from each |
8 |
slot/subslot pair. The buggy forms of behavior fixed by this change |
9 |
can be difficult to reproduce, since they only express themselves |
10 |
under some rare circumstances. |
11 |
|
12 |
In addition to the _dep_check_composite_db fixes, there is also a |
13 |
related fix inside _expand_new_virtuals, which is required so that |
14 |
_slot_operator_update_probe can reliably check whether or not a |
15 |
particular input atom was selected. Without this change, the |
16 |
_dep_check_composite_db changes will cause the test from commit |
17 |
d3be49fe6827aa1974856dffe6d5a1aca80a7bed to fail in a way that is |
18 |
very similar to the failure reported in bug #526160. |
19 |
|
20 |
Fixes: d3be49fe6827 ("depgraph: fix bug #526160") |
21 |
X-Gentoo-Bug: 526160 |
22 |
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=526160 |
23 |
--- |
24 |
pym/_emerge/depgraph.py | 118 ++++++++++++++++++------ |
25 |
pym/portage/dep/dep_check.py | 8 +- |
26 |
pym/portage/tests/resolver/test_virtual_slot.py | 11 ++- |
27 |
3 files changed, 106 insertions(+), 31 deletions(-) |
28 |
|
29 |
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py |
30 |
index 78b9236..94eaed8 100644 |
31 |
--- a/pym/_emerge/depgraph.py |
32 |
+++ b/pym/_emerge/depgraph.py |
33 |
@@ -8474,12 +8474,11 @@ class _dep_check_composite_db(dbapi): |
34 |
ret.append(pkg) |
35 |
|
36 |
if pkg is not None and \ |
37 |
- atom.slot is None and \ |
38 |
+ atom.sub_slot is None and \ |
39 |
pkg.cp.startswith("virtual/") and \ |
40 |
(("remove" not in self._depgraph._dynamic_config.myparams and |
41 |
"--update" not in self._depgraph._frozen_config.myopts) or |
42 |
- not ret or |
43 |
- not self._depgraph._virt_deps_visible(pkg, ignore_use=True)): |
44 |
+ not ret): |
45 |
# For new-style virtual lookahead that occurs inside dep_check() |
46 |
# for bug #141118, examine all slots. This is needed so that newer |
47 |
# slots will not unnecessarily be pulled in when a satisfying lower |
48 |
@@ -8487,34 +8486,66 @@ class _dep_check_composite_db(dbapi): |
49 |
# satisfied via gcj-jdk then there's no need to pull in a newer |
50 |
# slot to satisfy a virtual/jdk dependency, unless --update is |
51 |
# enabled. |
52 |
- slots = set() |
53 |
- slots.add(pkg.slot) |
54 |
+ sub_slots = set() |
55 |
+ resolved_sub_slots = set() |
56 |
for virt_pkg in self._depgraph._iter_match_pkgs_any( |
57 |
self._depgraph._frozen_config.roots[self._root], atom): |
58 |
if virt_pkg.cp != pkg.cp: |
59 |
continue |
60 |
- slots.add(virt_pkg.slot) |
61 |
+ sub_slots.add((virt_pkg.slot, virt_pkg.sub_slot)) |
62 |
+ |
63 |
+ sub_slot_key = (pkg.slot, pkg.sub_slot) |
64 |
+ if ret: |
65 |
+ # We've added pkg to ret already, and only one package |
66 |
+ # per slot/sub_slot is desired here. |
67 |
+ sub_slots.discard(sub_slot_key) |
68 |
+ resolved_sub_slots.add(sub_slot_key) |
69 |
+ else: |
70 |
+ sub_slots.add(sub_slot_key) |
71 |
|
72 |
- slots.remove(pkg.slot) |
73 |
- while slots: |
74 |
- slot_atom = atom.with_slot(slots.pop()) |
75 |
+ while sub_slots: |
76 |
+ slot, sub_slot = sub_slots.pop() |
77 |
+ slot_atom = atom.with_slot("%s/%s" % (slot, sub_slot)) |
78 |
pkg, existing = self._depgraph._select_package( |
79 |
self._root, slot_atom) |
80 |
if not pkg: |
81 |
continue |
82 |
- if not self._visible(pkg, atom_set): |
83 |
- continue |
84 |
+ if not self._visible(pkg, atom_set, |
85 |
+ avoid_slot_conflict=False): |
86 |
+ # Try to force a virtual update to be pulled in |
87 |
+ # when appropriate for bug #526160. |
88 |
+ selected = pkg |
89 |
+ for candidate in \ |
90 |
+ self._iter_virt_update(pkg, atom_set): |
91 |
+ |
92 |
+ if candidate.slot != slot: |
93 |
+ continue |
94 |
+ |
95 |
+ if (candidate.slot, candidate.sub_slot) in \ |
96 |
+ resolved_sub_slots: |
97 |
+ continue |
98 |
+ |
99 |
+ if selected is None or \ |
100 |
+ selected < candidate: |
101 |
+ selected = candidate |
102 |
+ |
103 |
+ if selected is pkg: |
104 |
+ continue |
105 |
+ pkg = selected |
106 |
+ |
107 |
+ resolved_sub_slots.add((pkg.slot, pkg.sub_slot)) |
108 |
ret.append(pkg) |
109 |
|
110 |
if len(ret) > 1: |
111 |
- ret.sort() |
112 |
+ ret = sorted(set(ret)) |
113 |
|
114 |
self._match_cache[cache_key] = ret |
115 |
for pkg in ret: |
116 |
self._cpv_pkg_map[pkg.cpv] = pkg |
117 |
return ret[:] |
118 |
|
119 |
- def _visible(self, pkg, atom_set): |
120 |
+ def _visible(self, pkg, atom_set, avoid_slot_conflict=True, |
121 |
+ probe_virt_update=True): |
122 |
if pkg.installed and not self._depgraph._want_installed_pkg(pkg): |
123 |
return False |
124 |
if pkg.installed and \ |
125 |
@@ -8536,22 +8567,23 @@ class _dep_check_composite_db(dbapi): |
126 |
return False |
127 |
|
128 |
if pkg.cp.startswith("virtual/"): |
129 |
- # Force virtual updates to be pulled in when appropriate |
130 |
- # for bug #526160. |
131 |
- want_update = False |
132 |
- if self._depgraph._select_atoms_parent is not None: |
133 |
- want_update = \ |
134 |
- self._depgraph._want_update_pkg( |
135 |
- self._depgraph._select_atoms_parent, pkg) |
136 |
- |
137 |
- if want_update: |
138 |
- for new_child in self._depgraph._iter_similar_available( |
139 |
- pkg, next(iter(atom_set))): |
140 |
- if not self._depgraph._virt_deps_visible( |
141 |
- new_child, ignore_use=True): |
142 |
- continue |
143 |
- if pkg < new_child: |
144 |
- return False |
145 |
+ |
146 |
+ if not self._depgraph._virt_deps_visible( |
147 |
+ pkg, ignore_use=True): |
148 |
+ return False |
149 |
+ |
150 |
+ if probe_virt_update and \ |
151 |
+ self._have_virt_update(pkg, atom_set): |
152 |
+ # Force virtual updates to be pulled in when appropriate |
153 |
+ # for bug #526160. |
154 |
+ return False |
155 |
+ |
156 |
+ if not avoid_slot_conflict: |
157 |
+ # This is useful when trying to pull in virtual updates, |
158 |
+ # since we don't want another instance that was previously |
159 |
+ # pulled in to mask an update that we're trying to pull |
160 |
+ # into the same slot. |
161 |
+ return True |
162 |
|
163 |
in_graph = next(self._depgraph._dynamic_config._package_tracker.match( |
164 |
self._root, pkg.slot_atom, installed=False), None) |
165 |
@@ -8578,6 +8610,34 @@ class _dep_check_composite_db(dbapi): |
166 |
return False |
167 |
return True |
168 |
|
169 |
+ def _iter_virt_update(self, pkg, atom_set): |
170 |
+ |
171 |
+ if self._depgraph._select_atoms_parent is not None and \ |
172 |
+ self._depgraph._want_update_pkg( |
173 |
+ self._depgraph._select_atoms_parent, pkg): |
174 |
+ |
175 |
+ for new_child in self._depgraph._iter_similar_available( |
176 |
+ pkg, next(iter(atom_set))): |
177 |
+ |
178 |
+ if not self._depgraph._virt_deps_visible( |
179 |
+ new_child, ignore_use=True): |
180 |
+ continue |
181 |
+ |
182 |
+ if not self._visible(new_child, atom_set, |
183 |
+ avoid_slot_conflict=False, |
184 |
+ probe_virt_update=False): |
185 |
+ continue |
186 |
+ |
187 |
+ yield new_child |
188 |
+ |
189 |
+ def _have_virt_update(self, pkg, atom_set): |
190 |
+ |
191 |
+ for new_child in self._iter_virt_update(pkg, atom_set): |
192 |
+ if pkg < new_child: |
193 |
+ return True |
194 |
+ |
195 |
+ return False |
196 |
+ |
197 |
def aux_get(self, cpv, wants): |
198 |
metadata = self._cpv_pkg_map[cpv]._metadata |
199 |
return [metadata.get(x, "") for x in wants] |
200 |
diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py |
201 |
index 9f48713..62f42ac 100644 |
202 |
--- a/pym/portage/dep/dep_check.py |
203 |
+++ b/pym/portage/dep/dep_check.py |
204 |
@@ -188,13 +188,19 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/", |
205 |
raise ParseError("%s: %s '%s'" % \ |
206 |
(pkg, mycheck[1], depstring)) |
207 |
|
208 |
- # pull in the new-style virtual |
209 |
+ # Pull in virt_atom which refers to the specific version |
210 |
+ # of the virtual whose deps we're expanding. Also pull |
211 |
+ # in the original input atom, so that callers can reliably |
212 |
+ # check to see if a given input atom has been selected, |
213 |
+ # as in depgraph._slot_operator_update_probe. |
214 |
mycheck[1].append(virt_atom) |
215 |
+ mycheck[1].append(x) |
216 |
a.append(mycheck[1]) |
217 |
if atom_graph is not None: |
218 |
virt_atom_node = (virt_atom, id(virt_atom)) |
219 |
atom_graph.add(virt_atom_node, graph_parent) |
220 |
atom_graph.add(pkg, virt_atom_node) |
221 |
+ atom_graph.add((x, id(x)), graph_parent) |
222 |
|
223 |
if not a and mychoices: |
224 |
# Check for a virtual package.provided match. |
225 |
diff --git a/pym/portage/tests/resolver/test_virtual_slot.py b/pym/portage/tests/resolver/test_virtual_slot.py |
226 |
index 2e5ca7f..cee1a23 100644 |
227 |
--- a/pym/portage/tests/resolver/test_virtual_slot.py |
228 |
+++ b/pym/portage/tests/resolver/test_virtual_slot.py |
229 |
@@ -115,7 +115,7 @@ class VirtualSlotResolverTestCase(TestCase): |
230 |
}, |
231 |
"dev-python/pygments-1.6_p20140324-r1": { |
232 |
"EAPI": "5", |
233 |
- "DEPEND": "virtual/pypy:=" |
234 |
+ "DEPEND": "virtual/pypy:0=" |
235 |
} |
236 |
} |
237 |
|
238 |
@@ -147,6 +147,15 @@ class VirtualSlotResolverTestCase(TestCase): |
239 |
mergelist = ['dev-python/pypy-2.4.0', |
240 |
'virtual/pypy-2.4.0', |
241 |
'dev-python/pygments-1.6_p20140324-r1']), |
242 |
+ |
243 |
+ # Repeat above test, but with --dynamic-deps disabled. |
244 |
+ ResolverPlaygroundTestCase( |
245 |
+ ["@world"], |
246 |
+ options = {"--update": True, "--deep": True, "--dynamic-deps": "n"}, |
247 |
+ success=True, |
248 |
+ mergelist = ['dev-python/pypy-2.4.0', |
249 |
+ 'virtual/pypy-2.4.0', |
250 |
+ 'dev-python/pygments-1.6_p20140324-r1']), |
251 |
) |
252 |
|
253 |
playground = ResolverPlayground(debug=False, ebuilds=ebuilds, |
254 |
-- |
255 |
2.0.4 |