Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH] _dep_check_composite_db: fix bug #526160
Date: Wed, 29 Oct 2014 09:29:37
Message-Id: 1414574947-3875-1-git-send-email-zmedico@gentoo.org
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

Replies