Gentoo Archives: gentoo-commits

From: "Fabian Groffen (grobian)" <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r15483 - in main/branches/prefix/pym/portage: . dbapi package/ebuild util
Date: Sat, 27 Feb 2010 19:33:09
Message-Id: E1NlSPB-00017K-AF@stork.gentoo.org
1 Author: grobian
2 Date: 2010-02-27 19:32:48 +0000 (Sat, 27 Feb 2010)
3 New Revision: 15483
4
5 Added:
6 main/branches/prefix/pym/portage/dep/
7 main/branches/prefix/pym/portage/package/ebuild/getmaskingreason.py
8 main/branches/prefix/pym/portage/package/ebuild/getmaskingstatus.py
9 main/branches/prefix/pym/portage/util/movefile.py
10 Removed:
11 main/branches/prefix/pym/portage/dep.py
12 Modified:
13 main/branches/prefix/pym/portage/__init__.py
14 main/branches/prefix/pym/portage/dbapi/__init__.py
15 main/branches/prefix/pym/portage/dbapi/vartree.py
16 Log:
17 Merged from trunk -r15460:15465
18
19 | 15461 | Move dep.py to dep/__init__.py, for splitting into smaller |
20 | zmedico | files. |
21
22 | 15462 | Move portage.dep_check and related functions to |
23 | zmedico | portage.dep.dep_check. |
24
25 | 15463 | Split getmaskingstatus and getmaskingreason info |
26 | zmedico | portage.package.ebuild submodules. |
27
28 | 15464 | Move portage.movefile to portage.util.movefile. |
29 | zmedico | |
30
31 | 15465 | Avoid name collision with dep_expand submodule so epydoc |
32 | zmedico | won't crash. |
33
34
35 Modified: main/branches/prefix/pym/portage/__init__.py
36 ===================================================================
37 --- main/branches/prefix/pym/portage/__init__.py 2010-02-27 19:26:00 UTC (rev 15482)
38 +++ main/branches/prefix/pym/portage/__init__.py 2010-02-27 19:32:48 UTC (rev 15483)
39 @@ -92,6 +92,7 @@
40 'portage.dep:best_match_to_list,dep_getcpv,dep_getkey,' + \
41 'flatten,get_operator,isjustname,isspecific,isvalidatom,' + \
42 'match_from_list,match_to_list',
43 + 'portage.dep.dep_check:dep_check,dep_eval,dep_wordreduce,dep_zapdeps',
44 'portage.eclass_cache',
45 'portage.env.loaders',
46 'portage.exception',
47 @@ -109,6 +110,8 @@
48 'portage.package.ebuild.digestcheck:digestcheck',
49 'portage.package.ebuild.digestgen:digestgen',
50 'portage.package.ebuild.fetch:fetch',
51 + 'portage.package.ebuild.getmaskingreason:getmaskingreason',
52 + 'portage.package.ebuild.getmaskingstatus:getmaskingstatus',
53 'portage.package.ebuild.prepare_build_dirs:prepare_build_dirs',
54 'portage.process',
55 'portage.process:atexit_register,run_exitfuncs',
56 @@ -127,6 +130,7 @@
57 'portage.util.env_update:env_update',
58 'portage.util.ExtractKernelVersion:ExtractKernelVersion',
59 'portage.util.listdir:cacheddir,listdir',
60 + 'portage.util.movefile:movefile',
61 'portage.versions',
62 'portage.versions:best,catpkgsplit,catsplit,cpv_getkey,' + \
63 'cpv_getkey@getCPFromCPV,endversion_keys,' + \
64 @@ -634,223 +638,6 @@
65 raise portage.exception.PortageException(
66 "mv '%s' '%s'" % (src, dest))
67
68 -def movefile(src, dest, newmtime=None, sstat=None, mysettings=None,
69 - hardlink_candidates=None, encoding=_encodings['fs']):
70 - """moves a file from src to dest, preserving all permissions and attributes; mtime will
71 - be preserved even when moving across filesystems. Returns true on success and false on
72 - failure. Move is atomic."""
73 - #print "movefile("+str(src)+","+str(dest)+","+str(newmtime)+","+str(sstat)+")"
74 -
75 - if mysettings is None:
76 - global settings
77 - mysettings = settings
78 -
79 - selinux_enabled = mysettings.selinux_enabled()
80 - if selinux_enabled:
81 - selinux = _unicode_module_wrapper(_selinux, encoding=encoding)
82 -
83 - lchown = _unicode_func_wrapper(data.lchown, encoding=encoding)
84 - os = _unicode_module_wrapper(_os,
85 - encoding=encoding, overrides=_os_overrides)
86 - shutil = _unicode_module_wrapper(_shutil, encoding=encoding)
87 -
88 - try:
89 - if not sstat:
90 - sstat=os.lstat(src)
91 -
92 - except SystemExit as e:
93 - raise
94 - except Exception as e:
95 - print(_("!!! Stating source file failed... movefile()"))
96 - print("!!!",e)
97 - return None
98 -
99 - destexists=1
100 - try:
101 - dstat=os.lstat(dest)
102 - except (OSError, IOError):
103 - dstat=os.lstat(os.path.dirname(dest))
104 - destexists=0
105 -
106 - if bsd_chflags:
107 - if destexists and dstat.st_flags != 0:
108 - bsd_chflags.lchflags(dest, 0)
109 - # Use normal stat/chflags for the parent since we want to
110 - # follow any symlinks to the real parent directory.
111 - pflags = os.stat(os.path.dirname(dest)).st_flags
112 - if pflags != 0:
113 - bsd_chflags.chflags(os.path.dirname(dest), 0)
114 -
115 - if destexists:
116 - if stat.S_ISLNK(dstat[stat.ST_MODE]):
117 - try:
118 - os.unlink(dest)
119 - destexists=0
120 - except SystemExit as e:
121 - raise
122 - except Exception as e:
123 - pass
124 -
125 - if stat.S_ISLNK(sstat[stat.ST_MODE]):
126 - try:
127 - target=os.readlink(src)
128 - if mysettings and mysettings["D"]:
129 - if target.find(mysettings["D"])==0:
130 - target=target[len(mysettings["D"]):]
131 - if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
132 - os.unlink(dest)
133 - if selinux_enabled:
134 - selinux.symlink(target, dest, src)
135 - else:
136 - os.symlink(target,dest)
137 - lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
138 - # utime() only works on the target of a symlink, so it's not
139 - # possible to perserve mtime on symlinks.
140 - return os.lstat(dest)[stat.ST_MTIME]
141 - except SystemExit as e:
142 - raise
143 - except Exception as e:
144 - print(_("!!! failed to properly create symlink:"))
145 - print("!!!",dest,"->",target)
146 - print("!!!",e)
147 - return None
148 -
149 - hardlinked = False
150 - # Since identical files might be merged to multiple filesystems,
151 - # so os.link() calls might fail for some paths, so try them all.
152 - # For atomic replacement, first create the link as a temp file
153 - # and them use os.rename() to replace the destination.
154 - if hardlink_candidates:
155 - head, tail = os.path.split(dest)
156 - hardlink_tmp = os.path.join(head, ".%s._portage_merge_.%s" % \
157 - (tail, os.getpid()))
158 - try:
159 - os.unlink(hardlink_tmp)
160 - except OSError as e:
161 - if e.errno != errno.ENOENT:
162 - writemsg(_("!!! Failed to remove hardlink temp file: %s\n") % \
163 - (hardlink_tmp,), noiselevel=-1)
164 - writemsg("!!! %s\n" % (e,), noiselevel=-1)
165 - return None
166 - del e
167 - for hardlink_src in hardlink_candidates:
168 - try:
169 - os.link(hardlink_src, hardlink_tmp)
170 - except OSError:
171 - continue
172 - else:
173 - try:
174 - os.rename(hardlink_tmp, dest)
175 - except OSError as e:
176 - writemsg(_("!!! Failed to rename %s to %s\n") % \
177 - (hardlink_tmp, dest), noiselevel=-1)
178 - writemsg("!!! %s\n" % (e,), noiselevel=-1)
179 - return None
180 - hardlinked = True
181 - break
182 -
183 - renamefailed=1
184 - if hardlinked:
185 - renamefailed = False
186 - if not hardlinked and (selinux_enabled or sstat.st_dev == dstat.st_dev):
187 - try:
188 - if selinux_enabled:
189 - ret = selinux.rename(src, dest)
190 - else:
191 - ret=os.rename(src,dest)
192 - renamefailed=0
193 - except OSError as e:
194 - if e.errno != errno.EXDEV:
195 - # Some random error.
196 - print(_("!!! Failed to move %(src)s to %(dest)s") % {"src": src, "dest": dest})
197 - print("!!!",e)
198 - return None
199 - # Invalid cross-device-link 'bind' mounted or actually Cross-Device
200 - if renamefailed:
201 - didcopy=0
202 - if stat.S_ISREG(sstat[stat.ST_MODE]):
203 - try: # For safety copy then move it over.
204 - if selinux_enabled:
205 - selinux.copyfile(src, dest + "#new")
206 - selinux.rename(dest + "#new", dest)
207 - else:
208 - shutil.copyfile(src,dest+"#new")
209 - os.rename(dest+"#new",dest)
210 - didcopy=1
211 - except SystemExit as e:
212 - raise
213 - except Exception as e:
214 - print(_('!!! copy %(src)s -> %(dest)s failed.') % {"src": src, "dest": dest})
215 - print("!!!",e)
216 - return None
217 - else:
218 - #we don't yet handle special, so we need to fall back to /bin/mv
219 - a = process.spawn([MOVE_BINARY, '-f', src, dest], env=os.environ)
220 - if a != os.EX_OK:
221 - writemsg(_("!!! Failed to move special file:\n"), noiselevel=-1)
222 - writemsg(_("!!! '%(src)s' to '%(dest)s'\n") % \
223 - {"src": _unicode_decode(src, encoding=encoding),
224 - "dest": _unicode_decode(dest, encoding=encoding)}, noiselevel=-1)
225 - writemsg("!!! %s\n" % a, noiselevel=-1)
226 - return None # failure
227 - try:
228 - if didcopy:
229 - if stat.S_ISLNK(sstat[stat.ST_MODE]):
230 - lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
231 - else:
232 - os.chown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
233 - os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
234 - os.unlink(src)
235 - except SystemExit as e:
236 - raise
237 - except Exception as e:
238 - print(_("!!! Failed to chown/chmod/unlink in movefile()"))
239 - print("!!!",dest)
240 - print("!!!",e)
241 - return None
242 -
243 - # Always use stat_obj[stat.ST_MTIME] for the integral timestamp which
244 - # is returned, since the stat_obj.st_mtime float attribute rounds *up*
245 - # if the nanosecond part of the timestamp is 999999881 ns or greater.
246 - try:
247 - if hardlinked:
248 - newmtime = os.stat(dest)[stat.ST_MTIME]
249 - else:
250 - # Note: It is not possible to preserve nanosecond precision
251 - # (supported in POSIX.1-2008 via utimensat) with the IEEE 754
252 - # double precision float which only has a 53 bit significand.
253 - if newmtime is not None:
254 - os.utime(dest, (newmtime, newmtime))
255 - else:
256 - newmtime = sstat[stat.ST_MTIME]
257 - if renamefailed:
258 - # If rename succeeded then timestamps are automatically
259 - # preserved with complete precision because the source
260 - # and destination inode are the same. Otherwise, round
261 - # down to the nearest whole second since python's float
262 - # st_mtime cannot be used to preserve the st_mtim.tv_nsec
263 - # field with complete precision. Note that we have to use
264 - # stat_obj[stat.ST_MTIME] here because the float
265 - # stat_obj.st_mtime rounds *up* sometimes.
266 - os.utime(dest, (newmtime, newmtime))
267 - except OSError:
268 - # The utime can fail here with EPERM even though the move succeeded.
269 - # Instead of failing, use stat to return the mtime if possible.
270 - try:
271 - newmtime = os.stat(dest)[stat.ST_MTIME]
272 - except OSError as e:
273 - writemsg(_("!!! Failed to stat in movefile()\n"), noiselevel=-1)
274 - writemsg("!!! %s\n" % dest, noiselevel=-1)
275 - writemsg("!!! %s\n" % str(e), noiselevel=-1)
276 - return None
277 -
278 - if bsd_chflags:
279 - # Restore the flags we saved before moving
280 - if pflags:
281 - bsd_chflags.chflags(os.path.dirname(dest), pflags)
282 -
283 - return newmtime
284 -
285 def merge(mycat, mypkg, pkgloc, infloc, myroot, mysettings, myebuild=None,
286 mytree=None, mydbapi=None, vartree=None, prev_mtimes=None, blockers=None,
287 scheduler=None):
288 @@ -911,835 +698,6 @@
289 newsplit.append(x)
290 return newsplit
291
292 -def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
293 - trees=None, use_mask=None, use_force=None, **kwargs):
294 - """
295 - In order to solve bug #141118, recursively expand new-style virtuals so
296 - as to collapse one or more levels of indirection, generating an expanded
297 - search space. In dep_zapdeps, new-style virtuals will be assigned
298 - zero cost regardless of whether or not they are currently installed. Virtual
299 - blockers are supported but only when the virtual expands to a single
300 - atom because it wouldn't necessarily make sense to block all the components
301 - of a compound virtual. When more than one new-style virtual is matched,
302 - the matches are sorted from highest to lowest versions and the atom is
303 - expanded to || ( highest match ... lowest match )."""
304 - newsplit = []
305 - mytrees = trees[myroot]
306 - portdb = mytrees["porttree"].dbapi
307 - atom_graph = mytrees.get("atom_graph")
308 - parent = mytrees.get("parent")
309 - virt_parent = mytrees.get("virt_parent")
310 - graph_parent = None
311 - eapi = None
312 - if parent is not None:
313 - if virt_parent is not None:
314 - graph_parent = virt_parent
315 - eapi = virt_parent[0].metadata['EAPI']
316 - else:
317 - graph_parent = parent
318 - eapi = parent.metadata["EAPI"]
319 - repoman = not mysettings.local_config
320 - if kwargs["use_binaries"]:
321 - portdb = trees[myroot]["bintree"].dbapi
322 - myvirtuals = mysettings.getvirtuals()
323 - pprovideddict = mysettings.pprovideddict
324 - myuse = kwargs["myuse"]
325 - for x in mysplit:
326 - if x == "||":
327 - newsplit.append(x)
328 - continue
329 - elif isinstance(x, list):
330 - newsplit.append(_expand_new_virtuals(x, edebug, mydbapi,
331 - mysettings, myroot=myroot, trees=trees, use_mask=use_mask,
332 - use_force=use_force, **kwargs))
333 - continue
334 -
335 - if not isinstance(x, portage.dep.Atom):
336 - try:
337 - x = portage.dep.Atom(x)
338 - except portage.exception.InvalidAtom:
339 - if portage.dep._dep_check_strict:
340 - raise portage.exception.ParseError(
341 - _("invalid atom: '%s'") % x)
342 - else:
343 - # Only real Atom instances are allowed past this point.
344 - continue
345 - else:
346 - if x.blocker and x.blocker.overlap.forbid and \
347 - eapi in ("0", "1") and portage.dep._dep_check_strict:
348 - raise portage.exception.ParseError(
349 - _("invalid atom: '%s'") % (x,))
350 - if x.use and eapi in ("0", "1") and \
351 - portage.dep._dep_check_strict:
352 - raise portage.exception.ParseError(
353 - _("invalid atom: '%s'") % (x,))
354 -
355 - if repoman and x.use and x.use.conditional:
356 - evaluated_atom = portage.dep.remove_slot(x)
357 - if x.slot:
358 - evaluated_atom += ":%s" % x.slot
359 - evaluated_atom += str(x.use._eval_qa_conditionals(
360 - use_mask, use_force))
361 - x = portage.dep.Atom(evaluated_atom)
362 -
363 - if not repoman and \
364 - myuse is not None and isinstance(x, portage.dep.Atom) and x.use:
365 - if x.use.conditional:
366 - x = x.evaluate_conditionals(myuse)
367 -
368 - mykey = x.cp
369 - if not mykey.startswith("virtual/"):
370 - newsplit.append(x)
371 - if atom_graph is not None:
372 - atom_graph.add(x, graph_parent)
373 - continue
374 - mychoices = myvirtuals.get(mykey, [])
375 - if x.blocker:
376 - # Virtual blockers are no longer expanded here since
377 - # the un-expanded virtual atom is more useful for
378 - # maintaining a cache of blocker atoms.
379 - newsplit.append(x)
380 - if atom_graph is not None:
381 - atom_graph.add(x, graph_parent)
382 - continue
383 -
384 - if repoman or not hasattr(portdb, 'match_pkgs'):
385 - if portdb.cp_list(x.cp):
386 - newsplit.append(x)
387 - else:
388 - # TODO: Add PROVIDE check for repoman.
389 - a = []
390 - for y in mychoices:
391 - a.append(dep.Atom(x.replace(x.cp, y.cp, 1)))
392 - if not a:
393 - newsplit.append(x)
394 - elif len(a) == 1:
395 - newsplit.append(a[0])
396 - else:
397 - newsplit.append(['||'] + a)
398 - continue
399 -
400 - pkgs = []
401 - # Ignore USE deps here, since otherwise we might not
402 - # get any matches. Choices with correct USE settings
403 - # will be preferred in dep_zapdeps().
404 - matches = portdb.match_pkgs(x.without_use)
405 - # Use descending order to prefer higher versions.
406 - matches.reverse()
407 - for pkg in matches:
408 - # only use new-style matches
409 - if pkg.cp.startswith("virtual/"):
410 - pkgs.append(pkg)
411 - if not (pkgs or mychoices):
412 - # This one couldn't be expanded as a new-style virtual. Old-style
413 - # virtuals have already been expanded by dep_virtual, so this one
414 - # is unavailable and dep_zapdeps will identify it as such. The
415 - # atom is not eliminated here since it may still represent a
416 - # dependency that needs to be satisfied.
417 - newsplit.append(x)
418 - if atom_graph is not None:
419 - atom_graph.add(x, graph_parent)
420 - continue
421 -
422 - a = []
423 - for pkg in pkgs:
424 - virt_atom = '=' + pkg.cpv
425 - if x.use:
426 - virt_atom += str(x.use)
427 - virt_atom = dep.Atom(virt_atom)
428 - # According to GLEP 37, RDEPEND is the only dependency
429 - # type that is valid for new-style virtuals. Repoman
430 - # should enforce this.
431 - depstring = pkg.metadata['RDEPEND']
432 - pkg_kwargs = kwargs.copy()
433 - pkg_kwargs["myuse"] = pkg.use.enabled
434 - if edebug:
435 - util.writemsg_level(_("Virtual Parent: %s\n") \
436 - % (pkg,), noiselevel=-1, level=logging.DEBUG)
437 - util.writemsg_level(_("Virtual Depstring: %s\n") \
438 - % (depstring,), noiselevel=-1, level=logging.DEBUG)
439 -
440 - # Set EAPI used for validation in dep_check() recursion.
441 - mytrees["virt_parent"] = (pkg, virt_atom)
442 -
443 - try:
444 - mycheck = dep_check(depstring, mydbapi, mysettings,
445 - myroot=myroot, trees=trees, **pkg_kwargs)
446 - finally:
447 - # Restore previous EAPI after recursion.
448 - if virt_parent is not None:
449 - mytrees["virt_parent"] = virt_parent
450 - else:
451 - del mytrees["virt_parent"]
452 -
453 - if not mycheck[0]:
454 - raise portage.exception.ParseError(
455 - "%s: %s '%s'" % (y[0], mycheck[1], depstring))
456 -
457 - # pull in the new-style virtual
458 - mycheck[1].append(virt_atom)
459 - a.append(mycheck[1])
460 - if atom_graph is not None:
461 - atom_graph.add(virt_atom, graph_parent)
462 - # Plain old-style virtuals. New-style virtuals are preferred.
463 - if not pkgs:
464 - for y in mychoices:
465 - new_atom = dep.Atom(x.replace(x.cp, y.cp, 1))
466 - matches = portdb.match(new_atom)
467 - # portdb is an instance of depgraph._dep_check_composite_db, so
468 - # USE conditionals are already evaluated.
469 - if matches and mykey in \
470 - portdb.aux_get(matches[-1], ['PROVIDE'])[0].split():
471 - a.append(new_atom)
472 - if atom_graph is not None:
473 - atom_graph.add(new_atom, graph_parent)
474 -
475 - if not a and mychoices:
476 - # Check for a virtual package.provided match.
477 - for y in mychoices:
478 - new_atom = dep.Atom(x.replace(x.cp, y.cp, 1))
479 - if match_from_list(new_atom,
480 - pprovideddict.get(new_atom.cp, [])):
481 - a.append(new_atom)
482 - if atom_graph is not None:
483 - atom_graph.add(new_atom, graph_parent)
484 -
485 - if not a:
486 - newsplit.append(x)
487 - if atom_graph is not None:
488 - atom_graph.add(x, graph_parent)
489 - elif len(a) == 1:
490 - newsplit.append(a[0])
491 - else:
492 - newsplit.append(['||'] + a)
493 -
494 - return newsplit
495 -
496 -def dep_eval(deplist):
497 - if not deplist:
498 - return 1
499 - if deplist[0]=="||":
500 - #or list; we just need one "1"
501 - for x in deplist[1:]:
502 - if isinstance(x, list):
503 - if dep_eval(x)==1:
504 - return 1
505 - elif x==1:
506 - return 1
507 - #XXX: unless there's no available atoms in the list
508 - #in which case we need to assume that everything is
509 - #okay as some ebuilds are relying on an old bug.
510 - if len(deplist) == 1:
511 - return 1
512 - return 0
513 - else:
514 - for x in deplist:
515 - if isinstance(x, list):
516 - if dep_eval(x)==0:
517 - return 0
518 - elif x==0 or x==2:
519 - return 0
520 - return 1
521 -
522 -def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
523 - """Takes an unreduced and reduced deplist and removes satisfied dependencies.
524 - Returned deplist contains steps that must be taken to satisfy dependencies."""
525 - if trees is None:
526 - global db
527 - trees = db
528 - writemsg("ZapDeps -- %s\n" % (use_binaries), 2)
529 - if not reduced or unreduced == ["||"] or dep_eval(reduced):
530 - return []
531 -
532 - if unreduced[0] != "||":
533 - unresolved = []
534 - for x, satisfied in zip(unreduced, reduced):
535 - if isinstance(x, list):
536 - unresolved += dep_zapdeps(x, satisfied, myroot,
537 - use_binaries=use_binaries, trees=trees)
538 - elif not satisfied:
539 - unresolved.append(x)
540 - return unresolved
541 -
542 - # We're at a ( || atom ... ) type level and need to make a choice
543 - deps = unreduced[1:]
544 - satisfieds = reduced[1:]
545 -
546 - # Our preference order is for an the first item that:
547 - # a) contains all unmasked packages with the same key as installed packages
548 - # b) contains all unmasked packages
549 - # c) contains masked installed packages
550 - # d) is the first item
551 -
552 - preferred_installed = []
553 - preferred_in_graph = []
554 - preferred_any_slot = []
555 - preferred_non_installed = []
556 - unsat_use_in_graph = []
557 - unsat_use_installed = []
558 - unsat_use_non_installed = []
559 - other = []
560 -
561 - # unsat_use_* must come after preferred_non_installed
562 - # for correct ordering in cases like || ( foo[a] foo[b] ).
563 - choice_bins = (
564 - preferred_in_graph,
565 - preferred_installed,
566 - preferred_any_slot,
567 - preferred_non_installed,
568 - unsat_use_in_graph,
569 - unsat_use_installed,
570 - unsat_use_non_installed,
571 - other,
572 - )
573 -
574 - # Alias the trees we'll be checking availability against
575 - parent = trees[myroot].get("parent")
576 - priority = trees[myroot].get("priority")
577 - graph_db = trees[myroot].get("graph_db")
578 - vardb = None
579 - if "vartree" in trees[myroot]:
580 - vardb = trees[myroot]["vartree"].dbapi
581 - if use_binaries:
582 - mydbapi = trees[myroot]["bintree"].dbapi
583 - else:
584 - mydbapi = trees[myroot]["porttree"].dbapi
585 -
586 - # Sort the deps into installed, not installed but already
587 - # in the graph and other, not installed and not in the graph
588 - # and other, with values of [[required_atom], availablility]
589 - for x, satisfied in zip(deps, satisfieds):
590 - if isinstance(x, list):
591 - atoms = dep_zapdeps(x, satisfied, myroot,
592 - use_binaries=use_binaries, trees=trees)
593 - else:
594 - atoms = [x]
595 - if vardb is None:
596 - # When called by repoman, we can simply return the first choice
597 - # because dep_eval() handles preference selection.
598 - return atoms
599 -
600 - all_available = True
601 - all_use_satisfied = True
602 - slot_map = {}
603 - cp_map = {}
604 - for atom in atoms:
605 - if atom.blocker:
606 - continue
607 - # Ignore USE dependencies here since we don't want USE
608 - # settings to adversely affect || preference evaluation.
609 - avail_pkg = mydbapi.match(atom.without_use)
610 - if avail_pkg:
611 - avail_pkg = avail_pkg[-1] # highest (ascending order)
612 - avail_slot = dep.Atom("%s:%s" % (atom.cp,
613 - mydbapi.aux_get(avail_pkg, ["SLOT"])[0]))
614 - if not avail_pkg:
615 - all_available = False
616 - all_use_satisfied = False
617 - break
618 -
619 - if atom.use:
620 - avail_pkg_use = mydbapi.match(atom)
621 - if not avail_pkg_use:
622 - all_use_satisfied = False
623 - else:
624 - # highest (ascending order)
625 - avail_pkg_use = avail_pkg_use[-1]
626 - if avail_pkg_use != avail_pkg:
627 - avail_pkg = avail_pkg_use
628 - avail_slot = dep.Atom("%s:%s" % (atom.cp,
629 - mydbapi.aux_get(avail_pkg, ["SLOT"])[0]))
630 -
631 - slot_map[avail_slot] = avail_pkg
632 - pkg_cp = cpv_getkey(avail_pkg)
633 - highest_cpv = cp_map.get(pkg_cp)
634 - if highest_cpv is None or \
635 - pkgcmp(catpkgsplit(avail_pkg)[1:],
636 - catpkgsplit(highest_cpv)[1:]) > 0:
637 - cp_map[pkg_cp] = avail_pkg
638 -
639 - this_choice = (atoms, slot_map, cp_map, all_available)
640 - if all_available:
641 - # The "all installed" criterion is not version or slot specific.
642 - # If any version of a package is already in the graph then we
643 - # assume that it is preferred over other possible packages choices.
644 - all_installed = True
645 - for atom in set(dep.Atom(atom.cp) for atom in atoms \
646 - if not atom.blocker):
647 - # New-style virtuals have zero cost to install.
648 - if not vardb.match(atom) and not atom.startswith("virtual/"):
649 - all_installed = False
650 - break
651 - all_installed_slots = False
652 - if all_installed:
653 - all_installed_slots = True
654 - for slot_atom in slot_map:
655 - # New-style virtuals have zero cost to install.
656 - if not vardb.match(slot_atom) and \
657 - not slot_atom.startswith("virtual/"):
658 - all_installed_slots = False
659 - break
660 - if graph_db is None:
661 - if all_use_satisfied:
662 - if all_installed:
663 - if all_installed_slots:
664 - preferred_installed.append(this_choice)
665 - else:
666 - preferred_any_slot.append(this_choice)
667 - else:
668 - preferred_non_installed.append(this_choice)
669 - else:
670 - if all_installed_slots:
671 - unsat_use_installed.append(this_choice)
672 - else:
673 - unsat_use_non_installed.append(this_choice)
674 - else:
675 - all_in_graph = True
676 - for slot_atom in slot_map:
677 - # New-style virtuals have zero cost to install.
678 - if not graph_db.match(slot_atom) and \
679 - not slot_atom.startswith("virtual/"):
680 - all_in_graph = False
681 - break
682 - circular_atom = None
683 - if all_in_graph:
684 - if parent is None or priority is None:
685 - pass
686 - elif priority.buildtime:
687 - # Check if the atom would result in a direct circular
688 - # dependency and try to avoid that if it seems likely
689 - # to be unresolvable. This is only relevant for
690 - # buildtime deps that aren't already satisfied by an
691 - # installed package.
692 - cpv_slot_list = [parent]
693 - for atom in atoms:
694 - if atom.blocker:
695 - continue
696 - if vardb.match(atom):
697 - # If the atom is satisfied by an installed
698 - # version then it's not a circular dep.
699 - continue
700 - if atom.cp != parent.cp:
701 - continue
702 - if match_from_list(atom, cpv_slot_list):
703 - circular_atom = atom
704 - break
705 - if circular_atom is not None:
706 - other.append(this_choice)
707 - else:
708 - if all_use_satisfied:
709 - if all_in_graph:
710 - preferred_in_graph.append(this_choice)
711 - elif all_installed:
712 - if all_installed_slots:
713 - preferred_installed.append(this_choice)
714 - else:
715 - preferred_any_slot.append(this_choice)
716 - else:
717 - preferred_non_installed.append(this_choice)
718 - else:
719 - if all_in_graph:
720 - unsat_use_in_graph.append(this_choice)
721 - elif all_installed_slots:
722 - unsat_use_installed.append(this_choice)
723 - else:
724 - unsat_use_non_installed.append(this_choice)
725 - else:
726 - other.append(this_choice)
727 -
728 - # Prefer choices which contain upgrades to higher slots. This helps
729 - # for deps such as || ( foo:1 foo:2 ), where we want to prefer the
730 - # atom which matches the higher version rather than the atom furthest
731 - # to the left. Sorting is done separately for each of choice_bins, so
732 - # as not to interfere with the ordering of the bins. Because of the
733 - # bin separation, the main function of this code is to allow
734 - # --depclean to remove old slots (rather than to pull in new slots).
735 - for choices in choice_bins:
736 - if len(choices) < 2:
737 - continue
738 - for choice_1 in choices[1:]:
739 - atoms_1, slot_map_1, cp_map_1, all_available_1 = choice_1
740 - cps = set(cp_map_1)
741 - for choice_2 in choices:
742 - if choice_1 is choice_2:
743 - # choice_1 will not be promoted, so move on
744 - break
745 - atoms_2, slot_map_2, cp_map_2, all_available_2 = choice_2
746 - intersecting_cps = cps.intersection(cp_map_2)
747 - if not intersecting_cps:
748 - continue
749 - has_upgrade = False
750 - has_downgrade = False
751 - for cp in intersecting_cps:
752 - version_1 = cp_map_1[cp]
753 - version_2 = cp_map_2[cp]
754 - difference = pkgcmp(catpkgsplit(version_1)[1:],
755 - catpkgsplit(version_2)[1:])
756 - if difference != 0:
757 - if difference > 0:
758 - has_upgrade = True
759 - else:
760 - has_downgrade = True
761 - break
762 - if has_upgrade and not has_downgrade:
763 - # promote choice_1 in front of choice_2
764 - choices.remove(choice_1)
765 - index_2 = choices.index(choice_2)
766 - choices.insert(index_2, choice_1)
767 - break
768 -
769 - for allow_masked in (False, True):
770 - for choices in choice_bins:
771 - for atoms, slot_map, cp_map, all_available in choices:
772 - if all_available or allow_masked:
773 - return atoms
774 -
775 - assert(False) # This point should not be reachable
776 -
777 -def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
778 - use_cache=1, use_binaries=0, myroot="/", trees=None):
779 - """Takes a depend string and parses the condition."""
780 - edebug = mysettings.get("PORTAGE_DEBUG", None) == "1"
781 - #check_config_instance(mysettings)
782 - if trees is None:
783 - trees = globals()["db"]
784 - if use=="yes":
785 - if myuse is None:
786 - #default behavior
787 - myusesplit = mysettings["PORTAGE_USE"].split()
788 - else:
789 - myusesplit = myuse
790 - # We've been given useflags to use.
791 - #print "USE FLAGS PASSED IN."
792 - #print myuse
793 - #if "bindist" in myusesplit:
794 - # print "BINDIST is set!"
795 - #else:
796 - # print "BINDIST NOT set."
797 - else:
798 - #we are being run by autouse(), don't consult USE vars yet.
799 - # WE ALSO CANNOT USE SETTINGS
800 - myusesplit=[]
801 -
802 - #convert parenthesis to sublists
803 - try:
804 - mysplit = portage.dep.paren_reduce(depstring)
805 - except portage.exception.InvalidDependString as e:
806 - return [0, str(e)]
807 -
808 - mymasks = set()
809 - useforce = set()
810 - useforce.add(mysettings["ARCH"])
811 - if use == "all":
812 - # This masking/forcing is only for repoman. In other cases, relevant
813 - # masking/forcing should have already been applied via
814 - # config.regenerate(). Also, binary or installed packages may have
815 - # been built with flags that are now masked, and it would be
816 - # inconsistent to mask them now. Additionally, myuse may consist of
817 - # flags from a parent package that is being merged to a $ROOT that is
818 - # different from the one that mysettings represents.
819 - mymasks.update(mysettings.usemask)
820 - mymasks.update(mysettings.archlist())
821 - mymasks.discard(mysettings["ARCH"])
822 - useforce.update(mysettings.useforce)
823 - useforce.difference_update(mymasks)
824 - try:
825 - mysplit = portage.dep.use_reduce(mysplit, uselist=myusesplit,
826 - masklist=mymasks, matchall=(use=="all"), excludeall=useforce)
827 - except portage.exception.InvalidDependString as e:
828 - return [0, str(e)]
829 -
830 - # Do the || conversions
831 - mysplit=portage.dep.dep_opconvert(mysplit)
832 -
833 - if mysplit == []:
834 - #dependencies were reduced to nothing
835 - return [1,[]]
836 -
837 - # Recursively expand new-style virtuals so as to
838 - # collapse one or more levels of indirection.
839 - try:
840 - mysplit = _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings,
841 - use=use, mode=mode, myuse=myuse,
842 - use_force=useforce, use_mask=mymasks, use_cache=use_cache,
843 - use_binaries=use_binaries, myroot=myroot, trees=trees)
844 - except portage.exception.ParseError as e:
845 - return [0, str(e)]
846 -
847 - mysplit2=mysplit[:]
848 - mysplit2=dep_wordreduce(mysplit2,mysettings,mydbapi,mode,use_cache=use_cache)
849 - if mysplit2 is None:
850 - return [0, _("Invalid token")]
851 -
852 - writemsg("\n\n\n", 1)
853 - writemsg("mysplit: %s\n" % (mysplit), 1)
854 - writemsg("mysplit2: %s\n" % (mysplit2), 1)
855 -
856 - try:
857 - selected_atoms = dep_zapdeps(mysplit, mysplit2, myroot,
858 - use_binaries=use_binaries, trees=trees)
859 - except portage.exception.InvalidAtom as e:
860 - if portage.dep._dep_check_strict:
861 - raise # This shouldn't happen.
862 - # dbapi.match() failed due to an invalid atom in
863 - # the dependencies of an installed package.
864 - return [0, _("Invalid atom: '%s'") % (e,)]
865 -
866 - return [1, selected_atoms]
867 -
868 -def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1):
869 - "Reduces the deplist to ones and zeros"
870 - deplist=mydeplist[:]
871 - for mypos, token in enumerate(deplist):
872 - if isinstance(deplist[mypos], list):
873 - #recurse
874 - deplist[mypos]=dep_wordreduce(deplist[mypos],mysettings,mydbapi,mode,use_cache=use_cache)
875 - elif deplist[mypos]=="||":
876 - pass
877 - elif token[:1] == "!":
878 - deplist[mypos] = False
879 - else:
880 - mykey = deplist[mypos].cp
881 - if mysettings and mykey in mysettings.pprovideddict and \
882 - match_from_list(deplist[mypos], mysettings.pprovideddict[mykey]):
883 - deplist[mypos]=True
884 - elif mydbapi is None:
885 - # Assume nothing is satisfied. This forces dep_zapdeps to
886 - # return all of deps the deps that have been selected
887 - # (excluding those satisfied by package.provided).
888 - deplist[mypos] = False
889 - else:
890 - if mode:
891 - x = mydbapi.xmatch(mode, deplist[mypos])
892 - if mode.startswith("minimum-"):
893 - mydep = []
894 - if x:
895 - mydep.append(x)
896 - else:
897 - mydep = x
898 - else:
899 - mydep=mydbapi.match(deplist[mypos],use_cache=use_cache)
900 - if mydep!=None:
901 - tmp=(len(mydep)>=1)
902 - if deplist[mypos][0]=="!":
903 - tmp=False
904 - deplist[mypos]=tmp
905 - else:
906 - #encountered invalid string
907 - return None
908 - return deplist
909 -
910 -def getmaskingreason(mycpv, metadata=None, settings=None, portdb=None, return_location=False):
911 - from portage.util import grablines
912 - if settings is None:
913 - settings = globals()["settings"]
914 - if portdb is None:
915 - portdb = globals()["portdb"]
916 - mysplit = catpkgsplit(mycpv)
917 - if not mysplit:
918 - raise ValueError(_("invalid CPV: %s") % mycpv)
919 - if metadata is None:
920 - db_keys = list(portdb._aux_cache_keys)
921 - try:
922 - metadata = dict(zip(db_keys, portdb.aux_get(mycpv, db_keys)))
923 - except KeyError:
924 - if not portdb.cpv_exists(mycpv):
925 - raise
926 - if metadata is None:
927 - # Can't access SLOT due to corruption.
928 - cpv_slot_list = [mycpv]
929 - else:
930 - cpv_slot_list = ["%s:%s" % (mycpv, metadata["SLOT"])]
931 - mycp=mysplit[0]+"/"+mysplit[1]
932 -
933 - # XXX- This is a temporary duplicate of code from the config constructor.
934 - locations = [os.path.join(settings["PORTDIR"], "profiles")]
935 - locations.extend(settings.profiles)
936 - for ov in settings["PORTDIR_OVERLAY"].split():
937 - profdir = os.path.join(normalize_path(ov), "profiles")
938 - if os.path.isdir(profdir):
939 - locations.append(profdir)
940 - locations.append(os.path.join(settings["PORTAGE_CONFIGROOT"],
941 - USER_CONFIG_PATH))
942 - locations.reverse()
943 - pmasklists = [(x, grablines(os.path.join(x, "package.mask"), recursive=1)) for x in locations]
944 -
945 - if mycp in settings.pmaskdict:
946 - for x in settings.pmaskdict[mycp]:
947 - if match_from_list(x, cpv_slot_list):
948 - for pmask in pmasklists:
949 - comment = ""
950 - comment_valid = -1
951 - pmask_filename = os.path.join(pmask[0], "package.mask")
952 - for i in range(len(pmask[1])):
953 - l = pmask[1][i].strip()
954 - if l == "":
955 - comment = ""
956 - comment_valid = -1
957 - elif l[0] == "#":
958 - comment += (l+"\n")
959 - comment_valid = i + 1
960 - elif l == x:
961 - if comment_valid != i:
962 - comment = ""
963 - if return_location:
964 - return (comment, pmask_filename)
965 - else:
966 - return comment
967 - elif comment_valid != -1:
968 - # Apparently this comment applies to muliple masks, so
969 - # it remains valid until a blank line is encountered.
970 - comment_valid += 1
971 - if return_location:
972 - return (None, None)
973 - else:
974 - return None
975 -
976 -def getmaskingstatus(mycpv, settings=None, portdb=None):
977 - if settings is None:
978 - settings = config(clone=globals()["settings"])
979 - if portdb is None:
980 - portdb = globals()["portdb"]
981 -
982 - metadata = None
983 - installed = False
984 - if not isinstance(mycpv, basestring):
985 - # emerge passed in a Package instance
986 - pkg = mycpv
987 - mycpv = pkg.cpv
988 - metadata = pkg.metadata
989 - installed = pkg.installed
990 -
991 - mysplit = catpkgsplit(mycpv)
992 - if not mysplit:
993 - raise ValueError(_("invalid CPV: %s") % mycpv)
994 - if metadata is None:
995 - db_keys = list(portdb._aux_cache_keys)
996 - try:
997 - metadata = dict(zip(db_keys, portdb.aux_get(mycpv, db_keys)))
998 - except KeyError:
999 - if not portdb.cpv_exists(mycpv):
1000 - raise
1001 - return ["corruption"]
1002 - if "?" in metadata["LICENSE"]:
1003 - settings.setcpv(mycpv, mydb=metadata)
1004 - metadata["USE"] = settings["PORTAGE_USE"]
1005 - else:
1006 - metadata["USE"] = ""
1007 - mycp=mysplit[0]+"/"+mysplit[1]
1008 -
1009 - rValue = []
1010 -
1011 - # profile checking
1012 - if settings._getProfileMaskAtom(mycpv, metadata):
1013 - rValue.append("profile")
1014 -
1015 - # package.mask checking
1016 - if settings._getMaskAtom(mycpv, metadata):
1017 - rValue.append("package.mask")
1018 -
1019 - # keywords checking
1020 - eapi = metadata["EAPI"]
1021 - mygroups = settings._getKeywords(mycpv, metadata)
1022 - licenses = metadata["LICENSE"]
1023 - properties = metadata["PROPERTIES"]
1024 - slot = metadata["SLOT"]
1025 - if eapi.startswith("-"):
1026 - eapi = eapi[1:]
1027 - if not eapi_is_supported(eapi):
1028 - return ["EAPI %s" % eapi]
1029 - elif _eapi_is_deprecated(eapi) and not installed:
1030 - return ["EAPI %s" % eapi]
1031 - egroups = settings.configdict["backupenv"].get(
1032 - "ACCEPT_KEYWORDS", "").split()
1033 - pgroups = settings["ACCEPT_KEYWORDS"].split()
1034 - myarch = settings["ARCH"]
1035 - if pgroups and myarch not in pgroups:
1036 - """For operating systems other than Linux, ARCH is not necessarily a
1037 - valid keyword."""
1038 - myarch = pgroups[0].lstrip("~")
1039 -
1040 - cp = cpv_getkey(mycpv)
1041 - pkgdict = settings.pkeywordsdict.get(cp)
1042 - matches = False
1043 - if pkgdict:
1044 - cpv_slot_list = ["%s:%s" % (mycpv, metadata["SLOT"])]
1045 - for atom, pkgkeywords in pkgdict.items():
1046 - if match_from_list(atom, cpv_slot_list):
1047 - matches = True
1048 - pgroups.extend(pkgkeywords)
1049 - if matches or egroups:
1050 - pgroups.extend(egroups)
1051 - inc_pgroups = set()
1052 - for x in pgroups:
1053 - if x.startswith("-"):
1054 - if x == "-*":
1055 - inc_pgroups.clear()
1056 - else:
1057 - inc_pgroups.discard(x[1:])
1058 - else:
1059 - inc_pgroups.add(x)
1060 - pgroups = inc_pgroups
1061 - del inc_pgroups
1062 -
1063 - kmask = "missing"
1064 -
1065 - if '**' in pgroups:
1066 - kmask = None
1067 - else:
1068 - for keyword in pgroups:
1069 - if keyword in mygroups:
1070 - kmask = None
1071 - break
1072 -
1073 - if kmask:
1074 - fallback = None
1075 - for gp in mygroups:
1076 - if gp=="*":
1077 - kmask=None
1078 - break
1079 - elif gp=="-"+myarch and myarch in pgroups:
1080 - kmask="-"+myarch
1081 - break
1082 - elif gp=="~"+myarch and myarch in pgroups:
1083 - kmask="~"+myarch
1084 - break
1085 -
1086 - try:
1087 - missing_licenses = settings._getMissingLicenses(mycpv, metadata)
1088 - if missing_licenses:
1089 - allowed_tokens = set(["||", "(", ")"])
1090 - allowed_tokens.update(missing_licenses)
1091 - license_split = licenses.split()
1092 - license_split = [x for x in license_split \
1093 - if x in allowed_tokens]
1094 - msg = license_split[:]
1095 - msg.append("license(s)")
1096 - rValue.append(" ".join(msg))
1097 - except portage.exception.InvalidDependString as e:
1098 - rValue.append("LICENSE: "+str(e))
1099 -
1100 - try:
1101 - missing_properties = settings._getMissingProperties(mycpv, metadata)
1102 - if missing_properties:
1103 - allowed_tokens = set(["||", "(", ")"])
1104 - allowed_tokens.update(missing_properties)
1105 - properties_split = properties.split()
1106 - properties_split = [x for x in properties_split \
1107 - if x in allowed_tokens]
1108 - msg = properties_split[:]
1109 - msg.append("properties")
1110 - rValue.append(" ".join(msg))
1111 - except portage.exception.InvalidDependString as e:
1112 - rValue.append("PROPERTIES: "+str(e))
1113 -
1114 - # Only show KEYWORDS masks for installed packages
1115 - # if they're not masked for any other reason.
1116 - if kmask and (not installed or not rValue):
1117 - rValue.append(kmask+" keyword")
1118 -
1119 - return rValue
1120 -
1121 auxdbkeys = (
1122 'DEPEND', 'RDEPEND', 'SLOT', 'SRC_URI',
1123 'RESTRICT', 'HOMEPAGE', 'LICENSE', 'DESCRIPTION',
1124
1125 Modified: main/branches/prefix/pym/portage/dbapi/__init__.py
1126 ===================================================================
1127 --- main/branches/prefix/pym/portage/dbapi/__init__.py 2010-02-27 19:26:00 UTC (rev 15482)
1128 +++ main/branches/prefix/pym/portage/dbapi/__init__.py 2010-02-27 19:32:48 UTC (rev 15483)
1129 @@ -8,7 +8,7 @@
1130
1131 import portage
1132 portage.proxy.lazyimport.lazyimport(globals(),
1133 - 'portage.dbapi.dep_expand:dep_expand',
1134 + 'portage.dbapi.dep_expand:_dep_expand',
1135 'portage.dep:match_from_list',
1136 'portage.locks:unlockfile',
1137 'portage.output:colorize',
1138 @@ -122,7 +122,7 @@
1139 Returns:
1140 a list of packages that match origdep
1141 """
1142 - mydep = dep_expand(origdep, mydb=self, settings=self.settings)
1143 + mydep = _dep_expand(origdep, mydb=self, settings=self.settings)
1144 return list(self._iter_match(mydep,
1145 self.cp_list(mydep.cp, use_cache=use_cache)))
1146
1147
1148 Modified: main/branches/prefix/pym/portage/dbapi/vartree.py
1149 ===================================================================
1150 --- main/branches/prefix/pym/portage/dbapi/vartree.py 2010-02-27 19:26:00 UTC (rev 15482)
1151 +++ main/branches/prefix/pym/portage/dbapi/vartree.py 2010-02-27 19:32:48 UTC (rev 15483)
1152 @@ -40,8 +40,9 @@
1153 InvalidData, InvalidPackageName, \
1154 FileNotFound, PermissionDenied, UnsupportedAPIException
1155 from portage.localization import _
1156 +from portage.util.movefile import movefile
1157
1158 -from portage import abssymlink, movefile, _movefile, bsd_chflags
1159 +from portage import abssymlink, _movefile, bsd_chflags
1160
1161 # This is a special version of the os module, wrapped for unicode support.
1162 from portage import os
1163
1164 Deleted: main/branches/prefix/pym/portage/dep.py
1165 ===================================================================
1166 --- main/branches/prefix/pym/portage/dep.py 2010-02-27 19:26:00 UTC (rev 15482)
1167 +++ main/branches/prefix/pym/portage/dep.py 2010-02-27 19:32:48 UTC (rev 15483)
1168 @@ -1,1203 +0,0 @@
1169 -# deps.py -- Portage dependency resolution functions
1170 -# Copyright 2003-2004 Gentoo Foundation
1171 -# Distributed under the terms of the GNU General Public License v2
1172 -# $Id$
1173 -
1174 -__all__ = [
1175 - 'Atom', 'best_match_to_list', 'cpvequal',
1176 - 'dep_getcpv', 'dep_getkey', 'dep_getslot',
1177 - 'dep_getusedeps', 'dep_opconvert', 'flatten',
1178 - 'get_operator', 'isjustname', 'isspecific',
1179 - 'isvalidatom', 'match_from_list', 'match_to_list',
1180 - 'paren_enclose', 'paren_normalize', 'paren_reduce',
1181 - 'remove_slot', 'strip_empty', 'use_reduce'
1182 -]
1183 -
1184 -# DEPEND SYNTAX:
1185 -#
1186 -# 'use?' only affects the immediately following word!
1187 -# Nesting is the only legal way to form multiple '[!]use?' requirements.
1188 -#
1189 -# Where: 'a' and 'b' are use flags, and 'z' is a depend atom.
1190 -#
1191 -# "a? z" -- If 'a' in [use], then b is valid.
1192 -# "a? ( z )" -- Syntax with parenthesis.
1193 -# "a? b? z" -- Deprecated.
1194 -# "a? ( b? z )" -- Valid
1195 -# "a? ( b? ( z ) ) -- Valid
1196 -#
1197 -
1198 -import re, sys
1199 -import warnings
1200 -from itertools import chain
1201 -import portage.exception
1202 -from portage.exception import InvalidData, InvalidAtom
1203 -from portage.localization import _
1204 -from portage.versions import catpkgsplit, catsplit, \
1205 - pkgcmp, pkgsplit, ververify, _cp, _cpv
1206 -import portage.cache.mappings
1207 -
1208 -if sys.hexversion >= 0x3000000:
1209 - basestring = str
1210 -
1211 -def cpvequal(cpv1, cpv2):
1212 - """
1213 -
1214 - @param cpv1: CategoryPackageVersion (no operators) Example: "sys-apps/portage-2.1"
1215 - @type cpv1: String
1216 - @param cpv2: CategoryPackageVersion (no operators) Example: "sys-apps/portage-2.1"
1217 - @type cpv2: String
1218 - @rtype: Boolean
1219 - @returns:
1220 - 1. True if cpv1 = cpv2
1221 - 2. False Otherwise
1222 - 3. Throws PortageException if cpv1 or cpv2 is not a CPV
1223 -
1224 - Example Usage:
1225 - >>> from portage.dep import cpvequal
1226 - >>> cpvequal("sys-apps/portage-2.1","sys-apps/portage-2.1")
1227 - >>> True
1228 -
1229 - """
1230 -
1231 - split1 = catpkgsplit(cpv1)
1232 - split2 = catpkgsplit(cpv2)
1233 -
1234 - if not split1 or not split2:
1235 - raise portage.exception.PortageException(_("Invalid data '%s, %s', parameter was not a CPV") % (cpv1, cpv2))
1236 -
1237 - if split1[0] != split2[0]:
1238 - return False
1239 -
1240 - return (pkgcmp(split1[1:], split2[1:]) == 0)
1241 -
1242 -def strip_empty(myarr):
1243 - """
1244 - Strip all empty elements from an array
1245 -
1246 - @param myarr: The list of elements
1247 - @type myarr: List
1248 - @rtype: Array
1249 - @return: The array with empty elements removed
1250 - """
1251 - return [x for x in myarr if x]
1252 -
1253 -_paren_whitespace_re = re.compile(r'\S(\(|\))|(\(|\))\S')
1254 -
1255 -def paren_reduce(mystr,tokenize=1):
1256 - """
1257 - Take a string and convert all paren enclosed entities into sublists, optionally
1258 - futher splitting the list elements by spaces.
1259 -
1260 - Example usage:
1261 - >>> paren_reduce('foobar foo ( bar baz )',1)
1262 - ['foobar', 'foo', ['bar', 'baz']]
1263 - >>> paren_reduce('foobar foo ( bar baz )',0)
1264 - ['foobar foo ', [' bar baz ']]
1265 -
1266 - @param mystr: The string to reduce
1267 - @type mystr: String
1268 - @param tokenize: Split on spaces to produces further list breakdown
1269 - @type tokenize: Integer
1270 - @rtype: Array
1271 - @return: The reduced string in an array
1272 - """
1273 - global _dep_check_strict, _paren_whitespace_re
1274 - if _dep_check_strict:
1275 - m = _paren_whitespace_re.search(mystr)
1276 - if m is not None:
1277 - raise portage.exception.InvalidDependString(
1278 - _("missing space by parenthesis: '%s'") % m.group(0))
1279 - mylist = []
1280 - while mystr:
1281 - left_paren = mystr.find("(")
1282 - has_left_paren = left_paren != -1
1283 - right_paren = mystr.find(")")
1284 - has_right_paren = right_paren != -1
1285 - if not has_left_paren and not has_right_paren:
1286 - freesec = mystr
1287 - subsec = None
1288 - tail = ""
1289 - elif mystr[0] == ")":
1290 - return [mylist,mystr[1:]]
1291 - elif has_left_paren and not has_right_paren:
1292 - raise portage.exception.InvalidDependString(
1293 - _("missing right parenthesis: '%s'") % mystr)
1294 - elif has_left_paren and left_paren < right_paren:
1295 - freesec,subsec = mystr.split("(",1)
1296 - sublist = paren_reduce(subsec, tokenize=tokenize)
1297 - if len(sublist) != 2:
1298 - raise portage.exception.InvalidDependString(
1299 - _("malformed syntax: '%s'") % mystr)
1300 - subsec, tail = sublist
1301 - else:
1302 - subsec,tail = mystr.split(")",1)
1303 - if tokenize:
1304 - subsec = strip_empty(subsec.split(" "))
1305 - return [mylist+subsec,tail]
1306 - return mylist+[subsec],tail
1307 - if not isinstance(tail, basestring):
1308 - raise portage.exception.InvalidDependString(
1309 - _("malformed syntax: '%s'") % mystr)
1310 - mystr = tail
1311 - if freesec:
1312 - if tokenize:
1313 - mylist = mylist + strip_empty(freesec.split(" "))
1314 - else:
1315 - mylist = mylist + [freesec]
1316 - if subsec is not None:
1317 - mylist = mylist + [subsec]
1318 - return mylist
1319 -
1320 -class paren_normalize(list):
1321 - """Take a dependency structure as returned by paren_reduce or use_reduce
1322 - and generate an equivalent structure that has no redundant lists."""
1323 - def __init__(self, src):
1324 - list.__init__(self)
1325 - self._zap_parens(src, self)
1326 -
1327 - def _zap_parens(self, src, dest, disjunction=False):
1328 - if not src:
1329 - return dest
1330 - i = iter(src)
1331 - for x in i:
1332 - if isinstance(x, basestring):
1333 - if x == '||':
1334 - x = self._zap_parens(next(i), [], disjunction=True)
1335 - if len(x) == 1:
1336 - dest.append(x[0])
1337 - else:
1338 - dest.append("||")
1339 - dest.append(x)
1340 - elif x.endswith("?"):
1341 - dest.append(x)
1342 - dest.append(self._zap_parens(next(i), []))
1343 - else:
1344 - dest.append(x)
1345 - else:
1346 - if disjunction:
1347 - x = self._zap_parens(x, [])
1348 - if len(x) == 1:
1349 - dest.append(x[0])
1350 - else:
1351 - dest.append(x)
1352 - else:
1353 - self._zap_parens(x, dest)
1354 - return dest
1355 -
1356 -def paren_enclose(mylist):
1357 - """
1358 - Convert a list to a string with sublists enclosed with parens.
1359 -
1360 - Example usage:
1361 - >>> test = ['foobar','foo',['bar','baz']]
1362 - >>> paren_enclose(test)
1363 - 'foobar foo ( bar baz )'
1364 -
1365 - @param mylist: The list
1366 - @type mylist: List
1367 - @rtype: String
1368 - @return: The paren enclosed string
1369 - """
1370 - mystrparts = []
1371 - for x in mylist:
1372 - if isinstance(x, list):
1373 - mystrparts.append("( "+paren_enclose(x)+" )")
1374 - else:
1375 - mystrparts.append(x)
1376 - return " ".join(mystrparts)
1377 -
1378 -# This is just for use by emerge so that it can enable a backward compatibility
1379 -# mode in order to gracefully deal with installed packages that have invalid
1380 -# atoms or dep syntax. For backward compatibility with api consumers, strict
1381 -# behavior will be explicitly enabled as necessary.
1382 -_dep_check_strict = False
1383 -
1384 -def use_reduce(deparray, uselist=[], masklist=[], matchall=0, excludeall=[]):
1385 - """
1386 - Takes a paren_reduce'd array and reduces the use? conditionals out
1387 - leaving an array with subarrays
1388 -
1389 - @param deparray: paren_reduce'd list of deps
1390 - @type deparray: List
1391 - @param uselist: List of use flags
1392 - @type uselist: List
1393 - @param masklist: List of masked flags
1394 - @type masklist: List
1395 - @param matchall: Resolve all conditional deps unconditionally. Used by repoman
1396 - @type matchall: Integer
1397 - @rtype: List
1398 - @return: The use reduced depend array
1399 - """
1400 - # Quick validity checks
1401 - for x, y in enumerate(deparray):
1402 - if y == '||':
1403 - if len(deparray) - 1 == x or not isinstance(deparray[x+1], list):
1404 - raise portage.exception.InvalidDependString(_('%(dep)s missing atom list in "%(deparray)s"') % {"dep": deparray[x], "deparray": paren_enclose(deparray)})
1405 - if deparray and deparray[-1] and deparray[-1][-1] == "?":
1406 - raise portage.exception.InvalidDependString(_('Conditional without target in "%s"') % paren_enclose(deparray))
1407 -
1408 - global _dep_check_strict
1409 -
1410 - mydeparray = deparray[:]
1411 - rlist = []
1412 - while mydeparray:
1413 - head = mydeparray.pop(0)
1414 -
1415 - if not isinstance(head, basestring):
1416 - additions = use_reduce(head, uselist, masklist, matchall, excludeall)
1417 - if additions:
1418 - rlist.append(additions)
1419 - elif rlist and rlist[-1] == "||":
1420 - #XXX: Currently some DEPEND strings have || lists without default atoms.
1421 - # raise portage.exception.InvalidDependString("No default atom(s) in \""+paren_enclose(deparray)+"\"")
1422 - rlist.append([])
1423 -
1424 - else:
1425 - if head[-1:] == "?": # Use reduce next group on fail.
1426 - # Pull any other use conditions and the following atom or list into a separate array
1427 - newdeparray = [head]
1428 - while isinstance(newdeparray[-1], basestring) and \
1429 - newdeparray[-1][-1:] == "?":
1430 - if mydeparray:
1431 - newdeparray.append(mydeparray.pop(0))
1432 - else:
1433 - raise ValueError(_("Conditional with no target."))
1434 -
1435 - # Deprecation checks
1436 - warned = 0
1437 - if len(newdeparray[-1]) == 0:
1438 - sys.stderr.write(_("Note: Empty target in string. (Deprecated)\n"))
1439 - warned = 1
1440 - if len(newdeparray) != 2:
1441 - sys.stderr.write(_("Note: Nested use flags without parenthesis (Deprecated)\n"))
1442 - warned = 1
1443 - if warned:
1444 - sys.stderr.write(" --> "+" ".join(map(str,[head]+newdeparray))+"\n")
1445 -
1446 - # Check that each flag matches
1447 - ismatch = True
1448 - missing_flag = False
1449 - for head in newdeparray[:-1]:
1450 - head = head[:-1]
1451 - if not head:
1452 - missing_flag = True
1453 - break
1454 - if head.startswith("!"):
1455 - head_key = head[1:]
1456 - if not head_key:
1457 - missing_flag = True
1458 - break
1459 - if not matchall and head_key in uselist or \
1460 - head_key in excludeall:
1461 - ismatch = False
1462 - break
1463 - elif head not in masklist:
1464 - if not matchall and head not in uselist:
1465 - ismatch = False
1466 - break
1467 - else:
1468 - ismatch = False
1469 - if missing_flag:
1470 - raise portage.exception.InvalidDependString(
1471 - _('Conditional without flag: "') + \
1472 - paren_enclose([head+"?", newdeparray[-1]])+"\"")
1473 -
1474 - # If they all match, process the target
1475 - if ismatch:
1476 - target = newdeparray[-1]
1477 - if isinstance(target, list):
1478 - additions = use_reduce(target, uselist, masklist, matchall, excludeall)
1479 - if additions:
1480 - rlist.append(additions)
1481 - elif not _dep_check_strict:
1482 - # The old deprecated behavior.
1483 - rlist.append(target)
1484 - else:
1485 - raise portage.exception.InvalidDependString(
1486 - _("Conditional without parenthesis: '%s?'") % head)
1487 -
1488 - else:
1489 - rlist += [head]
1490 -
1491 - return rlist
1492 -
1493 -def dep_opconvert(deplist):
1494 - """
1495 - Iterate recursively through a list of deps, if the
1496 - dep is a '||' or '&&' operator, combine it with the
1497 - list of deps that follows..
1498 -
1499 - Example usage:
1500 - >>> test = ["blah", "||", ["foo", "bar", "baz"]]
1501 - >>> dep_opconvert(test)
1502 - ['blah', ['||', 'foo', 'bar', 'baz']]
1503 -
1504 - @param deplist: A list of deps to format
1505 - @type mydep: List
1506 - @rtype: List
1507 - @return:
1508 - The new list with the new ordering
1509 - """
1510 -
1511 - retlist = []
1512 - x = 0
1513 - while x != len(deplist):
1514 - if isinstance(deplist[x], list):
1515 - retlist.append(dep_opconvert(deplist[x]))
1516 - elif deplist[x] == "||" or deplist[x] == "&&":
1517 - retlist.append([deplist[x]] + dep_opconvert(deplist[x+1]))
1518 - x += 1
1519 - else:
1520 - retlist.append(deplist[x])
1521 - x += 1
1522 - return retlist
1523 -
1524 -def flatten(mylist):
1525 - """
1526 - Recursively traverse nested lists and return a single list containing
1527 - all non-list elements that are found.
1528 -
1529 - Example usage:
1530 - >>> flatten([1, [2, 3, [4]]])
1531 - [1, 2, 3, 4]
1532 -
1533 - @param mylist: A list containing nested lists and non-list elements.
1534 - @type mylist: List
1535 - @rtype: List
1536 - @return: A single list containing only non-list elements.
1537 - """
1538 - newlist = []
1539 - for x in mylist:
1540 - if isinstance(x, list):
1541 - newlist.extend(flatten(x))
1542 - else:
1543 - newlist.append(x)
1544 - return newlist
1545 -
1546 -class _use_dep(object):
1547 -
1548 - __slots__ = ("__weakref__", "conditional",
1549 - "disabled", "enabled", "tokens", "required")
1550 -
1551 - _conditionals_class = portage.cache.mappings.slot_dict_class(
1552 - ("disabled", "enabled", "equal", "not_equal"), prefix="")
1553 -
1554 - _valid_use_re = re.compile(r'^[^-?!=][^?!=]*$')
1555 -
1556 - def __init__(self, use):
1557 - enabled_flags = []
1558 - disabled_flags = []
1559 - conditional = self._conditionals_class()
1560 - for k in conditional.allowed_keys:
1561 - conditional[k] = []
1562 -
1563 - for x in use:
1564 - last_char = x[-1:]
1565 - first_char = x[:1]
1566 -
1567 - if "?" == last_char:
1568 - if "!" == first_char:
1569 - conditional.disabled.append(
1570 - self._validate_flag(x, x[1:-1]))
1571 - else:
1572 - conditional.enabled.append(
1573 - self._validate_flag(x, x[:-1]))
1574 -
1575 - elif "=" == last_char:
1576 - if "!" == first_char:
1577 - conditional.not_equal.append(
1578 - self._validate_flag(x, x[1:-1]))
1579 - else:
1580 - conditional.equal.append(
1581 - self._validate_flag(x, x[:-1]))
1582 -
1583 - else:
1584 - if "-" == first_char:
1585 - disabled_flags.append(self._validate_flag(x, x[1:]))
1586 - else:
1587 - enabled_flags.append(self._validate_flag(x, x))
1588 -
1589 - self.tokens = use
1590 - if not isinstance(self.tokens, tuple):
1591 - self.tokens = tuple(self.tokens)
1592 -
1593 - self.required = frozenset(chain(
1594 - enabled_flags,
1595 - disabled_flags,
1596 - *conditional.values()
1597 - ))
1598 -
1599 - self.enabled = frozenset(enabled_flags)
1600 - self.disabled = frozenset(disabled_flags)
1601 - self.conditional = None
1602 -
1603 - for v in conditional.values():
1604 - if v:
1605 - for k, v in conditional.items():
1606 - conditional[k] = frozenset(v)
1607 - self.conditional = conditional
1608 - break
1609 -
1610 - def _validate_flag(self, token, flag):
1611 - if self._valid_use_re.match(flag) is None:
1612 - raise InvalidAtom(_("Invalid use dep: '%s'") % (token,))
1613 - return flag
1614 -
1615 - def __bool__(self):
1616 - return bool(self.tokens)
1617 -
1618 - if sys.hexversion < 0x3000000:
1619 - __nonzero__ = __bool__
1620 -
1621 - def __str__(self):
1622 - if not self.tokens:
1623 - return ""
1624 - return "[%s]" % (",".join(self.tokens),)
1625 -
1626 - def __repr__(self):
1627 - return "portage.dep._use_dep(%s)" % repr(self.tokens)
1628 -
1629 - def evaluate_conditionals(self, use):
1630 - """
1631 - Create a new instance with conditionals evaluated.
1632 -
1633 - Conditional evaluation behavior:
1634 -
1635 - parent state conditional result
1636 -
1637 - x x? x
1638 - -x x?
1639 - x !x?
1640 - -x !x? -x
1641 -
1642 - x x= x
1643 - -x x= -x
1644 - x !x= -x
1645 - -x !x= x
1646 -
1647 - Conditional syntax examples:
1648 -
1649 - Compact Form Equivalent Expanded Form
1650 -
1651 - foo[bar?] bar? ( foo[bar] ) !bar? ( foo )
1652 - foo[!bar?] bar? ( foo ) !bar? ( foo[-bar] )
1653 - foo[bar=] bar? ( foo[bar] ) !bar? ( foo[-bar] )
1654 - foo[!bar=] bar? ( foo[-bar] ) !bar? ( foo[bar] )
1655 -
1656 - """
1657 - tokens = []
1658 -
1659 - conditional = self.conditional
1660 - tokens.extend(self.enabled)
1661 - tokens.extend("-" + x for x in self.disabled)
1662 - tokens.extend(x for x in conditional.enabled if x in use)
1663 - tokens.extend("-" + x for x in conditional.disabled if x not in use)
1664 -
1665 - tokens.extend(x for x in conditional.equal if x in use)
1666 - tokens.extend("-" + x for x in conditional.equal if x not in use)
1667 - tokens.extend("-" + x for x in conditional.not_equal if x in use)
1668 - tokens.extend(x for x in conditional.not_equal if x not in use)
1669 -
1670 - return _use_dep(tokens)
1671 -
1672 - def _eval_qa_conditionals(self, use_mask, use_force):
1673 - """
1674 - For repoman, evaluate all possible combinations within the constraints
1675 - of the given use.force and use.mask settings. The result may seem
1676 - ambiguous in the sense that the same flag can be in both the enabled
1677 - and disabled sets, but this is useful within the context of how its
1678 - intended to be used by repoman. It is assumed that the caller has
1679 - already ensured that there is no intersection between the given
1680 - use_mask and use_force sets when necessary.
1681 - """
1682 - tokens = []
1683 -
1684 - conditional = self.conditional
1685 - tokens.extend(self.enabled)
1686 - tokens.extend("-" + x for x in self.disabled)
1687 - tokens.extend(x for x in conditional.enabled if x not in use_mask)
1688 - tokens.extend("-" + x for x in conditional.disabled if x not in use_force)
1689 -
1690 - tokens.extend(x for x in conditional.equal if x not in use_mask)
1691 - tokens.extend("-" + x for x in conditional.equal if x not in use_force)
1692 - tokens.extend("-" + x for x in conditional.not_equal if x not in use_mask)
1693 - tokens.extend(x for x in conditional.not_equal if x not in use_force)
1694 -
1695 - return _use_dep(tokens)
1696 -
1697 -if sys.hexversion < 0x3000000:
1698 - _atom_base = unicode
1699 -else:
1700 - _atom_base = str
1701 -
1702 -class Atom(_atom_base):
1703 -
1704 - """
1705 - For compatibility with existing atom string manipulation code, this
1706 - class emulates most of the str methods that are useful with atoms.
1707 - """
1708 -
1709 - class _blocker(object):
1710 - __slots__ = ("overlap",)
1711 -
1712 - class _overlap(object):
1713 - __slots__ = ("forbid",)
1714 -
1715 - def __init__(self, forbid=False):
1716 - self.forbid = forbid
1717 -
1718 - def __init__(self, forbid_overlap=False):
1719 - self.overlap = self._overlap(forbid=forbid_overlap)
1720 -
1721 - def __init__(self, s):
1722 - if isinstance(s, Atom):
1723 - # This is an efficiency assertion, to ensure that the Atom
1724 - # constructor is not called redundantly.
1725 - raise TypeError(_("Expected %s, got %s") % \
1726 - (_atom_base, type(s)))
1727 -
1728 - _atom_base.__init__(s)
1729 -
1730 - if "!" == s[:1]:
1731 - blocker = self._blocker(forbid_overlap=("!" == s[1:2]))
1732 - if blocker.overlap.forbid:
1733 - s = s[2:]
1734 - else:
1735 - s = s[1:]
1736 - else:
1737 - blocker = False
1738 - self.__dict__['blocker'] = blocker
1739 - m = _atom_re.match(s)
1740 - if m is None:
1741 - raise InvalidAtom(self)
1742 -
1743 - if m.group('op') is not None:
1744 - base = _atom_re.groupindex['op']
1745 - op = m.group(base + 1)
1746 - cpv = m.group(base + 2)
1747 - cp = m.group(base + 3)
1748 - if m.group(base + 4) is not None:
1749 - raise InvalidAtom(self)
1750 - elif m.group('star') is not None:
1751 - base = _atom_re.groupindex['star']
1752 - op = '=*'
1753 - cpv = m.group(base + 1)
1754 - cp = m.group(base + 2)
1755 - if m.group(base + 3) is not None:
1756 - raise InvalidAtom(self)
1757 - elif m.group('simple') is not None:
1758 - op = None
1759 - cpv = cp = m.group(_atom_re.groupindex['simple'] + 1)
1760 - if m.group(_atom_re.groupindex['simple'] + 2) is not None:
1761 - raise InvalidAtom(self)
1762 - else:
1763 - raise AssertionError(_("required group not found in atom: '%s'") % self)
1764 - self.__dict__['cp'] = cp
1765 - self.__dict__['cpv'] = cpv
1766 - self.__dict__['slot'] = m.group(_atom_re.groups - 1)
1767 - self.__dict__['operator'] = op
1768 -
1769 - use_str = m.group(_atom_re.groups)
1770 - if use_str is not None:
1771 - use = _use_dep(dep_getusedeps(s))
1772 - without_use = Atom(m.group('without_use'))
1773 - else:
1774 - use = None
1775 - without_use = self
1776 -
1777 - self.__dict__['use'] = use
1778 - self.__dict__['without_use'] = without_use
1779 -
1780 - def __setattr__(self, name, value):
1781 - raise AttributeError("Atom instances are immutable",
1782 - self.__class__, name, value)
1783 -
1784 - def intersects(self, other):
1785 - """
1786 - Atoms with different cpv, operator or use attributes cause this method
1787 - to return False even though there may actually be some intersection.
1788 - TODO: Detect more forms of intersection.
1789 - @param other: The package atom to match
1790 - @type other: Atom
1791 - @rtype: Boolean
1792 - @return: True if this atom and the other atom intersect,
1793 - False otherwise.
1794 - """
1795 - if not isinstance(other, Atom):
1796 - raise TypeError("expected %s, got %s" % \
1797 - (Atom, type(other)))
1798 -
1799 - if self == other:
1800 - return True
1801 -
1802 - if self.cp != other.cp or \
1803 - self.use != other.use or \
1804 - self.operator != other.operator or \
1805 - self.cpv != other.cpv:
1806 - return False
1807 -
1808 - if self.slot is None or \
1809 - other.slot is None or \
1810 - self.slot == other.slot:
1811 - return True
1812 -
1813 - return False
1814 -
1815 - def evaluate_conditionals(self, use):
1816 - """
1817 - Create an atom instance with any USE conditionals evaluated.
1818 - @param use: The set of enabled USE flags
1819 - @type use: set
1820 - @rtype: Atom
1821 - @return: an atom instance with any USE conditionals evaluated
1822 - """
1823 - if not (self.use and self.use.conditional):
1824 - return self
1825 - atom = remove_slot(self)
1826 - if self.slot:
1827 - atom += ":%s" % self.slot
1828 - atom += str(self.use.evaluate_conditionals(use))
1829 - return Atom(atom)
1830 -
1831 - def __copy__(self):
1832 - """Immutable, so returns self."""
1833 - return self
1834 -
1835 - def __deepcopy__(self, memo=None):
1836 - """Immutable, so returns self."""
1837 - memo[id(self)] = self
1838 - return self
1839 -
1840 -def get_operator(mydep):
1841 - """
1842 - Return the operator used in a depstring.
1843 -
1844 - Example usage:
1845 - >>> from portage.dep import *
1846 - >>> get_operator(">=test-1.0")
1847 - '>='
1848 -
1849 - @param mydep: The dep string to check
1850 - @type mydep: String
1851 - @rtype: String
1852 - @return: The operator. One of:
1853 - '~', '=', '>', '<', '=*', '>=', or '<='
1854 - """
1855 - if isinstance(mydep, Atom):
1856 - return mydep.operator
1857 - try:
1858 - return Atom(mydep).operator
1859 - except InvalidAtom:
1860 - pass
1861 -
1862 - # Fall back to legacy code for backward compatibility.
1863 - warnings.warn(_("%s is deprecated, use %s instead") % \
1864 - ('portage.dep.get_operator()', 'portage.dep.Atom.operator'),
1865 - DeprecationWarning)
1866 - operator = None
1867 - if mydep:
1868 - mydep = remove_slot(mydep)
1869 - if not mydep:
1870 - return None
1871 - if mydep[0] == "~":
1872 - operator = "~"
1873 - elif mydep[0] == "=":
1874 - if mydep[-1] == "*":
1875 - operator = "=*"
1876 - else:
1877 - operator = "="
1878 - elif mydep[0] in "><":
1879 - if len(mydep) > 1 and mydep[1] == "=":
1880 - operator = mydep[0:2]
1881 - else:
1882 - operator = mydep[0]
1883 - else:
1884 - operator = None
1885 -
1886 - return operator
1887 -
1888 -def dep_getcpv(mydep):
1889 - """
1890 - Return the category-package-version with any operators/slot specifications stripped off
1891 -
1892 - Example usage:
1893 - >>> dep_getcpv('>=media-libs/test-3.0')
1894 - 'media-libs/test-3.0'
1895 -
1896 - @param mydep: The depstring
1897 - @type mydep: String
1898 - @rtype: String
1899 - @return: The depstring with the operator removed
1900 - """
1901 - if isinstance(mydep, Atom):
1902 - return mydep.cpv
1903 - try:
1904 - return Atom(mydep).cpv
1905 - except InvalidAtom:
1906 - pass
1907 -
1908 - # Fall back to legacy code for backward compatibility.
1909 - warnings.warn(_("%s is deprecated, use %s instead") % \
1910 - ('portage.dep.dep_getcpv()', 'portage.dep.Atom.cpv'),
1911 - DeprecationWarning, stacklevel=2)
1912 - mydep_orig = mydep
1913 - if mydep:
1914 - mydep = remove_slot(mydep)
1915 - if mydep and mydep[0] == "*":
1916 - mydep = mydep[1:]
1917 - if mydep and mydep[-1] == "*":
1918 - mydep = mydep[:-1]
1919 - if mydep and mydep[0] == "!":
1920 - if mydep[1:2] == "!":
1921 - mydep = mydep[2:]
1922 - else:
1923 - mydep = mydep[1:]
1924 - if mydep[:2] in [">=", "<="]:
1925 - mydep = mydep[2:]
1926 - elif mydep[:1] in "=<>~":
1927 - mydep = mydep[1:]
1928 - return mydep
1929 -
1930 -def dep_getslot(mydep):
1931 - """
1932 - Retrieve the slot on a depend.
1933 -
1934 - Example usage:
1935 - >>> dep_getslot('app-misc/test:3')
1936 - '3'
1937 -
1938 - @param mydep: The depstring to retrieve the slot of
1939 - @type mydep: String
1940 - @rtype: String
1941 - @return: The slot
1942 - """
1943 - slot = getattr(mydep, "slot", False)
1944 - if slot is not False:
1945 - return slot
1946 - colon = mydep.find(":")
1947 - if colon != -1:
1948 - bracket = mydep.find("[", colon)
1949 - if bracket == -1:
1950 - return mydep[colon+1:]
1951 - else:
1952 - return mydep[colon+1:bracket]
1953 - return None
1954 -
1955 -def remove_slot(mydep):
1956 - """
1957 - Removes dep components from the right side of an atom:
1958 - * slot
1959 - * use
1960 - * repo
1961 - """
1962 - colon = mydep.find(":")
1963 - if colon != -1:
1964 - mydep = mydep[:colon]
1965 - else:
1966 - bracket = mydep.find("[")
1967 - if bracket != -1:
1968 - mydep = mydep[:bracket]
1969 - return mydep
1970 -
1971 -def dep_getusedeps( depend ):
1972 - """
1973 - Pull a listing of USE Dependencies out of a dep atom.
1974 -
1975 - Example usage:
1976 - >>> dep_getusedeps('app-misc/test:3[foo,-bar]')
1977 - ('foo', '-bar')
1978 -
1979 - @param depend: The depstring to process
1980 - @type depend: String
1981 - @rtype: List
1982 - @return: List of use flags ( or [] if no flags exist )
1983 - """
1984 - use_list = []
1985 - open_bracket = depend.find('[')
1986 - # -1 = failure (think c++ string::npos)
1987 - comma_separated = False
1988 - bracket_count = 0
1989 - while( open_bracket != -1 ):
1990 - bracket_count += 1
1991 - if bracket_count > 1:
1992 - raise InvalidAtom(_("USE Dependency with more "
1993 - "than one set of brackets: %s") % (depend,))
1994 - close_bracket = depend.find(']', open_bracket )
1995 - if close_bracket == -1:
1996 - raise InvalidAtom(_("USE Dependency with no closing bracket: %s") % depend )
1997 - use = depend[open_bracket + 1: close_bracket]
1998 - # foo[1:1] may return '' instead of None, we don't want '' in the result
1999 - if not use:
2000 - raise InvalidAtom(_("USE Dependency with "
2001 - "no use flag ([]): %s") % depend )
2002 - if not comma_separated:
2003 - comma_separated = "," in use
2004 -
2005 - if comma_separated and bracket_count > 1:
2006 - raise InvalidAtom(_("USE Dependency contains a mixture of "
2007 - "comma and bracket separators: %s") % depend )
2008 -
2009 - if comma_separated:
2010 - for x in use.split(","):
2011 - if x:
2012 - use_list.append(x)
2013 - else:
2014 - raise InvalidAtom(_("USE Dependency with no use "
2015 - "flag next to comma: %s") % depend )
2016 - else:
2017 - use_list.append(use)
2018 -
2019 - # Find next use flag
2020 - open_bracket = depend.find( '[', open_bracket+1 )
2021 - return tuple(use_list)
2022 -
2023 -# \w is [a-zA-Z0-9_]
2024 -
2025 -# 2.1.3 A slot name may contain any of the characters [A-Za-z0-9+_.-].
2026 -# It must not begin with a hyphen or a dot.
2027 -_slot = r'([\w+][\w+.-]*)'
2028 -_slot_re = re.compile('^' + _slot + '$', re.VERBOSE)
2029 -
2030 -_use = r'\[.*\]'
2031 -_op = r'([=~]|[><]=?)'
2032 -
2033 -_atom_re = re.compile('^(?P<without_use>(?:' +
2034 - '(?P<op>' + _op + _cpv + ')|' +
2035 - '(?P<star>=' + _cpv + r'\*)|' +
2036 - '(?P<simple>' + _cp + '))(:' + _slot + ')?)(' + _use + ')?$', re.VERBOSE)
2037 -
2038 -def isvalidatom(atom, allow_blockers=False):
2039 - """
2040 - Check to see if a depend atom is valid
2041 -
2042 - Example usage:
2043 - >>> isvalidatom('media-libs/test-3.0')
2044 - False
2045 - >>> isvalidatom('>=media-libs/test-3.0')
2046 - True
2047 -
2048 - @param atom: The depend atom to check against
2049 - @type atom: String or Atom
2050 - @rtype: Boolean
2051 - @return: One of the following:
2052 - 1) False if the atom is invalid
2053 - 2) True if the atom is valid
2054 - """
2055 - try:
2056 - if not isinstance(atom, Atom):
2057 - atom = Atom(atom)
2058 - if not allow_blockers and atom.blocker:
2059 - return False
2060 - return True
2061 - except InvalidAtom:
2062 - return False
2063 -
2064 -def isjustname(mypkg):
2065 - """
2066 - Checks to see if the atom is only the package name (no version parts).
2067 -
2068 - Example usage:
2069 - >>> isjustname('=media-libs/test-3.0')
2070 - False
2071 - >>> isjustname('media-libs/test')
2072 - True
2073 -
2074 - @param mypkg: The package atom to check
2075 - @param mypkg: String or Atom
2076 - @rtype: Integer
2077 - @return: One of the following:
2078 - 1) False if the package string is not just the package name
2079 - 2) True if it is
2080 - """
2081 - try:
2082 - if not isinstance(mypkg, Atom):
2083 - mypkg = Atom(mypkg)
2084 - return mypkg == mypkg.cp
2085 - except InvalidAtom:
2086 - pass
2087 -
2088 - for x in mypkg.split('-')[-2:]:
2089 - if ververify(x):
2090 - return False
2091 - return True
2092 -
2093 -def isspecific(mypkg):
2094 - """
2095 - Checks to see if a package is in =category/package-version or
2096 - package-version format.
2097 -
2098 - Example usage:
2099 - >>> isspecific('media-libs/test')
2100 - False
2101 - >>> isspecific('=media-libs/test-3.0')
2102 - True
2103 -
2104 - @param mypkg: The package depstring to check against
2105 - @type mypkg: String
2106 - @rtype: Boolean
2107 - @return: One of the following:
2108 - 1) False if the package string is not specific
2109 - 2) True if it is
2110 - """
2111 - try:
2112 - if not isinstance(mypkg, Atom):
2113 - mypkg = Atom(mypkg)
2114 - return mypkg != mypkg.cp
2115 - except InvalidAtom:
2116 - pass
2117 -
2118 - # Fall back to legacy code for backward compatibility.
2119 - return not isjustname(mypkg)
2120 -
2121 -def dep_getkey(mydep):
2122 - """
2123 - Return the category/package-name of a depstring.
2124 -
2125 - Example usage:
2126 - >>> dep_getkey('=media-libs/test-3.0')
2127 - 'media-libs/test'
2128 -
2129 - @param mydep: The depstring to retrieve the category/package-name of
2130 - @type mydep: String
2131 - @rtype: String
2132 - @return: The package category/package-name
2133 - """
2134 - if isinstance(mydep, Atom):
2135 - return mydep.cp
2136 - try:
2137 - return Atom(mydep).cp
2138 - except InvalidAtom:
2139 - try:
2140 - atom = Atom('=' + mydep)
2141 - except InvalidAtom:
2142 - pass
2143 - else:
2144 - warnings.warn(_("invalid input to %s: '%s', use %s instead") % \
2145 - ('portage.dep.dep_getkey()', mydep, 'portage.cpv_getkey()'),
2146 - DeprecationWarning, stacklevel=2)
2147 - return atom.cp
2148 -
2149 - # Fall back to legacy code for backward compatibility.
2150 - warnings.warn(_("%s is deprecated, use %s instead") % \
2151 - ('portage.dep.dep_getkey()', 'portage.dep.Atom.cp'),
2152 - DeprecationWarning, stacklevel=2)
2153 - mydep = dep_getcpv(mydep)
2154 - if mydep and isspecific(mydep):
2155 - mysplit = catpkgsplit(mydep)
2156 - if not mysplit:
2157 - return mydep
2158 - return mysplit[0] + "/" + mysplit[1]
2159 - else:
2160 - return mydep
2161 -
2162 -def match_to_list(mypkg, mylist):
2163 - """
2164 - Searches list for entries that matches the package.
2165 -
2166 - @param mypkg: The package atom to match
2167 - @type mypkg: String
2168 - @param mylist: The list of package atoms to compare against
2169 - @param mylist: List
2170 - @rtype: List
2171 - @return: A unique list of package atoms that match the given package atom
2172 - """
2173 - return [ x for x in set(mylist) if match_from_list(x, [mypkg]) ]
2174 -
2175 -def best_match_to_list(mypkg, mylist):
2176 - """
2177 - Returns the most specific entry that matches the package given.
2178 -
2179 - @param mypkg: The package atom to check
2180 - @type mypkg: String
2181 - @param mylist: The list of package atoms to check against
2182 - @type mylist: List
2183 - @rtype: String
2184 - @return: The package atom which best matches given the following ordering:
2185 - - =cpv 6
2186 - - ~cpv 5
2187 - - =cpv* 4
2188 - - cp:slot 3
2189 - - >cpv 2
2190 - - <cpv 2
2191 - - >=cpv 2
2192 - - <=cpv 2
2193 - - cp 1
2194 - """
2195 - operator_values = {'=':6, '~':5, '=*':4,
2196 - '>':2, '<':2, '>=':2, '<=':2, None:1}
2197 - maxvalue = 0
2198 - bestm = None
2199 - for x in match_to_list(mypkg, mylist):
2200 - if dep_getslot(x) is not None:
2201 - if maxvalue < 3:
2202 - maxvalue = 3
2203 - bestm = x
2204 - op_val = operator_values[x.operator]
2205 - if op_val > maxvalue:
2206 - maxvalue = op_val
2207 - bestm = x
2208 - return bestm
2209 -
2210 -def match_from_list(mydep, candidate_list):
2211 - """
2212 - Searches list for entries that matches the package.
2213 -
2214 - @param mydep: The package atom to match
2215 - @type mydep: String
2216 - @param candidate_list: The list of package atoms to compare against
2217 - @param candidate_list: List
2218 - @rtype: List
2219 - @return: A list of package atoms that match the given package atom
2220 - """
2221 -
2222 - if not candidate_list:
2223 - return []
2224 -
2225 - from portage.util import writemsg
2226 - if "!" == mydep[:1]:
2227 - mydep = mydep[1:]
2228 - if not isinstance(mydep, Atom):
2229 - mydep = Atom(mydep)
2230 -
2231 - mycpv = mydep.cpv
2232 - mycpv_cps = catpkgsplit(mycpv) # Can be None if not specific
2233 - slot = mydep.slot
2234 -
2235 - if not mycpv_cps:
2236 - cat, pkg = catsplit(mycpv)
2237 - ver = None
2238 - rev = None
2239 - else:
2240 - cat, pkg, ver, rev = mycpv_cps
2241 - if mydep == mycpv:
2242 - raise KeyError(_("Specific key requires an operator"
2243 - " (%s) (try adding an '=')") % (mydep))
2244 -
2245 - if ver and rev:
2246 - operator = mydep.operator
2247 - if not operator:
2248 - writemsg(_("!!! Invalid atom: %s\n") % mydep, noiselevel=-1)
2249 - return []
2250 - else:
2251 - operator = None
2252 -
2253 - mylist = []
2254 -
2255 - if operator is None:
2256 - for x in candidate_list:
2257 - cp = getattr(x, "cp", None)
2258 - if cp is None:
2259 - mysplit = catpkgsplit(remove_slot(x))
2260 - if mysplit is not None:
2261 - cp = mysplit[0] + '/' + mysplit[1]
2262 - if cp != mycpv:
2263 - continue
2264 - mylist.append(x)
2265 -
2266 - elif operator == "=": # Exact match
2267 - for x in candidate_list:
2268 - xcpv = getattr(x, "cpv", None)
2269 - if xcpv is None:
2270 - xcpv = remove_slot(x)
2271 - if not cpvequal(xcpv, mycpv):
2272 - continue
2273 - mylist.append(x)
2274 -
2275 - elif operator == "=*": # glob match
2276 - # XXX: Nasty special casing for leading zeros
2277 - # Required as =* is a literal prefix match, so can't
2278 - # use vercmp
2279 - mysplit = catpkgsplit(mycpv)
2280 - myver = mysplit[2].lstrip("0")
2281 - if not myver or not myver[0].isdigit():
2282 - myver = "0"+myver
2283 - mycpv = mysplit[0]+"/"+mysplit[1]+"-"+myver
2284 - for x in candidate_list:
2285 - xs = getattr(x, "cpv_split", None)
2286 - if xs is None:
2287 - xs = catpkgsplit(remove_slot(x))
2288 - myver = xs[2].lstrip("0")
2289 - if not myver or not myver[0].isdigit():
2290 - myver = "0"+myver
2291 - xcpv = xs[0]+"/"+xs[1]+"-"+myver
2292 - if xcpv.startswith(mycpv):
2293 - mylist.append(x)
2294 -
2295 - elif operator == "~": # version, any revision, match
2296 - for x in candidate_list:
2297 - xs = getattr(x, "cpv_split", None)
2298 - if xs is None:
2299 - xs = catpkgsplit(remove_slot(x))
2300 - if xs is None:
2301 - raise InvalidData(x)
2302 - if not cpvequal(xs[0]+"/"+xs[1]+"-"+xs[2], mycpv_cps[0]+"/"+mycpv_cps[1]+"-"+mycpv_cps[2]):
2303 - continue
2304 - if xs[2] != ver:
2305 - continue
2306 - mylist.append(x)
2307 -
2308 - elif operator in [">", ">=", "<", "<="]:
2309 - mysplit = ["%s/%s" % (cat, pkg), ver, rev]
2310 - for x in candidate_list:
2311 - xs = getattr(x, "cpv_split", None)
2312 - if xs is None:
2313 - xs = catpkgsplit(remove_slot(x))
2314 - xcat, xpkg, xver, xrev = xs
2315 - xs = ["%s/%s" % (xcat, xpkg), xver, xrev]
2316 - try:
2317 - result = pkgcmp(xs, mysplit)
2318 - except ValueError: # pkgcmp may return ValueError during int() conversion
2319 - writemsg(_("\nInvalid package name: %s\n") % x, noiselevel=-1)
2320 - raise
2321 - if result is None:
2322 - continue
2323 - elif operator == ">":
2324 - if result > 0:
2325 - mylist.append(x)
2326 - elif operator == ">=":
2327 - if result >= 0:
2328 - mylist.append(x)
2329 - elif operator == "<":
2330 - if result < 0:
2331 - mylist.append(x)
2332 - elif operator == "<=":
2333 - if result <= 0:
2334 - mylist.append(x)
2335 - else:
2336 - raise KeyError(_("Unknown operator: %s") % mydep)
2337 - else:
2338 - raise KeyError(_("Unknown operator: %s") % mydep)
2339 -
2340 - if slot is not None:
2341 - candidate_list = mylist
2342 - mylist = []
2343 - for x in candidate_list:
2344 - xslot = getattr(x, "slot", False)
2345 - if xslot is False:
2346 - xslot = dep_getslot(x)
2347 - if xslot is not None and xslot != slot:
2348 - continue
2349 - mylist.append(x)
2350 -
2351 - if mydep.use:
2352 - candidate_list = mylist
2353 - mylist = []
2354 - for x in candidate_list:
2355 - use = getattr(x, "use", None)
2356 - if use is not None:
2357 - regex = x.iuse.regex
2358 - missing_iuse = False
2359 - for y in mydep.use.required:
2360 - if regex.match(y) is None:
2361 - missing_iuse = True
2362 - break
2363 - if missing_iuse:
2364 - continue
2365 - if mydep.use.enabled.difference(use.enabled):
2366 - continue
2367 - if mydep.use.disabled.intersection(use.enabled):
2368 - continue
2369 - mylist.append(x)
2370 -
2371 - return mylist
2372
2373 Copied: main/branches/prefix/pym/portage/package/ebuild/getmaskingreason.py (from rev 15465, main/trunk/pym/portage/package/ebuild/getmaskingreason.py)
2374 ===================================================================
2375 --- main/branches/prefix/pym/portage/package/ebuild/getmaskingreason.py (rev 0)
2376 +++ main/branches/prefix/pym/portage/package/ebuild/getmaskingreason.py 2010-02-27 19:32:48 UTC (rev 15483)
2377 @@ -0,0 +1,78 @@
2378 +# Copyright 2010 Gentoo Foundation
2379 +# Distributed under the terms of the GNU General Public License v2
2380 +# $Id$
2381 +
2382 +__all__ = ['getmaskingreason']
2383 +
2384 +import portage
2385 +from portage import os
2386 +from portage.const import USER_CONFIG_PATH
2387 +from portage.dep import match_from_list
2388 +from portage.localization import _
2389 +from portage.util import grablines, normalize_path
2390 +from portage.versions import catpkgsplit
2391 +
2392 +def getmaskingreason(mycpv, metadata=None, settings=None, portdb=None, return_location=False):
2393 + if settings is None:
2394 + settings = portage.settings
2395 + if portdb is None:
2396 + portdb = portage.portdb
2397 + mysplit = catpkgsplit(mycpv)
2398 + if not mysplit:
2399 + raise ValueError(_("invalid CPV: %s") % mycpv)
2400 + if metadata is None:
2401 + db_keys = list(portdb._aux_cache_keys)
2402 + try:
2403 + metadata = dict(zip(db_keys, portdb.aux_get(mycpv, db_keys)))
2404 + except KeyError:
2405 + if not portdb.cpv_exists(mycpv):
2406 + raise
2407 + if metadata is None:
2408 + # Can't access SLOT due to corruption.
2409 + cpv_slot_list = [mycpv]
2410 + else:
2411 + cpv_slot_list = ["%s:%s" % (mycpv, metadata["SLOT"])]
2412 + mycp=mysplit[0]+"/"+mysplit[1]
2413 +
2414 + # XXX- This is a temporary duplicate of code from the config constructor.
2415 + locations = [os.path.join(settings["PORTDIR"], "profiles")]
2416 + locations.extend(settings.profiles)
2417 + for ov in settings["PORTDIR_OVERLAY"].split():
2418 + profdir = os.path.join(normalize_path(ov), "profiles")
2419 + if os.path.isdir(profdir):
2420 + locations.append(profdir)
2421 + locations.append(os.path.join(settings["PORTAGE_CONFIGROOT"],
2422 + USER_CONFIG_PATH))
2423 + locations.reverse()
2424 + pmasklists = [(x, grablines(os.path.join(x, "package.mask"), recursive=1)) for x in locations]
2425 +
2426 + if mycp in settings.pmaskdict:
2427 + for x in settings.pmaskdict[mycp]:
2428 + if match_from_list(x, cpv_slot_list):
2429 + for pmask in pmasklists:
2430 + comment = ""
2431 + comment_valid = -1
2432 + pmask_filename = os.path.join(pmask[0], "package.mask")
2433 + for i in range(len(pmask[1])):
2434 + l = pmask[1][i].strip()
2435 + if l == "":
2436 + comment = ""
2437 + comment_valid = -1
2438 + elif l[0] == "#":
2439 + comment += (l+"\n")
2440 + comment_valid = i + 1
2441 + elif l == x:
2442 + if comment_valid != i:
2443 + comment = ""
2444 + if return_location:
2445 + return (comment, pmask_filename)
2446 + else:
2447 + return comment
2448 + elif comment_valid != -1:
2449 + # Apparently this comment applies to muliple masks, so
2450 + # it remains valid until a blank line is encountered.
2451 + comment_valid += 1
2452 + if return_location:
2453 + return (None, None)
2454 + else:
2455 + return None
2456
2457 Copied: main/branches/prefix/pym/portage/package/ebuild/getmaskingstatus.py (from rev 15465, main/trunk/pym/portage/package/ebuild/getmaskingstatus.py)
2458 ===================================================================
2459 --- main/branches/prefix/pym/portage/package/ebuild/getmaskingstatus.py (rev 0)
2460 +++ main/branches/prefix/pym/portage/package/ebuild/getmaskingstatus.py 2010-02-27 19:32:48 UTC (rev 15483)
2461 @@ -0,0 +1,154 @@
2462 +# Copyright 2010 Gentoo Foundation
2463 +# Distributed under the terms of the GNU General Public License v2
2464 +# $Id$
2465 +
2466 +__all__ = ['getmaskingstatus']
2467 +
2468 +import portage
2469 +from portage import eapi_is_supported, _eapi_is_deprecated
2470 +from portage.dep import match_from_list
2471 +from portage.localization import _
2472 +from portage.package.ebuild.config import config
2473 +from portage.versions import catpkgsplit, cpv_getkey
2474 +
2475 +def getmaskingstatus(mycpv, settings=None, portdb=None):
2476 + if settings is None:
2477 + settings = config(clone=portage.settings)
2478 + if portdb is None:
2479 + portdb = portage.portdb
2480 +
2481 + metadata = None
2482 + installed = False
2483 + if not isinstance(mycpv, basestring):
2484 + # emerge passed in a Package instance
2485 + pkg = mycpv
2486 + mycpv = pkg.cpv
2487 + metadata = pkg.metadata
2488 + installed = pkg.installed
2489 +
2490 + mysplit = catpkgsplit(mycpv)
2491 + if not mysplit:
2492 + raise ValueError(_("invalid CPV: %s") % mycpv)
2493 + if metadata is None:
2494 + db_keys = list(portdb._aux_cache_keys)
2495 + try:
2496 + metadata = dict(zip(db_keys, portdb.aux_get(mycpv, db_keys)))
2497 + except KeyError:
2498 + if not portdb.cpv_exists(mycpv):
2499 + raise
2500 + return ["corruption"]
2501 + if "?" in metadata["LICENSE"]:
2502 + settings.setcpv(mycpv, mydb=metadata)
2503 + metadata["USE"] = settings["PORTAGE_USE"]
2504 + else:
2505 + metadata["USE"] = ""
2506 +
2507 + rValue = []
2508 +
2509 + # profile checking
2510 + if settings._getProfileMaskAtom(mycpv, metadata):
2511 + rValue.append("profile")
2512 +
2513 + # package.mask checking
2514 + if settings._getMaskAtom(mycpv, metadata):
2515 + rValue.append("package.mask")
2516 +
2517 + # keywords checking
2518 + eapi = metadata["EAPI"]
2519 + mygroups = settings._getKeywords(mycpv, metadata)
2520 + licenses = metadata["LICENSE"]
2521 + properties = metadata["PROPERTIES"]
2522 + if eapi.startswith("-"):
2523 + eapi = eapi[1:]
2524 + if not eapi_is_supported(eapi):
2525 + return ["EAPI %s" % eapi]
2526 + elif _eapi_is_deprecated(eapi) and not installed:
2527 + return ["EAPI %s" % eapi]
2528 + egroups = settings.configdict["backupenv"].get(
2529 + "ACCEPT_KEYWORDS", "").split()
2530 + pgroups = settings["ACCEPT_KEYWORDS"].split()
2531 + myarch = settings["ARCH"]
2532 + if pgroups and myarch not in pgroups:
2533 + """For operating systems other than Linux, ARCH is not necessarily a
2534 + valid keyword."""
2535 + myarch = pgroups[0].lstrip("~")
2536 +
2537 + cp = cpv_getkey(mycpv)
2538 + pkgdict = settings.pkeywordsdict.get(cp)
2539 + matches = False
2540 + if pkgdict:
2541 + cpv_slot_list = ["%s:%s" % (mycpv, metadata["SLOT"])]
2542 + for atom, pkgkeywords in pkgdict.items():
2543 + if match_from_list(atom, cpv_slot_list):
2544 + matches = True
2545 + pgroups.extend(pkgkeywords)
2546 + if matches or egroups:
2547 + pgroups.extend(egroups)
2548 + inc_pgroups = set()
2549 + for x in pgroups:
2550 + if x.startswith("-"):
2551 + if x == "-*":
2552 + inc_pgroups.clear()
2553 + else:
2554 + inc_pgroups.discard(x[1:])
2555 + else:
2556 + inc_pgroups.add(x)
2557 + pgroups = inc_pgroups
2558 + del inc_pgroups
2559 +
2560 + kmask = "missing"
2561 +
2562 + if '**' in pgroups:
2563 + kmask = None
2564 + else:
2565 + for keyword in pgroups:
2566 + if keyword in mygroups:
2567 + kmask = None
2568 + break
2569 +
2570 + if kmask:
2571 + for gp in mygroups:
2572 + if gp=="*":
2573 + kmask=None
2574 + break
2575 + elif gp=="-"+myarch and myarch in pgroups:
2576 + kmask="-"+myarch
2577 + break
2578 + elif gp=="~"+myarch and myarch in pgroups:
2579 + kmask="~"+myarch
2580 + break
2581 +
2582 + try:
2583 + missing_licenses = settings._getMissingLicenses(mycpv, metadata)
2584 + if missing_licenses:
2585 + allowed_tokens = set(["||", "(", ")"])
2586 + allowed_tokens.update(missing_licenses)
2587 + license_split = licenses.split()
2588 + license_split = [x for x in license_split \
2589 + if x in allowed_tokens]
2590 + msg = license_split[:]
2591 + msg.append("license(s)")
2592 + rValue.append(" ".join(msg))
2593 + except portage.exception.InvalidDependString as e:
2594 + rValue.append("LICENSE: "+str(e))
2595 +
2596 + try:
2597 + missing_properties = settings._getMissingProperties(mycpv, metadata)
2598 + if missing_properties:
2599 + allowed_tokens = set(["||", "(", ")"])
2600 + allowed_tokens.update(missing_properties)
2601 + properties_split = properties.split()
2602 + properties_split = [x for x in properties_split \
2603 + if x in allowed_tokens]
2604 + msg = properties_split[:]
2605 + msg.append("properties")
2606 + rValue.append(" ".join(msg))
2607 + except portage.exception.InvalidDependString as e:
2608 + rValue.append("PROPERTIES: "+str(e))
2609 +
2610 + # Only show KEYWORDS masks for installed packages
2611 + # if they're not masked for any other reason.
2612 + if kmask and (not installed or not rValue):
2613 + rValue.append(kmask+" keyword")
2614 +
2615 + return rValue
2616
2617 Copied: main/branches/prefix/pym/portage/util/movefile.py (from rev 15465, main/trunk/pym/portage/util/movefile.py)
2618 ===================================================================
2619 --- main/branches/prefix/pym/portage/util/movefile.py (rev 0)
2620 +++ main/branches/prefix/pym/portage/util/movefile.py 2010-02-27 19:32:48 UTC (rev 15483)
2621 @@ -0,0 +1,234 @@
2622 +# Copyright 2010 Gentoo Foundation
2623 +# Distributed under the terms of the GNU General Public License v2
2624 +# $Id$
2625 +
2626 +__all__ = ['movefile']
2627 +
2628 +import errno
2629 +import os as _os
2630 +import shutil as _shutil
2631 +import stat
2632 +
2633 +import portage
2634 +from portage import bsd_chflags, _encodings, _os_overrides, _selinux, \
2635 + _unicode_decode, _unicode_func_wrapper, _unicode_module_wrapper
2636 +from portage.const import MOVE_BINARY
2637 +from portage.localization import _
2638 +from portage.process import spawn
2639 +from portage.util import writemsg
2640 +
2641 +def movefile(src, dest, newmtime=None, sstat=None, mysettings=None,
2642 + hardlink_candidates=None, encoding=_encodings['fs']):
2643 + """moves a file from src to dest, preserving all permissions and attributes; mtime will
2644 + be preserved even when moving across filesystems. Returns true on success and false on
2645 + failure. Move is atomic."""
2646 + #print "movefile("+str(src)+","+str(dest)+","+str(newmtime)+","+str(sstat)+")"
2647 +
2648 + if mysettings is None:
2649 + mysettings = portage.settings
2650 +
2651 + selinux_enabled = mysettings.selinux_enabled()
2652 + if selinux_enabled:
2653 + selinux = _unicode_module_wrapper(_selinux, encoding=encoding)
2654 +
2655 + lchown = _unicode_func_wrapper(portage.data.lchown, encoding=encoding)
2656 + os = _unicode_module_wrapper(_os,
2657 + encoding=encoding, overrides=_os_overrides)
2658 + shutil = _unicode_module_wrapper(_shutil, encoding=encoding)
2659 +
2660 + try:
2661 + if not sstat:
2662 + sstat=os.lstat(src)
2663 +
2664 + except SystemExit as e:
2665 + raise
2666 + except Exception as e:
2667 + print(_("!!! Stating source file failed... movefile()"))
2668 + print("!!!",e)
2669 + return None
2670 +
2671 + destexists=1
2672 + try:
2673 + dstat=os.lstat(dest)
2674 + except (OSError, IOError):
2675 + dstat=os.lstat(os.path.dirname(dest))
2676 + destexists=0
2677 +
2678 + if bsd_chflags:
2679 + if destexists and dstat.st_flags != 0:
2680 + bsd_chflags.lchflags(dest, 0)
2681 + # Use normal stat/chflags for the parent since we want to
2682 + # follow any symlinks to the real parent directory.
2683 + pflags = os.stat(os.path.dirname(dest)).st_flags
2684 + if pflags != 0:
2685 + bsd_chflags.chflags(os.path.dirname(dest), 0)
2686 +
2687 + if destexists:
2688 + if stat.S_ISLNK(dstat[stat.ST_MODE]):
2689 + try:
2690 + os.unlink(dest)
2691 + destexists=0
2692 + except SystemExit as e:
2693 + raise
2694 + except Exception as e:
2695 + pass
2696 +
2697 + if stat.S_ISLNK(sstat[stat.ST_MODE]):
2698 + try:
2699 + target=os.readlink(src)
2700 + if mysettings and mysettings["D"]:
2701 + if target.find(mysettings["D"])==0:
2702 + target=target[len(mysettings["D"]):]
2703 + if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
2704 + os.unlink(dest)
2705 + if selinux_enabled:
2706 + selinux.symlink(target, dest, src)
2707 + else:
2708 + os.symlink(target,dest)
2709 + lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
2710 + # utime() only works on the target of a symlink, so it's not
2711 + # possible to perserve mtime on symlinks.
2712 + return os.lstat(dest)[stat.ST_MTIME]
2713 + except SystemExit as e:
2714 + raise
2715 + except Exception as e:
2716 + print(_("!!! failed to properly create symlink:"))
2717 + print("!!!",dest,"->",target)
2718 + print("!!!",e)
2719 + return None
2720 +
2721 + hardlinked = False
2722 + # Since identical files might be merged to multiple filesystems,
2723 + # so os.link() calls might fail for some paths, so try them all.
2724 + # For atomic replacement, first create the link as a temp file
2725 + # and them use os.rename() to replace the destination.
2726 + if hardlink_candidates:
2727 + head, tail = os.path.split(dest)
2728 + hardlink_tmp = os.path.join(head, ".%s._portage_merge_.%s" % \
2729 + (tail, os.getpid()))
2730 + try:
2731 + os.unlink(hardlink_tmp)
2732 + except OSError as e:
2733 + if e.errno != errno.ENOENT:
2734 + writemsg(_("!!! Failed to remove hardlink temp file: %s\n") % \
2735 + (hardlink_tmp,), noiselevel=-1)
2736 + writemsg("!!! %s\n" % (e,), noiselevel=-1)
2737 + return None
2738 + del e
2739 + for hardlink_src in hardlink_candidates:
2740 + try:
2741 + os.link(hardlink_src, hardlink_tmp)
2742 + except OSError:
2743 + continue
2744 + else:
2745 + try:
2746 + os.rename(hardlink_tmp, dest)
2747 + except OSError as e:
2748 + writemsg(_("!!! Failed to rename %s to %s\n") % \
2749 + (hardlink_tmp, dest), noiselevel=-1)
2750 + writemsg("!!! %s\n" % (e,), noiselevel=-1)
2751 + return None
2752 + hardlinked = True
2753 + break
2754 +
2755 + renamefailed=1
2756 + if hardlinked:
2757 + renamefailed = False
2758 + if not hardlinked and (selinux_enabled or sstat.st_dev == dstat.st_dev):
2759 + try:
2760 + if selinux_enabled:
2761 + selinux.rename(src, dest)
2762 + else:
2763 + os.rename(src,dest)
2764 + renamefailed=0
2765 + except OSError as e:
2766 + if e.errno != errno.EXDEV:
2767 + # Some random error.
2768 + print(_("!!! Failed to move %(src)s to %(dest)s") % {"src": src, "dest": dest})
2769 + print("!!!",e)
2770 + return None
2771 + # Invalid cross-device-link 'bind' mounted or actually Cross-Device
2772 + if renamefailed:
2773 + didcopy=0
2774 + if stat.S_ISREG(sstat[stat.ST_MODE]):
2775 + try: # For safety copy then move it over.
2776 + if selinux_enabled:
2777 + selinux.copyfile(src, dest + "#new")
2778 + selinux.rename(dest + "#new", dest)
2779 + else:
2780 + shutil.copyfile(src,dest+"#new")
2781 + os.rename(dest+"#new",dest)
2782 + didcopy=1
2783 + except SystemExit as e:
2784 + raise
2785 + except Exception as e:
2786 + print(_('!!! copy %(src)s -> %(dest)s failed.') % {"src": src, "dest": dest})
2787 + print("!!!",e)
2788 + return None
2789 + else:
2790 + #we don't yet handle special, so we need to fall back to /bin/mv
2791 + a = spawn([MOVE_BINARY, '-f', src, dest], env=os.environ)
2792 + if a != os.EX_OK:
2793 + writemsg(_("!!! Failed to move special file:\n"), noiselevel=-1)
2794 + writemsg(_("!!! '%(src)s' to '%(dest)s'\n") % \
2795 + {"src": _unicode_decode(src, encoding=encoding),
2796 + "dest": _unicode_decode(dest, encoding=encoding)}, noiselevel=-1)
2797 + writemsg("!!! %s\n" % a, noiselevel=-1)
2798 + return None # failure
2799 + try:
2800 + if didcopy:
2801 + if stat.S_ISLNK(sstat[stat.ST_MODE]):
2802 + lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
2803 + else:
2804 + os.chown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
2805 + os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
2806 + os.unlink(src)
2807 + except SystemExit as e:
2808 + raise
2809 + except Exception as e:
2810 + print(_("!!! Failed to chown/chmod/unlink in movefile()"))
2811 + print("!!!",dest)
2812 + print("!!!",e)
2813 + return None
2814 +
2815 + # Always use stat_obj[stat.ST_MTIME] for the integral timestamp which
2816 + # is returned, since the stat_obj.st_mtime float attribute rounds *up*
2817 + # if the nanosecond part of the timestamp is 999999881 ns or greater.
2818 + try:
2819 + if hardlinked:
2820 + newmtime = os.stat(dest)[stat.ST_MTIME]
2821 + else:
2822 + # Note: It is not possible to preserve nanosecond precision
2823 + # (supported in POSIX.1-2008 via utimensat) with the IEEE 754
2824 + # double precision float which only has a 53 bit significand.
2825 + if newmtime is not None:
2826 + os.utime(dest, (newmtime, newmtime))
2827 + else:
2828 + newmtime = sstat[stat.ST_MTIME]
2829 + if renamefailed:
2830 + # If rename succeeded then timestamps are automatically
2831 + # preserved with complete precision because the source
2832 + # and destination inode are the same. Otherwise, round
2833 + # down to the nearest whole second since python's float
2834 + # st_mtime cannot be used to preserve the st_mtim.tv_nsec
2835 + # field with complete precision. Note that we have to use
2836 + # stat_obj[stat.ST_MTIME] here because the float
2837 + # stat_obj.st_mtime rounds *up* sometimes.
2838 + os.utime(dest, (newmtime, newmtime))
2839 + except OSError:
2840 + # The utime can fail here with EPERM even though the move succeeded.
2841 + # Instead of failing, use stat to return the mtime if possible.
2842 + try:
2843 + newmtime = os.stat(dest)[stat.ST_MTIME]
2844 + except OSError as e:
2845 + writemsg(_("!!! Failed to stat in movefile()\n"), noiselevel=-1)
2846 + writemsg("!!! %s\n" % dest, noiselevel=-1)
2847 + writemsg("!!! %s\n" % str(e), noiselevel=-1)
2848 + return None
2849 +
2850 + if bsd_chflags:
2851 + # Restore the flags we saved before moving
2852 + if pflags:
2853 + bsd_chflags.chflags(os.path.dirname(dest), pflags)
2854 +
2855 + return newmtime