1 |
Author: zmedico |
2 |
Date: 2010-02-25 21:15:35 +0000 (Thu, 25 Feb 2010) |
3 |
New Revision: 15462 |
4 |
|
5 |
Added: |
6 |
main/trunk/pym/portage/dep/dep_check.py |
7 |
Modified: |
8 |
main/trunk/pym/portage/__init__.py |
9 |
Log: |
10 |
Move portage.dep_check and related functions to portage.dep.dep_check. |
11 |
|
12 |
|
13 |
Modified: main/trunk/pym/portage/__init__.py |
14 |
=================================================================== |
15 |
--- main/trunk/pym/portage/__init__.py 2010-02-25 20:48:08 UTC (rev 15461) |
16 |
+++ main/trunk/pym/portage/__init__.py 2010-02-25 21:15:35 UTC (rev 15462) |
17 |
@@ -92,6 +92,7 @@ |
18 |
'portage.dep:best_match_to_list,dep_getcpv,dep_getkey,' + \ |
19 |
'flatten,get_operator,isjustname,isspecific,isvalidatom,' + \ |
20 |
'match_from_list,match_to_list', |
21 |
+ 'portage.dep.dep_check:dep_check,dep_eval,dep_wordreduce,dep_zapdeps', |
22 |
'portage.eclass_cache', |
23 |
'portage.env.loaders', |
24 |
'portage.exception', |
25 |
@@ -912,624 +913,6 @@ |
26 |
newsplit.append(x) |
27 |
return newsplit |
28 |
|
29 |
-def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/", |
30 |
- trees=None, use_mask=None, use_force=None, **kwargs): |
31 |
- """ |
32 |
- In order to solve bug #141118, recursively expand new-style virtuals so |
33 |
- as to collapse one or more levels of indirection, generating an expanded |
34 |
- search space. In dep_zapdeps, new-style virtuals will be assigned |
35 |
- zero cost regardless of whether or not they are currently installed. Virtual |
36 |
- blockers are supported but only when the virtual expands to a single |
37 |
- atom because it wouldn't necessarily make sense to block all the components |
38 |
- of a compound virtual. When more than one new-style virtual is matched, |
39 |
- the matches are sorted from highest to lowest versions and the atom is |
40 |
- expanded to || ( highest match ... lowest match ).""" |
41 |
- newsplit = [] |
42 |
- mytrees = trees[myroot] |
43 |
- portdb = mytrees["porttree"].dbapi |
44 |
- atom_graph = mytrees.get("atom_graph") |
45 |
- parent = mytrees.get("parent") |
46 |
- virt_parent = mytrees.get("virt_parent") |
47 |
- graph_parent = None |
48 |
- eapi = None |
49 |
- if parent is not None: |
50 |
- if virt_parent is not None: |
51 |
- graph_parent = virt_parent |
52 |
- eapi = virt_parent[0].metadata['EAPI'] |
53 |
- else: |
54 |
- graph_parent = parent |
55 |
- eapi = parent.metadata["EAPI"] |
56 |
- repoman = not mysettings.local_config |
57 |
- if kwargs["use_binaries"]: |
58 |
- portdb = trees[myroot]["bintree"].dbapi |
59 |
- myvirtuals = mysettings.getvirtuals() |
60 |
- pprovideddict = mysettings.pprovideddict |
61 |
- myuse = kwargs["myuse"] |
62 |
- for x in mysplit: |
63 |
- if x == "||": |
64 |
- newsplit.append(x) |
65 |
- continue |
66 |
- elif isinstance(x, list): |
67 |
- newsplit.append(_expand_new_virtuals(x, edebug, mydbapi, |
68 |
- mysettings, myroot=myroot, trees=trees, use_mask=use_mask, |
69 |
- use_force=use_force, **kwargs)) |
70 |
- continue |
71 |
- |
72 |
- if not isinstance(x, portage.dep.Atom): |
73 |
- try: |
74 |
- x = portage.dep.Atom(x) |
75 |
- except portage.exception.InvalidAtom: |
76 |
- if portage.dep._dep_check_strict: |
77 |
- raise portage.exception.ParseError( |
78 |
- _("invalid atom: '%s'") % x) |
79 |
- else: |
80 |
- # Only real Atom instances are allowed past this point. |
81 |
- continue |
82 |
- else: |
83 |
- if x.blocker and x.blocker.overlap.forbid and \ |
84 |
- eapi in ("0", "1") and portage.dep._dep_check_strict: |
85 |
- raise portage.exception.ParseError( |
86 |
- _("invalid atom: '%s'") % (x,)) |
87 |
- if x.use and eapi in ("0", "1") and \ |
88 |
- portage.dep._dep_check_strict: |
89 |
- raise portage.exception.ParseError( |
90 |
- _("invalid atom: '%s'") % (x,)) |
91 |
- |
92 |
- if repoman and x.use and x.use.conditional: |
93 |
- evaluated_atom = portage.dep.remove_slot(x) |
94 |
- if x.slot: |
95 |
- evaluated_atom += ":%s" % x.slot |
96 |
- evaluated_atom += str(x.use._eval_qa_conditionals( |
97 |
- use_mask, use_force)) |
98 |
- x = portage.dep.Atom(evaluated_atom) |
99 |
- |
100 |
- if not repoman and \ |
101 |
- myuse is not None and isinstance(x, portage.dep.Atom) and x.use: |
102 |
- if x.use.conditional: |
103 |
- x = x.evaluate_conditionals(myuse) |
104 |
- |
105 |
- mykey = x.cp |
106 |
- if not mykey.startswith("virtual/"): |
107 |
- newsplit.append(x) |
108 |
- if atom_graph is not None: |
109 |
- atom_graph.add(x, graph_parent) |
110 |
- continue |
111 |
- mychoices = myvirtuals.get(mykey, []) |
112 |
- if x.blocker: |
113 |
- # Virtual blockers are no longer expanded here since |
114 |
- # the un-expanded virtual atom is more useful for |
115 |
- # maintaining a cache of blocker atoms. |
116 |
- newsplit.append(x) |
117 |
- if atom_graph is not None: |
118 |
- atom_graph.add(x, graph_parent) |
119 |
- continue |
120 |
- |
121 |
- if repoman or not hasattr(portdb, 'match_pkgs'): |
122 |
- if portdb.cp_list(x.cp): |
123 |
- newsplit.append(x) |
124 |
- else: |
125 |
- # TODO: Add PROVIDE check for repoman. |
126 |
- a = [] |
127 |
- for y in mychoices: |
128 |
- a.append(dep.Atom(x.replace(x.cp, y.cp, 1))) |
129 |
- if not a: |
130 |
- newsplit.append(x) |
131 |
- elif len(a) == 1: |
132 |
- newsplit.append(a[0]) |
133 |
- else: |
134 |
- newsplit.append(['||'] + a) |
135 |
- continue |
136 |
- |
137 |
- pkgs = [] |
138 |
- # Ignore USE deps here, since otherwise we might not |
139 |
- # get any matches. Choices with correct USE settings |
140 |
- # will be preferred in dep_zapdeps(). |
141 |
- matches = portdb.match_pkgs(x.without_use) |
142 |
- # Use descending order to prefer higher versions. |
143 |
- matches.reverse() |
144 |
- for pkg in matches: |
145 |
- # only use new-style matches |
146 |
- if pkg.cp.startswith("virtual/"): |
147 |
- pkgs.append(pkg) |
148 |
- if not (pkgs or mychoices): |
149 |
- # This one couldn't be expanded as a new-style virtual. Old-style |
150 |
- # virtuals have already been expanded by dep_virtual, so this one |
151 |
- # is unavailable and dep_zapdeps will identify it as such. The |
152 |
- # atom is not eliminated here since it may still represent a |
153 |
- # dependency that needs to be satisfied. |
154 |
- newsplit.append(x) |
155 |
- if atom_graph is not None: |
156 |
- atom_graph.add(x, graph_parent) |
157 |
- continue |
158 |
- |
159 |
- a = [] |
160 |
- for pkg in pkgs: |
161 |
- virt_atom = '=' + pkg.cpv |
162 |
- if x.use: |
163 |
- virt_atom += str(x.use) |
164 |
- virt_atom = dep.Atom(virt_atom) |
165 |
- # According to GLEP 37, RDEPEND is the only dependency |
166 |
- # type that is valid for new-style virtuals. Repoman |
167 |
- # should enforce this. |
168 |
- depstring = pkg.metadata['RDEPEND'] |
169 |
- pkg_kwargs = kwargs.copy() |
170 |
- pkg_kwargs["myuse"] = pkg.use.enabled |
171 |
- if edebug: |
172 |
- util.writemsg_level(_("Virtual Parent: %s\n") \ |
173 |
- % (pkg,), noiselevel=-1, level=logging.DEBUG) |
174 |
- util.writemsg_level(_("Virtual Depstring: %s\n") \ |
175 |
- % (depstring,), noiselevel=-1, level=logging.DEBUG) |
176 |
- |
177 |
- # Set EAPI used for validation in dep_check() recursion. |
178 |
- mytrees["virt_parent"] = (pkg, virt_atom) |
179 |
- |
180 |
- try: |
181 |
- mycheck = dep_check(depstring, mydbapi, mysettings, |
182 |
- myroot=myroot, trees=trees, **pkg_kwargs) |
183 |
- finally: |
184 |
- # Restore previous EAPI after recursion. |
185 |
- if virt_parent is not None: |
186 |
- mytrees["virt_parent"] = virt_parent |
187 |
- else: |
188 |
- del mytrees["virt_parent"] |
189 |
- |
190 |
- if not mycheck[0]: |
191 |
- raise portage.exception.ParseError( |
192 |
- "%s: %s '%s'" % (y[0], mycheck[1], depstring)) |
193 |
- |
194 |
- # pull in the new-style virtual |
195 |
- mycheck[1].append(virt_atom) |
196 |
- a.append(mycheck[1]) |
197 |
- if atom_graph is not None: |
198 |
- atom_graph.add(virt_atom, graph_parent) |
199 |
- # Plain old-style virtuals. New-style virtuals are preferred. |
200 |
- if not pkgs: |
201 |
- for y in mychoices: |
202 |
- new_atom = dep.Atom(x.replace(x.cp, y.cp, 1)) |
203 |
- matches = portdb.match(new_atom) |
204 |
- # portdb is an instance of depgraph._dep_check_composite_db, so |
205 |
- # USE conditionals are already evaluated. |
206 |
- if matches and mykey in \ |
207 |
- portdb.aux_get(matches[-1], ['PROVIDE'])[0].split(): |
208 |
- a.append(new_atom) |
209 |
- if atom_graph is not None: |
210 |
- atom_graph.add(new_atom, graph_parent) |
211 |
- |
212 |
- if not a and mychoices: |
213 |
- # Check for a virtual package.provided match. |
214 |
- for y in mychoices: |
215 |
- new_atom = dep.Atom(x.replace(x.cp, y.cp, 1)) |
216 |
- if match_from_list(new_atom, |
217 |
- pprovideddict.get(new_atom.cp, [])): |
218 |
- a.append(new_atom) |
219 |
- if atom_graph is not None: |
220 |
- atom_graph.add(new_atom, graph_parent) |
221 |
- |
222 |
- if not a: |
223 |
- newsplit.append(x) |
224 |
- if atom_graph is not None: |
225 |
- atom_graph.add(x, graph_parent) |
226 |
- elif len(a) == 1: |
227 |
- newsplit.append(a[0]) |
228 |
- else: |
229 |
- newsplit.append(['||'] + a) |
230 |
- |
231 |
- return newsplit |
232 |
- |
233 |
-def dep_eval(deplist): |
234 |
- if not deplist: |
235 |
- return 1 |
236 |
- if deplist[0]=="||": |
237 |
- #or list; we just need one "1" |
238 |
- for x in deplist[1:]: |
239 |
- if isinstance(x, list): |
240 |
- if dep_eval(x)==1: |
241 |
- return 1 |
242 |
- elif x==1: |
243 |
- return 1 |
244 |
- #XXX: unless there's no available atoms in the list |
245 |
- #in which case we need to assume that everything is |
246 |
- #okay as some ebuilds are relying on an old bug. |
247 |
- if len(deplist) == 1: |
248 |
- return 1 |
249 |
- return 0 |
250 |
- else: |
251 |
- for x in deplist: |
252 |
- if isinstance(x, list): |
253 |
- if dep_eval(x)==0: |
254 |
- return 0 |
255 |
- elif x==0 or x==2: |
256 |
- return 0 |
257 |
- return 1 |
258 |
- |
259 |
-def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): |
260 |
- """Takes an unreduced and reduced deplist and removes satisfied dependencies. |
261 |
- Returned deplist contains steps that must be taken to satisfy dependencies.""" |
262 |
- if trees is None: |
263 |
- global db |
264 |
- trees = db |
265 |
- writemsg("ZapDeps -- %s\n" % (use_binaries), 2) |
266 |
- if not reduced or unreduced == ["||"] or dep_eval(reduced): |
267 |
- return [] |
268 |
- |
269 |
- if unreduced[0] != "||": |
270 |
- unresolved = [] |
271 |
- for x, satisfied in zip(unreduced, reduced): |
272 |
- if isinstance(x, list): |
273 |
- unresolved += dep_zapdeps(x, satisfied, myroot, |
274 |
- use_binaries=use_binaries, trees=trees) |
275 |
- elif not satisfied: |
276 |
- unresolved.append(x) |
277 |
- return unresolved |
278 |
- |
279 |
- # We're at a ( || atom ... ) type level and need to make a choice |
280 |
- deps = unreduced[1:] |
281 |
- satisfieds = reduced[1:] |
282 |
- |
283 |
- # Our preference order is for an the first item that: |
284 |
- # a) contains all unmasked packages with the same key as installed packages |
285 |
- # b) contains all unmasked packages |
286 |
- # c) contains masked installed packages |
287 |
- # d) is the first item |
288 |
- |
289 |
- preferred_installed = [] |
290 |
- preferred_in_graph = [] |
291 |
- preferred_any_slot = [] |
292 |
- preferred_non_installed = [] |
293 |
- unsat_use_in_graph = [] |
294 |
- unsat_use_installed = [] |
295 |
- unsat_use_non_installed = [] |
296 |
- other = [] |
297 |
- |
298 |
- # unsat_use_* must come after preferred_non_installed |
299 |
- # for correct ordering in cases like || ( foo[a] foo[b] ). |
300 |
- choice_bins = ( |
301 |
- preferred_in_graph, |
302 |
- preferred_installed, |
303 |
- preferred_any_slot, |
304 |
- preferred_non_installed, |
305 |
- unsat_use_in_graph, |
306 |
- unsat_use_installed, |
307 |
- unsat_use_non_installed, |
308 |
- other, |
309 |
- ) |
310 |
- |
311 |
- # Alias the trees we'll be checking availability against |
312 |
- parent = trees[myroot].get("parent") |
313 |
- priority = trees[myroot].get("priority") |
314 |
- graph_db = trees[myroot].get("graph_db") |
315 |
- vardb = None |
316 |
- if "vartree" in trees[myroot]: |
317 |
- vardb = trees[myroot]["vartree"].dbapi |
318 |
- if use_binaries: |
319 |
- mydbapi = trees[myroot]["bintree"].dbapi |
320 |
- else: |
321 |
- mydbapi = trees[myroot]["porttree"].dbapi |
322 |
- |
323 |
- # Sort the deps into installed, not installed but already |
324 |
- # in the graph and other, not installed and not in the graph |
325 |
- # and other, with values of [[required_atom], availablility] |
326 |
- for x, satisfied in zip(deps, satisfieds): |
327 |
- if isinstance(x, list): |
328 |
- atoms = dep_zapdeps(x, satisfied, myroot, |
329 |
- use_binaries=use_binaries, trees=trees) |
330 |
- else: |
331 |
- atoms = [x] |
332 |
- if vardb is None: |
333 |
- # When called by repoman, we can simply return the first choice |
334 |
- # because dep_eval() handles preference selection. |
335 |
- return atoms |
336 |
- |
337 |
- all_available = True |
338 |
- all_use_satisfied = True |
339 |
- slot_map = {} |
340 |
- cp_map = {} |
341 |
- for atom in atoms: |
342 |
- if atom.blocker: |
343 |
- continue |
344 |
- # Ignore USE dependencies here since we don't want USE |
345 |
- # settings to adversely affect || preference evaluation. |
346 |
- avail_pkg = mydbapi.match(atom.without_use) |
347 |
- if avail_pkg: |
348 |
- avail_pkg = avail_pkg[-1] # highest (ascending order) |
349 |
- avail_slot = dep.Atom("%s:%s" % (atom.cp, |
350 |
- mydbapi.aux_get(avail_pkg, ["SLOT"])[0])) |
351 |
- if not avail_pkg: |
352 |
- all_available = False |
353 |
- all_use_satisfied = False |
354 |
- break |
355 |
- |
356 |
- if atom.use: |
357 |
- avail_pkg_use = mydbapi.match(atom) |
358 |
- if not avail_pkg_use: |
359 |
- all_use_satisfied = False |
360 |
- else: |
361 |
- # highest (ascending order) |
362 |
- avail_pkg_use = avail_pkg_use[-1] |
363 |
- if avail_pkg_use != avail_pkg: |
364 |
- avail_pkg = avail_pkg_use |
365 |
- avail_slot = dep.Atom("%s:%s" % (atom.cp, |
366 |
- mydbapi.aux_get(avail_pkg, ["SLOT"])[0])) |
367 |
- |
368 |
- slot_map[avail_slot] = avail_pkg |
369 |
- pkg_cp = cpv_getkey(avail_pkg) |
370 |
- highest_cpv = cp_map.get(pkg_cp) |
371 |
- if highest_cpv is None or \ |
372 |
- pkgcmp(catpkgsplit(avail_pkg)[1:], |
373 |
- catpkgsplit(highest_cpv)[1:]) > 0: |
374 |
- cp_map[pkg_cp] = avail_pkg |
375 |
- |
376 |
- this_choice = (atoms, slot_map, cp_map, all_available) |
377 |
- if all_available: |
378 |
- # The "all installed" criterion is not version or slot specific. |
379 |
- # If any version of a package is already in the graph then we |
380 |
- # assume that it is preferred over other possible packages choices. |
381 |
- all_installed = True |
382 |
- for atom in set(dep.Atom(atom.cp) for atom in atoms \ |
383 |
- if not atom.blocker): |
384 |
- # New-style virtuals have zero cost to install. |
385 |
- if not vardb.match(atom) and not atom.startswith("virtual/"): |
386 |
- all_installed = False |
387 |
- break |
388 |
- all_installed_slots = False |
389 |
- if all_installed: |
390 |
- all_installed_slots = True |
391 |
- for slot_atom in slot_map: |
392 |
- # New-style virtuals have zero cost to install. |
393 |
- if not vardb.match(slot_atom) and \ |
394 |
- not slot_atom.startswith("virtual/"): |
395 |
- all_installed_slots = False |
396 |
- break |
397 |
- if graph_db is None: |
398 |
- if all_use_satisfied: |
399 |
- if all_installed: |
400 |
- if all_installed_slots: |
401 |
- preferred_installed.append(this_choice) |
402 |
- else: |
403 |
- preferred_any_slot.append(this_choice) |
404 |
- else: |
405 |
- preferred_non_installed.append(this_choice) |
406 |
- else: |
407 |
- if all_installed_slots: |
408 |
- unsat_use_installed.append(this_choice) |
409 |
- else: |
410 |
- unsat_use_non_installed.append(this_choice) |
411 |
- else: |
412 |
- all_in_graph = True |
413 |
- for slot_atom in slot_map: |
414 |
- # New-style virtuals have zero cost to install. |
415 |
- if not graph_db.match(slot_atom) and \ |
416 |
- not slot_atom.startswith("virtual/"): |
417 |
- all_in_graph = False |
418 |
- break |
419 |
- circular_atom = None |
420 |
- if all_in_graph: |
421 |
- if parent is None or priority is None: |
422 |
- pass |
423 |
- elif priority.buildtime: |
424 |
- # Check if the atom would result in a direct circular |
425 |
- # dependency and try to avoid that if it seems likely |
426 |
- # to be unresolvable. This is only relevant for |
427 |
- # buildtime deps that aren't already satisfied by an |
428 |
- # installed package. |
429 |
- cpv_slot_list = [parent] |
430 |
- for atom in atoms: |
431 |
- if atom.blocker: |
432 |
- continue |
433 |
- if vardb.match(atom): |
434 |
- # If the atom is satisfied by an installed |
435 |
- # version then it's not a circular dep. |
436 |
- continue |
437 |
- if atom.cp != parent.cp: |
438 |
- continue |
439 |
- if match_from_list(atom, cpv_slot_list): |
440 |
- circular_atom = atom |
441 |
- break |
442 |
- if circular_atom is not None: |
443 |
- other.append(this_choice) |
444 |
- else: |
445 |
- if all_use_satisfied: |
446 |
- if all_in_graph: |
447 |
- preferred_in_graph.append(this_choice) |
448 |
- elif all_installed: |
449 |
- if all_installed_slots: |
450 |
- preferred_installed.append(this_choice) |
451 |
- else: |
452 |
- preferred_any_slot.append(this_choice) |
453 |
- else: |
454 |
- preferred_non_installed.append(this_choice) |
455 |
- else: |
456 |
- if all_in_graph: |
457 |
- unsat_use_in_graph.append(this_choice) |
458 |
- elif all_installed_slots: |
459 |
- unsat_use_installed.append(this_choice) |
460 |
- else: |
461 |
- unsat_use_non_installed.append(this_choice) |
462 |
- else: |
463 |
- other.append(this_choice) |
464 |
- |
465 |
- # Prefer choices which contain upgrades to higher slots. This helps |
466 |
- # for deps such as || ( foo:1 foo:2 ), where we want to prefer the |
467 |
- # atom which matches the higher version rather than the atom furthest |
468 |
- # to the left. Sorting is done separately for each of choice_bins, so |
469 |
- # as not to interfere with the ordering of the bins. Because of the |
470 |
- # bin separation, the main function of this code is to allow |
471 |
- # --depclean to remove old slots (rather than to pull in new slots). |
472 |
- for choices in choice_bins: |
473 |
- if len(choices) < 2: |
474 |
- continue |
475 |
- for choice_1 in choices[1:]: |
476 |
- atoms_1, slot_map_1, cp_map_1, all_available_1 = choice_1 |
477 |
- cps = set(cp_map_1) |
478 |
- for choice_2 in choices: |
479 |
- if choice_1 is choice_2: |
480 |
- # choice_1 will not be promoted, so move on |
481 |
- break |
482 |
- atoms_2, slot_map_2, cp_map_2, all_available_2 = choice_2 |
483 |
- intersecting_cps = cps.intersection(cp_map_2) |
484 |
- if not intersecting_cps: |
485 |
- continue |
486 |
- has_upgrade = False |
487 |
- has_downgrade = False |
488 |
- for cp in intersecting_cps: |
489 |
- version_1 = cp_map_1[cp] |
490 |
- version_2 = cp_map_2[cp] |
491 |
- difference = pkgcmp(catpkgsplit(version_1)[1:], |
492 |
- catpkgsplit(version_2)[1:]) |
493 |
- if difference != 0: |
494 |
- if difference > 0: |
495 |
- has_upgrade = True |
496 |
- else: |
497 |
- has_downgrade = True |
498 |
- break |
499 |
- if has_upgrade and not has_downgrade: |
500 |
- # promote choice_1 in front of choice_2 |
501 |
- choices.remove(choice_1) |
502 |
- index_2 = choices.index(choice_2) |
503 |
- choices.insert(index_2, choice_1) |
504 |
- break |
505 |
- |
506 |
- for allow_masked in (False, True): |
507 |
- for choices in choice_bins: |
508 |
- for atoms, slot_map, cp_map, all_available in choices: |
509 |
- if all_available or allow_masked: |
510 |
- return atoms |
511 |
- |
512 |
- assert(False) # This point should not be reachable |
513 |
- |
514 |
-def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None, |
515 |
- use_cache=1, use_binaries=0, myroot="/", trees=None): |
516 |
- """Takes a depend string and parses the condition.""" |
517 |
- edebug = mysettings.get("PORTAGE_DEBUG", None) == "1" |
518 |
- #check_config_instance(mysettings) |
519 |
- if trees is None: |
520 |
- trees = globals()["db"] |
521 |
- if use=="yes": |
522 |
- if myuse is None: |
523 |
- #default behavior |
524 |
- myusesplit = mysettings["PORTAGE_USE"].split() |
525 |
- else: |
526 |
- myusesplit = myuse |
527 |
- # We've been given useflags to use. |
528 |
- #print "USE FLAGS PASSED IN." |
529 |
- #print myuse |
530 |
- #if "bindist" in myusesplit: |
531 |
- # print "BINDIST is set!" |
532 |
- #else: |
533 |
- # print "BINDIST NOT set." |
534 |
- else: |
535 |
- #we are being run by autouse(), don't consult USE vars yet. |
536 |
- # WE ALSO CANNOT USE SETTINGS |
537 |
- myusesplit=[] |
538 |
- |
539 |
- #convert parenthesis to sublists |
540 |
- try: |
541 |
- mysplit = portage.dep.paren_reduce(depstring) |
542 |
- except portage.exception.InvalidDependString as e: |
543 |
- return [0, str(e)] |
544 |
- |
545 |
- mymasks = set() |
546 |
- useforce = set() |
547 |
- useforce.add(mysettings["ARCH"]) |
548 |
- if use == "all": |
549 |
- # This masking/forcing is only for repoman. In other cases, relevant |
550 |
- # masking/forcing should have already been applied via |
551 |
- # config.regenerate(). Also, binary or installed packages may have |
552 |
- # been built with flags that are now masked, and it would be |
553 |
- # inconsistent to mask them now. Additionally, myuse may consist of |
554 |
- # flags from a parent package that is being merged to a $ROOT that is |
555 |
- # different from the one that mysettings represents. |
556 |
- mymasks.update(mysettings.usemask) |
557 |
- mymasks.update(mysettings.archlist()) |
558 |
- mymasks.discard(mysettings["ARCH"]) |
559 |
- useforce.update(mysettings.useforce) |
560 |
- useforce.difference_update(mymasks) |
561 |
- try: |
562 |
- mysplit = portage.dep.use_reduce(mysplit, uselist=myusesplit, |
563 |
- masklist=mymasks, matchall=(use=="all"), excludeall=useforce) |
564 |
- except portage.exception.InvalidDependString as e: |
565 |
- return [0, str(e)] |
566 |
- |
567 |
- # Do the || conversions |
568 |
- mysplit=portage.dep.dep_opconvert(mysplit) |
569 |
- |
570 |
- if mysplit == []: |
571 |
- #dependencies were reduced to nothing |
572 |
- return [1,[]] |
573 |
- |
574 |
- # Recursively expand new-style virtuals so as to |
575 |
- # collapse one or more levels of indirection. |
576 |
- try: |
577 |
- mysplit = _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, |
578 |
- use=use, mode=mode, myuse=myuse, |
579 |
- use_force=useforce, use_mask=mymasks, use_cache=use_cache, |
580 |
- use_binaries=use_binaries, myroot=myroot, trees=trees) |
581 |
- except portage.exception.ParseError as e: |
582 |
- return [0, str(e)] |
583 |
- |
584 |
- mysplit2=mysplit[:] |
585 |
- mysplit2=dep_wordreduce(mysplit2,mysettings,mydbapi,mode,use_cache=use_cache) |
586 |
- if mysplit2 is None: |
587 |
- return [0, _("Invalid token")] |
588 |
- |
589 |
- writemsg("\n\n\n", 1) |
590 |
- writemsg("mysplit: %s\n" % (mysplit), 1) |
591 |
- writemsg("mysplit2: %s\n" % (mysplit2), 1) |
592 |
- |
593 |
- try: |
594 |
- selected_atoms = dep_zapdeps(mysplit, mysplit2, myroot, |
595 |
- use_binaries=use_binaries, trees=trees) |
596 |
- except portage.exception.InvalidAtom as e: |
597 |
- if portage.dep._dep_check_strict: |
598 |
- raise # This shouldn't happen. |
599 |
- # dbapi.match() failed due to an invalid atom in |
600 |
- # the dependencies of an installed package. |
601 |
- return [0, _("Invalid atom: '%s'") % (e,)] |
602 |
- |
603 |
- return [1, selected_atoms] |
604 |
- |
605 |
-def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1): |
606 |
- "Reduces the deplist to ones and zeros" |
607 |
- deplist=mydeplist[:] |
608 |
- for mypos, token in enumerate(deplist): |
609 |
- if isinstance(deplist[mypos], list): |
610 |
- #recurse |
611 |
- deplist[mypos]=dep_wordreduce(deplist[mypos],mysettings,mydbapi,mode,use_cache=use_cache) |
612 |
- elif deplist[mypos]=="||": |
613 |
- pass |
614 |
- elif token[:1] == "!": |
615 |
- deplist[mypos] = False |
616 |
- else: |
617 |
- mykey = deplist[mypos].cp |
618 |
- if mysettings and mykey in mysettings.pprovideddict and \ |
619 |
- match_from_list(deplist[mypos], mysettings.pprovideddict[mykey]): |
620 |
- deplist[mypos]=True |
621 |
- elif mydbapi is None: |
622 |
- # Assume nothing is satisfied. This forces dep_zapdeps to |
623 |
- # return all of deps the deps that have been selected |
624 |
- # (excluding those satisfied by package.provided). |
625 |
- deplist[mypos] = False |
626 |
- else: |
627 |
- if mode: |
628 |
- x = mydbapi.xmatch(mode, deplist[mypos]) |
629 |
- if mode.startswith("minimum-"): |
630 |
- mydep = [] |
631 |
- if x: |
632 |
- mydep.append(x) |
633 |
- else: |
634 |
- mydep = x |
635 |
- else: |
636 |
- mydep=mydbapi.match(deplist[mypos],use_cache=use_cache) |
637 |
- if mydep!=None: |
638 |
- tmp=(len(mydep)>=1) |
639 |
- if deplist[mypos][0]=="!": |
640 |
- tmp=False |
641 |
- deplist[mypos]=tmp |
642 |
- else: |
643 |
- #encountered invalid string |
644 |
- return None |
645 |
- return deplist |
646 |
- |
647 |
def getmaskingreason(mycpv, metadata=None, settings=None, portdb=None, return_location=False): |
648 |
from portage.util import grablines |
649 |
if settings is None: |
650 |
|
651 |
Added: main/trunk/pym/portage/dep/dep_check.py |
652 |
=================================================================== |
653 |
--- main/trunk/pym/portage/dep/dep_check.py (rev 0) |
654 |
+++ main/trunk/pym/portage/dep/dep_check.py 2010-02-25 21:15:35 UTC (rev 15462) |
655 |
@@ -0,0 +1,634 @@ |
656 |
+# Copyright 2010 Gentoo Foundation |
657 |
+# Distributed under the terms of the GNU General Public License v2 |
658 |
+# $Id$ |
659 |
+ |
660 |
+__all__ = ['dep_check', 'dep_eval', 'dep_wordreduce', 'dep_zapdeps'] |
661 |
+ |
662 |
+import logging |
663 |
+ |
664 |
+import portage |
665 |
+from portage.dep import Atom, dep_opconvert, match_from_list, paren_reduce, \ |
666 |
+ remove_slot, use_reduce |
667 |
+from portage.exception import InvalidAtom, InvalidDependString, ParseError |
668 |
+from portage.localization import _ |
669 |
+from portage.util import writemsg, writemsg_level |
670 |
+from portage.versions import catpkgsplit, cpv_getkey, pkgcmp |
671 |
+ |
672 |
+def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/", |
673 |
+ trees=None, use_mask=None, use_force=None, **kwargs): |
674 |
+ """ |
675 |
+ In order to solve bug #141118, recursively expand new-style virtuals so |
676 |
+ as to collapse one or more levels of indirection, generating an expanded |
677 |
+ search space. In dep_zapdeps, new-style virtuals will be assigned |
678 |
+ zero cost regardless of whether or not they are currently installed. Virtual |
679 |
+ blockers are supported but only when the virtual expands to a single |
680 |
+ atom because it wouldn't necessarily make sense to block all the components |
681 |
+ of a compound virtual. When more than one new-style virtual is matched, |
682 |
+ the matches are sorted from highest to lowest versions and the atom is |
683 |
+ expanded to || ( highest match ... lowest match ).""" |
684 |
+ newsplit = [] |
685 |
+ mytrees = trees[myroot] |
686 |
+ portdb = mytrees["porttree"].dbapi |
687 |
+ atom_graph = mytrees.get("atom_graph") |
688 |
+ parent = mytrees.get("parent") |
689 |
+ virt_parent = mytrees.get("virt_parent") |
690 |
+ graph_parent = None |
691 |
+ eapi = None |
692 |
+ if parent is not None: |
693 |
+ if virt_parent is not None: |
694 |
+ graph_parent = virt_parent |
695 |
+ eapi = virt_parent[0].metadata['EAPI'] |
696 |
+ else: |
697 |
+ graph_parent = parent |
698 |
+ eapi = parent.metadata["EAPI"] |
699 |
+ repoman = not mysettings.local_config |
700 |
+ if kwargs["use_binaries"]: |
701 |
+ portdb = trees[myroot]["bintree"].dbapi |
702 |
+ myvirtuals = mysettings.getvirtuals() |
703 |
+ pprovideddict = mysettings.pprovideddict |
704 |
+ myuse = kwargs["myuse"] |
705 |
+ for x in mysplit: |
706 |
+ if x == "||": |
707 |
+ newsplit.append(x) |
708 |
+ continue |
709 |
+ elif isinstance(x, list): |
710 |
+ newsplit.append(_expand_new_virtuals(x, edebug, mydbapi, |
711 |
+ mysettings, myroot=myroot, trees=trees, use_mask=use_mask, |
712 |
+ use_force=use_force, **kwargs)) |
713 |
+ continue |
714 |
+ |
715 |
+ if not isinstance(x, Atom): |
716 |
+ try: |
717 |
+ x = Atom(x) |
718 |
+ except InvalidAtom: |
719 |
+ if portage.dep._dep_check_strict: |
720 |
+ raise ParseError( |
721 |
+ _("invalid atom: '%s'") % x) |
722 |
+ else: |
723 |
+ # Only real Atom instances are allowed past this point. |
724 |
+ continue |
725 |
+ else: |
726 |
+ if x.blocker and x.blocker.overlap.forbid and \ |
727 |
+ eapi in ("0", "1") and portage.dep._dep_check_strict: |
728 |
+ raise ParseError( |
729 |
+ _("invalid atom: '%s'") % (x,)) |
730 |
+ if x.use and eapi in ("0", "1") and \ |
731 |
+ portage.dep._dep_check_strict: |
732 |
+ raise ParseError( |
733 |
+ _("invalid atom: '%s'") % (x,)) |
734 |
+ |
735 |
+ if repoman and x.use and x.use.conditional: |
736 |
+ evaluated_atom = remove_slot(x) |
737 |
+ if x.slot: |
738 |
+ evaluated_atom += ":%s" % x.slot |
739 |
+ evaluated_atom += str(x.use._eval_qa_conditionals( |
740 |
+ use_mask, use_force)) |
741 |
+ x = Atom(evaluated_atom) |
742 |
+ |
743 |
+ if not repoman and \ |
744 |
+ myuse is not None and isinstance(x, Atom) and x.use: |
745 |
+ if x.use.conditional: |
746 |
+ x = x.evaluate_conditionals(myuse) |
747 |
+ |
748 |
+ mykey = x.cp |
749 |
+ if not mykey.startswith("virtual/"): |
750 |
+ newsplit.append(x) |
751 |
+ if atom_graph is not None: |
752 |
+ atom_graph.add(x, graph_parent) |
753 |
+ continue |
754 |
+ mychoices = myvirtuals.get(mykey, []) |
755 |
+ if x.blocker: |
756 |
+ # Virtual blockers are no longer expanded here since |
757 |
+ # the un-expanded virtual atom is more useful for |
758 |
+ # maintaining a cache of blocker atoms. |
759 |
+ newsplit.append(x) |
760 |
+ if atom_graph is not None: |
761 |
+ atom_graph.add(x, graph_parent) |
762 |
+ continue |
763 |
+ |
764 |
+ if repoman or not hasattr(portdb, 'match_pkgs'): |
765 |
+ if portdb.cp_list(x.cp): |
766 |
+ newsplit.append(x) |
767 |
+ else: |
768 |
+ # TODO: Add PROVIDE check for repoman. |
769 |
+ a = [] |
770 |
+ for y in mychoices: |
771 |
+ a.append(Atom(x.replace(x.cp, y.cp, 1))) |
772 |
+ if not a: |
773 |
+ newsplit.append(x) |
774 |
+ elif len(a) == 1: |
775 |
+ newsplit.append(a[0]) |
776 |
+ else: |
777 |
+ newsplit.append(['||'] + a) |
778 |
+ continue |
779 |
+ |
780 |
+ pkgs = [] |
781 |
+ # Ignore USE deps here, since otherwise we might not |
782 |
+ # get any matches. Choices with correct USE settings |
783 |
+ # will be preferred in dep_zapdeps(). |
784 |
+ matches = portdb.match_pkgs(x.without_use) |
785 |
+ # Use descending order to prefer higher versions. |
786 |
+ matches.reverse() |
787 |
+ for pkg in matches: |
788 |
+ # only use new-style matches |
789 |
+ if pkg.cp.startswith("virtual/"): |
790 |
+ pkgs.append(pkg) |
791 |
+ if not (pkgs or mychoices): |
792 |
+ # This one couldn't be expanded as a new-style virtual. Old-style |
793 |
+ # virtuals have already been expanded by dep_virtual, so this one |
794 |
+ # is unavailable and dep_zapdeps will identify it as such. The |
795 |
+ # atom is not eliminated here since it may still represent a |
796 |
+ # dependency that needs to be satisfied. |
797 |
+ newsplit.append(x) |
798 |
+ if atom_graph is not None: |
799 |
+ atom_graph.add(x, graph_parent) |
800 |
+ continue |
801 |
+ |
802 |
+ a = [] |
803 |
+ for pkg in pkgs: |
804 |
+ virt_atom = '=' + pkg.cpv |
805 |
+ if x.use: |
806 |
+ virt_atom += str(x.use) |
807 |
+ virt_atom = Atom(virt_atom) |
808 |
+ # According to GLEP 37, RDEPEND is the only dependency |
809 |
+ # type that is valid for new-style virtuals. Repoman |
810 |
+ # should enforce this. |
811 |
+ depstring = pkg.metadata['RDEPEND'] |
812 |
+ pkg_kwargs = kwargs.copy() |
813 |
+ pkg_kwargs["myuse"] = pkg.use.enabled |
814 |
+ if edebug: |
815 |
+ writemsg_level(_("Virtual Parent: %s\n") \ |
816 |
+ % (pkg,), noiselevel=-1, level=logging.DEBUG) |
817 |
+ writemsg_level(_("Virtual Depstring: %s\n") \ |
818 |
+ % (depstring,), noiselevel=-1, level=logging.DEBUG) |
819 |
+ |
820 |
+ # Set EAPI used for validation in dep_check() recursion. |
821 |
+ mytrees["virt_parent"] = (pkg, virt_atom) |
822 |
+ |
823 |
+ try: |
824 |
+ mycheck = dep_check(depstring, mydbapi, mysettings, |
825 |
+ myroot=myroot, trees=trees, **pkg_kwargs) |
826 |
+ finally: |
827 |
+ # Restore previous EAPI after recursion. |
828 |
+ if virt_parent is not None: |
829 |
+ mytrees["virt_parent"] = virt_parent |
830 |
+ else: |
831 |
+ del mytrees["virt_parent"] |
832 |
+ |
833 |
+ if not mycheck[0]: |
834 |
+ raise ParseError( |
835 |
+ "%s: %s '%s'" % (y[0], mycheck[1], depstring)) |
836 |
+ |
837 |
+ # pull in the new-style virtual |
838 |
+ mycheck[1].append(virt_atom) |
839 |
+ a.append(mycheck[1]) |
840 |
+ if atom_graph is not None: |
841 |
+ atom_graph.add(virt_atom, graph_parent) |
842 |
+ # Plain old-style virtuals. New-style virtuals are preferred. |
843 |
+ if not pkgs: |
844 |
+ for y in mychoices: |
845 |
+ new_atom = Atom(x.replace(x.cp, y.cp, 1)) |
846 |
+ matches = portdb.match(new_atom) |
847 |
+ # portdb is an instance of depgraph._dep_check_composite_db, so |
848 |
+ # USE conditionals are already evaluated. |
849 |
+ if matches and mykey in \ |
850 |
+ portdb.aux_get(matches[-1], ['PROVIDE'])[0].split(): |
851 |
+ a.append(new_atom) |
852 |
+ if atom_graph is not None: |
853 |
+ atom_graph.add(new_atom, graph_parent) |
854 |
+ |
855 |
+ if not a and mychoices: |
856 |
+ # Check for a virtual package.provided match. |
857 |
+ for y in mychoices: |
858 |
+ new_atom = Atom(x.replace(x.cp, y.cp, 1)) |
859 |
+ if match_from_list(new_atom, |
860 |
+ pprovideddict.get(new_atom.cp, [])): |
861 |
+ a.append(new_atom) |
862 |
+ if atom_graph is not None: |
863 |
+ atom_graph.add(new_atom, graph_parent) |
864 |
+ |
865 |
+ if not a: |
866 |
+ newsplit.append(x) |
867 |
+ if atom_graph is not None: |
868 |
+ atom_graph.add(x, graph_parent) |
869 |
+ elif len(a) == 1: |
870 |
+ newsplit.append(a[0]) |
871 |
+ else: |
872 |
+ newsplit.append(['||'] + a) |
873 |
+ |
874 |
+ return newsplit |
875 |
+ |
876 |
+def dep_eval(deplist): |
877 |
+ if not deplist: |
878 |
+ return 1 |
879 |
+ if deplist[0]=="||": |
880 |
+ #or list; we just need one "1" |
881 |
+ for x in deplist[1:]: |
882 |
+ if isinstance(x, list): |
883 |
+ if dep_eval(x)==1: |
884 |
+ return 1 |
885 |
+ elif x==1: |
886 |
+ return 1 |
887 |
+ #XXX: unless there's no available atoms in the list |
888 |
+ #in which case we need to assume that everything is |
889 |
+ #okay as some ebuilds are relying on an old bug. |
890 |
+ if len(deplist) == 1: |
891 |
+ return 1 |
892 |
+ return 0 |
893 |
+ else: |
894 |
+ for x in deplist: |
895 |
+ if isinstance(x, list): |
896 |
+ if dep_eval(x)==0: |
897 |
+ return 0 |
898 |
+ elif x==0 or x==2: |
899 |
+ return 0 |
900 |
+ return 1 |
901 |
+ |
902 |
+def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): |
903 |
+ """ |
904 |
+ Takes an unreduced and reduced deplist and removes satisfied dependencies. |
905 |
+ Returned deplist contains steps that must be taken to satisfy dependencies. |
906 |
+ """ |
907 |
+ if trees is None: |
908 |
+ trees = portage.db |
909 |
+ writemsg("ZapDeps -- %s\n" % (use_binaries), 2) |
910 |
+ if not reduced or unreduced == ["||"] or dep_eval(reduced): |
911 |
+ return [] |
912 |
+ |
913 |
+ if unreduced[0] != "||": |
914 |
+ unresolved = [] |
915 |
+ for x, satisfied in zip(unreduced, reduced): |
916 |
+ if isinstance(x, list): |
917 |
+ unresolved += dep_zapdeps(x, satisfied, myroot, |
918 |
+ use_binaries=use_binaries, trees=trees) |
919 |
+ elif not satisfied: |
920 |
+ unresolved.append(x) |
921 |
+ return unresolved |
922 |
+ |
923 |
+ # We're at a ( || atom ... ) type level and need to make a choice |
924 |
+ deps = unreduced[1:] |
925 |
+ satisfieds = reduced[1:] |
926 |
+ |
927 |
+ # Our preference order is for an the first item that: |
928 |
+ # a) contains all unmasked packages with the same key as installed packages |
929 |
+ # b) contains all unmasked packages |
930 |
+ # c) contains masked installed packages |
931 |
+ # d) is the first item |
932 |
+ |
933 |
+ preferred_installed = [] |
934 |
+ preferred_in_graph = [] |
935 |
+ preferred_any_slot = [] |
936 |
+ preferred_non_installed = [] |
937 |
+ unsat_use_in_graph = [] |
938 |
+ unsat_use_installed = [] |
939 |
+ unsat_use_non_installed = [] |
940 |
+ other = [] |
941 |
+ |
942 |
+ # unsat_use_* must come after preferred_non_installed |
943 |
+ # for correct ordering in cases like || ( foo[a] foo[b] ). |
944 |
+ choice_bins = ( |
945 |
+ preferred_in_graph, |
946 |
+ preferred_installed, |
947 |
+ preferred_any_slot, |
948 |
+ preferred_non_installed, |
949 |
+ unsat_use_in_graph, |
950 |
+ unsat_use_installed, |
951 |
+ unsat_use_non_installed, |
952 |
+ other, |
953 |
+ ) |
954 |
+ |
955 |
+ # Alias the trees we'll be checking availability against |
956 |
+ parent = trees[myroot].get("parent") |
957 |
+ priority = trees[myroot].get("priority") |
958 |
+ graph_db = trees[myroot].get("graph_db") |
959 |
+ vardb = None |
960 |
+ if "vartree" in trees[myroot]: |
961 |
+ vardb = trees[myroot]["vartree"].dbapi |
962 |
+ if use_binaries: |
963 |
+ mydbapi = trees[myroot]["bintree"].dbapi |
964 |
+ else: |
965 |
+ mydbapi = trees[myroot]["porttree"].dbapi |
966 |
+ |
967 |
+ # Sort the deps into installed, not installed but already |
968 |
+ # in the graph and other, not installed and not in the graph |
969 |
+ # and other, with values of [[required_atom], availablility] |
970 |
+ for x, satisfied in zip(deps, satisfieds): |
971 |
+ if isinstance(x, list): |
972 |
+ atoms = dep_zapdeps(x, satisfied, myroot, |
973 |
+ use_binaries=use_binaries, trees=trees) |
974 |
+ else: |
975 |
+ atoms = [x] |
976 |
+ if vardb is None: |
977 |
+ # When called by repoman, we can simply return the first choice |
978 |
+ # because dep_eval() handles preference selection. |
979 |
+ return atoms |
980 |
+ |
981 |
+ all_available = True |
982 |
+ all_use_satisfied = True |
983 |
+ slot_map = {} |
984 |
+ cp_map = {} |
985 |
+ for atom in atoms: |
986 |
+ if atom.blocker: |
987 |
+ continue |
988 |
+ # Ignore USE dependencies here since we don't want USE |
989 |
+ # settings to adversely affect || preference evaluation. |
990 |
+ avail_pkg = mydbapi.match(atom.without_use) |
991 |
+ if avail_pkg: |
992 |
+ avail_pkg = avail_pkg[-1] # highest (ascending order) |
993 |
+ avail_slot = Atom("%s:%s" % (atom.cp, |
994 |
+ mydbapi.aux_get(avail_pkg, ["SLOT"])[0])) |
995 |
+ if not avail_pkg: |
996 |
+ all_available = False |
997 |
+ all_use_satisfied = False |
998 |
+ break |
999 |
+ |
1000 |
+ if atom.use: |
1001 |
+ avail_pkg_use = mydbapi.match(atom) |
1002 |
+ if not avail_pkg_use: |
1003 |
+ all_use_satisfied = False |
1004 |
+ else: |
1005 |
+ # highest (ascending order) |
1006 |
+ avail_pkg_use = avail_pkg_use[-1] |
1007 |
+ if avail_pkg_use != avail_pkg: |
1008 |
+ avail_pkg = avail_pkg_use |
1009 |
+ avail_slot = Atom("%s:%s" % (atom.cp, |
1010 |
+ mydbapi.aux_get(avail_pkg, ["SLOT"])[0])) |
1011 |
+ |
1012 |
+ slot_map[avail_slot] = avail_pkg |
1013 |
+ pkg_cp = cpv_getkey(avail_pkg) |
1014 |
+ highest_cpv = cp_map.get(pkg_cp) |
1015 |
+ if highest_cpv is None or \ |
1016 |
+ pkgcmp(catpkgsplit(avail_pkg)[1:], |
1017 |
+ catpkgsplit(highest_cpv)[1:]) > 0: |
1018 |
+ cp_map[pkg_cp] = avail_pkg |
1019 |
+ |
1020 |
+ this_choice = (atoms, slot_map, cp_map, all_available) |
1021 |
+ if all_available: |
1022 |
+ # The "all installed" criterion is not version or slot specific. |
1023 |
+ # If any version of a package is already in the graph then we |
1024 |
+ # assume that it is preferred over other possible packages choices. |
1025 |
+ all_installed = True |
1026 |
+ for atom in set(Atom(atom.cp) for atom in atoms \ |
1027 |
+ if not atom.blocker): |
1028 |
+ # New-style virtuals have zero cost to install. |
1029 |
+ if not vardb.match(atom) and not atom.startswith("virtual/"): |
1030 |
+ all_installed = False |
1031 |
+ break |
1032 |
+ all_installed_slots = False |
1033 |
+ if all_installed: |
1034 |
+ all_installed_slots = True |
1035 |
+ for slot_atom in slot_map: |
1036 |
+ # New-style virtuals have zero cost to install. |
1037 |
+ if not vardb.match(slot_atom) and \ |
1038 |
+ not slot_atom.startswith("virtual/"): |
1039 |
+ all_installed_slots = False |
1040 |
+ break |
1041 |
+ if graph_db is None: |
1042 |
+ if all_use_satisfied: |
1043 |
+ if all_installed: |
1044 |
+ if all_installed_slots: |
1045 |
+ preferred_installed.append(this_choice) |
1046 |
+ else: |
1047 |
+ preferred_any_slot.append(this_choice) |
1048 |
+ else: |
1049 |
+ preferred_non_installed.append(this_choice) |
1050 |
+ else: |
1051 |
+ if all_installed_slots: |
1052 |
+ unsat_use_installed.append(this_choice) |
1053 |
+ else: |
1054 |
+ unsat_use_non_installed.append(this_choice) |
1055 |
+ else: |
1056 |
+ all_in_graph = True |
1057 |
+ for slot_atom in slot_map: |
1058 |
+ # New-style virtuals have zero cost to install. |
1059 |
+ if not graph_db.match(slot_atom) and \ |
1060 |
+ not slot_atom.startswith("virtual/"): |
1061 |
+ all_in_graph = False |
1062 |
+ break |
1063 |
+ circular_atom = None |
1064 |
+ if all_in_graph: |
1065 |
+ if parent is None or priority is None: |
1066 |
+ pass |
1067 |
+ elif priority.buildtime: |
1068 |
+ # Check if the atom would result in a direct circular |
1069 |
+ # dependency and try to avoid that if it seems likely |
1070 |
+ # to be unresolvable. This is only relevant for |
1071 |
+ # buildtime deps that aren't already satisfied by an |
1072 |
+ # installed package. |
1073 |
+ cpv_slot_list = [parent] |
1074 |
+ for atom in atoms: |
1075 |
+ if atom.blocker: |
1076 |
+ continue |
1077 |
+ if vardb.match(atom): |
1078 |
+ # If the atom is satisfied by an installed |
1079 |
+ # version then it's not a circular dep. |
1080 |
+ continue |
1081 |
+ if atom.cp != parent.cp: |
1082 |
+ continue |
1083 |
+ if match_from_list(atom, cpv_slot_list): |
1084 |
+ circular_atom = atom |
1085 |
+ break |
1086 |
+ if circular_atom is not None: |
1087 |
+ other.append(this_choice) |
1088 |
+ else: |
1089 |
+ if all_use_satisfied: |
1090 |
+ if all_in_graph: |
1091 |
+ preferred_in_graph.append(this_choice) |
1092 |
+ elif all_installed: |
1093 |
+ if all_installed_slots: |
1094 |
+ preferred_installed.append(this_choice) |
1095 |
+ else: |
1096 |
+ preferred_any_slot.append(this_choice) |
1097 |
+ else: |
1098 |
+ preferred_non_installed.append(this_choice) |
1099 |
+ else: |
1100 |
+ if all_in_graph: |
1101 |
+ unsat_use_in_graph.append(this_choice) |
1102 |
+ elif all_installed_slots: |
1103 |
+ unsat_use_installed.append(this_choice) |
1104 |
+ else: |
1105 |
+ unsat_use_non_installed.append(this_choice) |
1106 |
+ else: |
1107 |
+ other.append(this_choice) |
1108 |
+ |
1109 |
+ # Prefer choices which contain upgrades to higher slots. This helps |
1110 |
+ # for deps such as || ( foo:1 foo:2 ), where we want to prefer the |
1111 |
+ # atom which matches the higher version rather than the atom furthest |
1112 |
+ # to the left. Sorting is done separately for each of choice_bins, so |
1113 |
+ # as not to interfere with the ordering of the bins. Because of the |
1114 |
+ # bin separation, the main function of this code is to allow |
1115 |
+ # --depclean to remove old slots (rather than to pull in new slots). |
1116 |
+ for choices in choice_bins: |
1117 |
+ if len(choices) < 2: |
1118 |
+ continue |
1119 |
+ for choice_1 in choices[1:]: |
1120 |
+ atoms_1, slot_map_1, cp_map_1, all_available_1 = choice_1 |
1121 |
+ cps = set(cp_map_1) |
1122 |
+ for choice_2 in choices: |
1123 |
+ if choice_1 is choice_2: |
1124 |
+ # choice_1 will not be promoted, so move on |
1125 |
+ break |
1126 |
+ atoms_2, slot_map_2, cp_map_2, all_available_2 = choice_2 |
1127 |
+ intersecting_cps = cps.intersection(cp_map_2) |
1128 |
+ if not intersecting_cps: |
1129 |
+ continue |
1130 |
+ has_upgrade = False |
1131 |
+ has_downgrade = False |
1132 |
+ for cp in intersecting_cps: |
1133 |
+ version_1 = cp_map_1[cp] |
1134 |
+ version_2 = cp_map_2[cp] |
1135 |
+ difference = pkgcmp(catpkgsplit(version_1)[1:], |
1136 |
+ catpkgsplit(version_2)[1:]) |
1137 |
+ if difference != 0: |
1138 |
+ if difference > 0: |
1139 |
+ has_upgrade = True |
1140 |
+ else: |
1141 |
+ has_downgrade = True |
1142 |
+ break |
1143 |
+ if has_upgrade and not has_downgrade: |
1144 |
+ # promote choice_1 in front of choice_2 |
1145 |
+ choices.remove(choice_1) |
1146 |
+ index_2 = choices.index(choice_2) |
1147 |
+ choices.insert(index_2, choice_1) |
1148 |
+ break |
1149 |
+ |
1150 |
+ for allow_masked in (False, True): |
1151 |
+ for choices in choice_bins: |
1152 |
+ for atoms, slot_map, cp_map, all_available in choices: |
1153 |
+ if all_available or allow_masked: |
1154 |
+ return atoms |
1155 |
+ |
1156 |
+ assert(False) # This point should not be reachable |
1157 |
+ |
1158 |
+def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None, |
1159 |
+ use_cache=1, use_binaries=0, myroot="/", trees=None): |
1160 |
+ """Takes a depend string and parses the condition.""" |
1161 |
+ edebug = mysettings.get("PORTAGE_DEBUG", None) == "1" |
1162 |
+ #check_config_instance(mysettings) |
1163 |
+ if trees is None: |
1164 |
+ trees = globals()["db"] |
1165 |
+ if use=="yes": |
1166 |
+ if myuse is None: |
1167 |
+ #default behavior |
1168 |
+ myusesplit = mysettings["PORTAGE_USE"].split() |
1169 |
+ else: |
1170 |
+ myusesplit = myuse |
1171 |
+ # We've been given useflags to use. |
1172 |
+ #print "USE FLAGS PASSED IN." |
1173 |
+ #print myuse |
1174 |
+ #if "bindist" in myusesplit: |
1175 |
+ # print "BINDIST is set!" |
1176 |
+ #else: |
1177 |
+ # print "BINDIST NOT set." |
1178 |
+ else: |
1179 |
+ #we are being run by autouse(), don't consult USE vars yet. |
1180 |
+ # WE ALSO CANNOT USE SETTINGS |
1181 |
+ myusesplit=[] |
1182 |
+ |
1183 |
+ #convert parenthesis to sublists |
1184 |
+ try: |
1185 |
+ mysplit = paren_reduce(depstring) |
1186 |
+ except InvalidDependString as e: |
1187 |
+ return [0, str(e)] |
1188 |
+ |
1189 |
+ mymasks = set() |
1190 |
+ useforce = set() |
1191 |
+ useforce.add(mysettings["ARCH"]) |
1192 |
+ if use == "all": |
1193 |
+ # This masking/forcing is only for repoman. In other cases, relevant |
1194 |
+ # masking/forcing should have already been applied via |
1195 |
+ # config.regenerate(). Also, binary or installed packages may have |
1196 |
+ # been built with flags that are now masked, and it would be |
1197 |
+ # inconsistent to mask them now. Additionally, myuse may consist of |
1198 |
+ # flags from a parent package that is being merged to a $ROOT that is |
1199 |
+ # different from the one that mysettings represents. |
1200 |
+ mymasks.update(mysettings.usemask) |
1201 |
+ mymasks.update(mysettings.archlist()) |
1202 |
+ mymasks.discard(mysettings["ARCH"]) |
1203 |
+ useforce.update(mysettings.useforce) |
1204 |
+ useforce.difference_update(mymasks) |
1205 |
+ try: |
1206 |
+ mysplit = use_reduce(mysplit, uselist=myusesplit, |
1207 |
+ masklist=mymasks, matchall=(use=="all"), excludeall=useforce) |
1208 |
+ except InvalidDependString as e: |
1209 |
+ return [0, str(e)] |
1210 |
+ |
1211 |
+ # Do the || conversions |
1212 |
+ mysplit = dep_opconvert(mysplit) |
1213 |
+ |
1214 |
+ if mysplit == []: |
1215 |
+ #dependencies were reduced to nothing |
1216 |
+ return [1,[]] |
1217 |
+ |
1218 |
+ # Recursively expand new-style virtuals so as to |
1219 |
+ # collapse one or more levels of indirection. |
1220 |
+ try: |
1221 |
+ mysplit = _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, |
1222 |
+ use=use, mode=mode, myuse=myuse, |
1223 |
+ use_force=useforce, use_mask=mymasks, use_cache=use_cache, |
1224 |
+ use_binaries=use_binaries, myroot=myroot, trees=trees) |
1225 |
+ except ParseError as e: |
1226 |
+ return [0, str(e)] |
1227 |
+ |
1228 |
+ mysplit2=mysplit[:] |
1229 |
+ mysplit2=dep_wordreduce(mysplit2,mysettings,mydbapi,mode,use_cache=use_cache) |
1230 |
+ if mysplit2 is None: |
1231 |
+ return [0, _("Invalid token")] |
1232 |
+ |
1233 |
+ writemsg("\n\n\n", 1) |
1234 |
+ writemsg("mysplit: %s\n" % (mysplit), 1) |
1235 |
+ writemsg("mysplit2: %s\n" % (mysplit2), 1) |
1236 |
+ |
1237 |
+ try: |
1238 |
+ selected_atoms = dep_zapdeps(mysplit, mysplit2, myroot, |
1239 |
+ use_binaries=use_binaries, trees=trees) |
1240 |
+ except InvalidAtom as e: |
1241 |
+ if portage.dep._dep_check_strict: |
1242 |
+ raise # This shouldn't happen. |
1243 |
+ # dbapi.match() failed due to an invalid atom in |
1244 |
+ # the dependencies of an installed package. |
1245 |
+ return [0, _("Invalid atom: '%s'") % (e,)] |
1246 |
+ |
1247 |
+ return [1, selected_atoms] |
1248 |
+ |
1249 |
+def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1): |
1250 |
+ "Reduces the deplist to ones and zeros" |
1251 |
+ deplist=mydeplist[:] |
1252 |
+ for mypos, token in enumerate(deplist): |
1253 |
+ if isinstance(deplist[mypos], list): |
1254 |
+ #recurse |
1255 |
+ deplist[mypos]=dep_wordreduce(deplist[mypos],mysettings,mydbapi,mode,use_cache=use_cache) |
1256 |
+ elif deplist[mypos]=="||": |
1257 |
+ pass |
1258 |
+ elif token[:1] == "!": |
1259 |
+ deplist[mypos] = False |
1260 |
+ else: |
1261 |
+ mykey = deplist[mypos].cp |
1262 |
+ if mysettings and mykey in mysettings.pprovideddict and \ |
1263 |
+ match_from_list(deplist[mypos], mysettings.pprovideddict[mykey]): |
1264 |
+ deplist[mypos]=True |
1265 |
+ elif mydbapi is None: |
1266 |
+ # Assume nothing is satisfied. This forces dep_zapdeps to |
1267 |
+ # return all of deps the deps that have been selected |
1268 |
+ # (excluding those satisfied by package.provided). |
1269 |
+ deplist[mypos] = False |
1270 |
+ else: |
1271 |
+ if mode: |
1272 |
+ x = mydbapi.xmatch(mode, deplist[mypos]) |
1273 |
+ if mode.startswith("minimum-"): |
1274 |
+ mydep = [] |
1275 |
+ if x: |
1276 |
+ mydep.append(x) |
1277 |
+ else: |
1278 |
+ mydep = x |
1279 |
+ else: |
1280 |
+ mydep=mydbapi.match(deplist[mypos],use_cache=use_cache) |
1281 |
+ if mydep!=None: |
1282 |
+ tmp=(len(mydep)>=1) |
1283 |
+ if deplist[mypos][0]=="!": |
1284 |
+ tmp=False |
1285 |
+ deplist[mypos]=tmp |
1286 |
+ else: |
1287 |
+ #encountered invalid string |
1288 |
+ return None |
1289 |
+ return deplist |
1290 |
|
1291 |
|
1292 |
Property changes on: main/trunk/pym/portage/dep/dep_check.py |
1293 |
___________________________________________________________________ |
1294 |
Added: svn:keywords |
1295 |
+ Id |