1 |
commit: 8838c798d771af7f5356cacf37e10d9f55ac6519 |
2 |
Author: Zac Medico <zmedico <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun Jun 17 03:06:36 2012 +0000 |
4 |
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Jun 17 03:06:36 2012 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=8838c798 |
7 |
|
8 |
depgraph: split out _handle_slot_conflict method |
9 |
|
10 |
--- |
11 |
pym/_emerge/depgraph.py | 245 ++++++++++++++++++++++++----------------------- |
12 |
1 files changed, 125 insertions(+), 120 deletions(-) |
13 |
|
14 |
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py |
15 |
index 276a749..ec9434b 100644 |
16 |
--- a/pym/_emerge/depgraph.py |
17 |
+++ b/pym/_emerge/depgraph.py |
18 |
@@ -833,6 +833,128 @@ class depgraph(object): |
19 |
else: |
20 |
self._dynamic_config._slot_conflict_parent_atoms.add(parent_atom) |
21 |
|
22 |
+ def _handle_slot_conflict(self, existing_node, pkg, dep, arg_atoms): |
23 |
+ |
24 |
+ debug = "--debug" in self._frozen_config.myopts |
25 |
+ self._add_slot_conflict(pkg) |
26 |
+ |
27 |
+ if dep.atom is not None and dep.parent is not None: |
28 |
+ self._add_parent_atom(pkg, (dep.parent, dep.atom)) |
29 |
+ |
30 |
+ if arg_atoms: |
31 |
+ for parent_atom in arg_atoms: |
32 |
+ parent, atom = parent_atom |
33 |
+ self._add_parent_atom(pkg, parent_atom) |
34 |
+ |
35 |
+ # The existing node should not already be in |
36 |
+ # runtime_pkg_mask, since that would trigger an |
37 |
+ # infinite backtracking loop. |
38 |
+ if self._dynamic_config._allow_backtracking and \ |
39 |
+ existing_node in self._dynamic_config._runtime_pkg_mask: |
40 |
+ if debug: |
41 |
+ writemsg_level( |
42 |
+ "!!! backtracking loop detected: %s %s\n" % \ |
43 |
+ (existing_node, |
44 |
+ self._dynamic_config._runtime_pkg_mask[existing_node]), |
45 |
+ level=logging.DEBUG, noiselevel=-1) |
46 |
+ elif self._dynamic_config._allow_backtracking and \ |
47 |
+ not self._accept_blocker_conflicts() and \ |
48 |
+ not self.need_restart(): |
49 |
+ |
50 |
+ self._process_slot_conflicts() |
51 |
+ |
52 |
+ backtrack_data = [] |
53 |
+ fallback_data = [] |
54 |
+ all_parents = set() |
55 |
+ # The ordering of backtrack_data can make |
56 |
+ # a difference here, because both mask actions may lead |
57 |
+ # to valid, but different, solutions and the one with |
58 |
+ # 'existing_node' masked is usually the better one. Because |
59 |
+ # of that, we choose an order such that |
60 |
+ # the backtracker will first explore the choice with |
61 |
+ # existing_node masked. The backtracker reverses the |
62 |
+ # order, so the order it uses is the reverse of the |
63 |
+ # order shown here. See bug #339606. |
64 |
+ for to_be_selected, to_be_masked in (existing_node, pkg), (pkg, existing_node): |
65 |
+ # For missed update messages, find out which |
66 |
+ # atoms matched to_be_selected that did not |
67 |
+ # match to_be_masked. |
68 |
+ parent_atoms = \ |
69 |
+ self._dynamic_config._parent_atoms.get(to_be_selected, set()) |
70 |
+ if parent_atoms: |
71 |
+ conflict_atoms = self._dynamic_config._slot_conflict_parent_atoms.intersection(parent_atoms) |
72 |
+ if conflict_atoms: |
73 |
+ parent_atoms = conflict_atoms |
74 |
+ |
75 |
+ all_parents.update(parent_atoms) |
76 |
+ |
77 |
+ all_match = True |
78 |
+ for parent, atom in parent_atoms: |
79 |
+ i = InternalPackageSet(initial_atoms=(atom,), |
80 |
+ allow_repo=True) |
81 |
+ if not i.findAtomForPackage(to_be_masked): |
82 |
+ all_match = False |
83 |
+ break |
84 |
+ |
85 |
+ fallback_data.append((to_be_masked, parent_atoms)) |
86 |
+ |
87 |
+ if all_match: |
88 |
+ # 'to_be_masked' does not violate any parent atom, which means |
89 |
+ # there is no point in masking it. |
90 |
+ pass |
91 |
+ else: |
92 |
+ backtrack_data.append((to_be_masked, parent_atoms)) |
93 |
+ |
94 |
+ if not backtrack_data: |
95 |
+ # This shouldn't happen, but fall back to the old |
96 |
+ # behavior if this gets triggered somehow. |
97 |
+ backtrack_data = fallback_data |
98 |
+ |
99 |
+ if len(backtrack_data) > 1: |
100 |
+ # NOTE: Generally, we prefer to mask the higher |
101 |
+ # version since this solves common cases in which a |
102 |
+ # lower version is needed so that all dependencies |
103 |
+ # will be satisfied (bug #337178). However, if |
104 |
+ # existing_node happens to be installed then we |
105 |
+ # mask that since this is a common case that is |
106 |
+ # triggered when --update is not enabled. |
107 |
+ if existing_node.installed: |
108 |
+ pass |
109 |
+ elif pkg > existing_node: |
110 |
+ backtrack_data.reverse() |
111 |
+ |
112 |
+ to_be_masked = backtrack_data[-1][0] |
113 |
+ |
114 |
+ self._dynamic_config._backtrack_infos["slot conflict"] = backtrack_data |
115 |
+ self._dynamic_config._need_restart = True |
116 |
+ if debug: |
117 |
+ msg = [] |
118 |
+ msg.append("") |
119 |
+ msg.append("") |
120 |
+ msg.append("backtracking due to slot conflict:") |
121 |
+ if backtrack_data is fallback_data: |
122 |
+ msg.append("!!! backtrack_data fallback") |
123 |
+ msg.append(" first package: %s" % existing_node) |
124 |
+ msg.append(" second package: %s" % pkg) |
125 |
+ msg.append(" package to mask: %s" % to_be_masked) |
126 |
+ msg.append(" slot: %s" % pkg.slot_atom) |
127 |
+ msg.append(" parents: %s" % ", ".join( \ |
128 |
+ "(%s, '%s')" % (ppkg, atom) for ppkg, atom in all_parents)) |
129 |
+ msg.append("") |
130 |
+ writemsg_level("".join("%s\n" % l for l in msg), |
131 |
+ noiselevel=-1, level=logging.DEBUG) |
132 |
+ return False |
133 |
+ |
134 |
+ if debug: |
135 |
+ writemsg_level( |
136 |
+ "%s%s %s\n" % ("Slot Conflict:".ljust(15), |
137 |
+ existing_node, pkg_use_display(existing_node, |
138 |
+ self._frozen_config.myopts, |
139 |
+ modified_use=self._pkg_use_enabled(existing_node))), |
140 |
+ level=logging.DEBUG, noiselevel=-1) |
141 |
+ |
142 |
+ return True |
143 |
+ |
144 |
def _reinstall_for_flags(self, pkg, forced_flags, |
145 |
orig_use, orig_iuse, cur_use, cur_iuse): |
146 |
"""Return a set of flags that trigger reinstallation, or None if there |
147 |
@@ -1152,128 +1274,11 @@ class depgraph(object): |
148 |
return 1 |
149 |
else: |
150 |
# A slot conflict has occurred. |
151 |
- # The existing node should not already be in |
152 |
- # runtime_pkg_mask, since that would trigger an |
153 |
- # infinite backtracking loop. |
154 |
- if self._dynamic_config._allow_backtracking and \ |
155 |
- existing_node in \ |
156 |
- self._dynamic_config._runtime_pkg_mask: |
157 |
- if "--debug" in self._frozen_config.myopts: |
158 |
- writemsg( |
159 |
- "!!! backtracking loop detected: %s %s\n" % \ |
160 |
- (existing_node, |
161 |
- self._dynamic_config._runtime_pkg_mask[ |
162 |
- existing_node]), noiselevel=-1) |
163 |
- elif self._dynamic_config._allow_backtracking and \ |
164 |
- not self._accept_blocker_conflicts() and \ |
165 |
- not self.need_restart(): |
166 |
- |
167 |
- self._add_slot_conflict(pkg) |
168 |
- if dep.atom is not None and dep.parent is not None: |
169 |
- self._add_parent_atom(pkg, (dep.parent, dep.atom)) |
170 |
- |
171 |
- if arg_atoms: |
172 |
- for parent_atom in arg_atoms: |
173 |
- parent, atom = parent_atom |
174 |
- self._add_parent_atom(pkg, parent_atom) |
175 |
- self._process_slot_conflicts() |
176 |
- |
177 |
- backtrack_data = [] |
178 |
- fallback_data = [] |
179 |
- all_parents = set() |
180 |
- # The ordering of backtrack_data can make |
181 |
- # a difference here, because both mask actions may lead |
182 |
- # to valid, but different, solutions and the one with |
183 |
- # 'existing_node' masked is usually the better one. Because |
184 |
- # of that, we choose an order such that |
185 |
- # the backtracker will first explore the choice with |
186 |
- # existing_node masked. The backtracker reverses the |
187 |
- # order, so the order it uses is the reverse of the |
188 |
- # order shown here. See bug #339606. |
189 |
- for to_be_selected, to_be_masked in (existing_node, pkg), (pkg, existing_node): |
190 |
- # For missed update messages, find out which |
191 |
- # atoms matched to_be_selected that did not |
192 |
- # match to_be_masked. |
193 |
- parent_atoms = \ |
194 |
- self._dynamic_config._parent_atoms.get(to_be_selected, set()) |
195 |
- if parent_atoms: |
196 |
- conflict_atoms = self._dynamic_config._slot_conflict_parent_atoms.intersection(parent_atoms) |
197 |
- if conflict_atoms: |
198 |
- parent_atoms = conflict_atoms |
199 |
- |
200 |
- all_parents.update(parent_atoms) |
201 |
- |
202 |
- all_match = True |
203 |
- for parent, atom in parent_atoms: |
204 |
- i = InternalPackageSet(initial_atoms=(atom,), |
205 |
- allow_repo=True) |
206 |
- if not i.findAtomForPackage(to_be_masked): |
207 |
- all_match = False |
208 |
- break |
209 |
- |
210 |
- fallback_data.append((to_be_masked, parent_atoms)) |
211 |
- |
212 |
- if all_match: |
213 |
- # 'to_be_masked' does not violate any parent atom, which means |
214 |
- # there is no point in masking it. |
215 |
- pass |
216 |
- else: |
217 |
- backtrack_data.append((to_be_masked, parent_atoms)) |
218 |
- |
219 |
- if not backtrack_data: |
220 |
- # This shouldn't happen, but fall back to the old |
221 |
- # behavior if this gets triggered somehow. |
222 |
- backtrack_data = fallback_data |
223 |
- |
224 |
- if len(backtrack_data) > 1: |
225 |
- # NOTE: Generally, we prefer to mask the higher |
226 |
- # version since this solves common cases in which a |
227 |
- # lower version is needed so that all dependencies |
228 |
- # will be satisfied (bug #337178). However, if |
229 |
- # existing_node happens to be installed then we |
230 |
- # mask that since this is a common case that is |
231 |
- # triggered when --update is not enabled. |
232 |
- if existing_node.installed: |
233 |
- pass |
234 |
- elif pkg > existing_node: |
235 |
- backtrack_data.reverse() |
236 |
- |
237 |
- to_be_masked = backtrack_data[-1][0] |
238 |
- |
239 |
- self._dynamic_config._backtrack_infos["slot conflict"] = backtrack_data |
240 |
- self._dynamic_config._need_restart = True |
241 |
- if "--debug" in self._frozen_config.myopts: |
242 |
- msg = [] |
243 |
- msg.append("") |
244 |
- msg.append("") |
245 |
- msg.append("backtracking due to slot conflict:") |
246 |
- if backtrack_data is fallback_data: |
247 |
- msg.append("!!! backtrack_data fallback") |
248 |
- msg.append(" first package: %s" % existing_node) |
249 |
- msg.append(" second package: %s" % pkg) |
250 |
- msg.append(" package to mask: %s" % to_be_masked) |
251 |
- msg.append(" slot: %s" % pkg.slot_atom) |
252 |
- msg.append(" parents: %s" % ", ".join( \ |
253 |
- "(%s, '%s')" % (ppkg, atom) for ppkg, atom in all_parents)) |
254 |
- msg.append("") |
255 |
- writemsg_level("".join("%s\n" % l for l in msg), |
256 |
- noiselevel=-1, level=logging.DEBUG) |
257 |
- return 0 |
258 |
- |
259 |
- # A slot collision has occurred. Sometimes this coincides |
260 |
- # with unresolvable blockers, so the slot collision will be |
261 |
- # shown later if there are no unresolvable blockers. |
262 |
- self._add_slot_conflict(pkg) |
263 |
+ if not self._handle_slot_conflict( |
264 |
+ existing_node, pkg, dep, arg_atoms): |
265 |
+ return False |
266 |
slot_collision = True |
267 |
|
268 |
- if debug: |
269 |
- writemsg_level( |
270 |
- "%s%s %s\n" % ("Slot Conflict:".ljust(15), |
271 |
- existing_node, pkg_use_display(existing_node, |
272 |
- self._frozen_config.myopts, |
273 |
- modified_use=self._pkg_use_enabled(existing_node))), |
274 |
- level=logging.DEBUG, noiselevel=-1) |
275 |
- |
276 |
if slot_collision: |
277 |
# Now add this node to the graph so that self.display() |
278 |
# can show use flags and --tree portage.output. This node is |