Gentoo Archives: gentoo-commits

From: "Fabian Groffen (grobian)" <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r13708 - main/branches/prefix/pym/_emerge
Date: Sat, 27 Jun 2009 13:35:45
Message-Id: E1MKY4B-0000GA-H3@stork.gentoo.org
1 Author: grobian
2 Date: 2009-06-27 13:35:38 +0000 (Sat, 27 Jun 2009)
3 New Revision: 13708
4
5 Added:
6 main/branches/prefix/pym/_emerge/BlockerDB.py
7 main/branches/prefix/pym/_emerge/FakeVartree.py
8 main/branches/prefix/pym/_emerge/MergeListItem.py
9 main/branches/prefix/pym/_emerge/MetadataRegen.py
10 main/branches/prefix/pym/_emerge/Package.py
11 main/branches/prefix/pym/_emerge/PackageCounters.py
12 main/branches/prefix/pym/_emerge/PackageUninstall.py
13 main/branches/prefix/pym/_emerge/RootConfig.py
14 main/branches/prefix/pym/_emerge/countdown.py
15 main/branches/prefix/pym/_emerge/emergelog.py
16 main/branches/prefix/pym/_emerge/format_size.py
17 main/branches/prefix/pym/_emerge/search.py
18 main/branches/prefix/pym/_emerge/show_invalid_depstring_notice.py
19 main/branches/prefix/pym/_emerge/unmerge.py
20 main/branches/prefix/pym/_emerge/userquery.py
21 main/branches/prefix/pym/_emerge/visible.py
22 Modified:
23 main/branches/prefix/pym/_emerge/__init__.py
24 Log:
25 Merged from trunk -r13668:13669
26
27 | 13669 | Bug #275047 - Split _emerge/__init__.py into smaller pieces |
28 | zmedico | (part 4). Thanks to Sebastian Mingramm (few) |
29 | | <s.mingramm@×××.de> for this patch. |
30
31
32 Copied: main/branches/prefix/pym/_emerge/BlockerDB.py (from rev 13669, main/trunk/pym/_emerge/BlockerDB.py)
33 ===================================================================
34 --- main/branches/prefix/pym/_emerge/BlockerDB.py (rev 0)
35 +++ main/branches/prefix/pym/_emerge/BlockerDB.py 2009-06-27 13:35:38 UTC (rev 13708)
36 @@ -0,0 +1,126 @@
37 +# for an explanation on this logic, see pym/_emerge/__init__.py
38 +import os
39 +import sys
40 +if os.environ.__contains__("PORTAGE_PYTHONPATH"):
41 + sys.path.insert(0, os.environ["PORTAGE_PYTHONPATH"])
42 +else:
43 + sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "pym"))
44 +import portage
45 +
46 +from portage import digraph
47 +from portage.sets.base import InternalPackageSet
48 +
49 +from _emerge.BlockerCache import BlockerCache
50 +from _emerge.FakeVartree import FakeVartree
51 +from _emerge.show_invalid_depstring_notice import show_invalid_depstring_notice
52 +
53 +class BlockerDB(object):
54 +
55 + def __init__(self, root_config):
56 + self._root_config = root_config
57 + self._vartree = root_config.trees["vartree"]
58 + self._portdb = root_config.trees["porttree"].dbapi
59 +
60 + self._dep_check_trees = None
61 + self._fake_vartree = None
62 +
63 + def _get_fake_vartree(self, acquire_lock=0):
64 + fake_vartree = self._fake_vartree
65 + if fake_vartree is None:
66 + fake_vartree = FakeVartree(self._root_config,
67 + acquire_lock=acquire_lock)
68 + self._fake_vartree = fake_vartree
69 + self._dep_check_trees = { self._vartree.root : {
70 + "porttree" : fake_vartree,
71 + "vartree" : fake_vartree,
72 + }}
73 + else:
74 + fake_vartree.sync(acquire_lock=acquire_lock)
75 + return fake_vartree
76 +
77 + def findInstalledBlockers(self, new_pkg, acquire_lock=0):
78 + blocker_cache = BlockerCache(self._vartree.root, self._vartree.dbapi)
79 + dep_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
80 + settings = self._vartree.settings
81 + stale_cache = set(blocker_cache)
82 + fake_vartree = self._get_fake_vartree(acquire_lock=acquire_lock)
83 + dep_check_trees = self._dep_check_trees
84 + vardb = fake_vartree.dbapi
85 + installed_pkgs = list(vardb)
86 +
87 + for inst_pkg in installed_pkgs:
88 + stale_cache.discard(inst_pkg.cpv)
89 + cached_blockers = blocker_cache.get(inst_pkg.cpv)
90 + if cached_blockers is not None and \
91 + cached_blockers.counter != long(inst_pkg.metadata["COUNTER"]):
92 + cached_blockers = None
93 + if cached_blockers is not None:
94 + blocker_atoms = cached_blockers.atoms
95 + else:
96 + # Use aux_get() to trigger FakeVartree global
97 + # updates on *DEPEND when appropriate.
98 + depstr = " ".join(vardb.aux_get(inst_pkg.cpv, dep_keys))
99 + try:
100 + portage.dep._dep_check_strict = False
101 + success, atoms = portage.dep_check(depstr,
102 + vardb, settings, myuse=inst_pkg.use.enabled,
103 + trees=dep_check_trees, myroot=inst_pkg.root)
104 + finally:
105 + portage.dep._dep_check_strict = True
106 + if not success:
107 + pkg_location = os.path.join(inst_pkg.root,
108 + portage.VDB_PATH, inst_pkg.category, inst_pkg.pf)
109 + portage.writemsg("!!! %s/*DEPEND: %s\n" % \
110 + (pkg_location, atoms), noiselevel=-1)
111 + continue
112 +
113 + blocker_atoms = [atom for atom in atoms \
114 + if atom.startswith("!")]
115 + blocker_atoms.sort()
116 + counter = long(inst_pkg.metadata["COUNTER"])
117 + blocker_cache[inst_pkg.cpv] = \
118 + blocker_cache.BlockerData(counter, blocker_atoms)
119 + for cpv in stale_cache:
120 + del blocker_cache[cpv]
121 + blocker_cache.flush()
122 +
123 + blocker_parents = digraph()
124 + blocker_atoms = []
125 + for pkg in installed_pkgs:
126 + for blocker_atom in blocker_cache[pkg.cpv].atoms:
127 + blocker_atom = blocker_atom.lstrip("!")
128 + blocker_atoms.append(blocker_atom)
129 + blocker_parents.add(blocker_atom, pkg)
130 +
131 + blocker_atoms = InternalPackageSet(initial_atoms=blocker_atoms)
132 + blocking_pkgs = set()
133 + for atom in blocker_atoms.iterAtomsForPackage(new_pkg):
134 + blocking_pkgs.update(blocker_parents.parent_nodes(atom))
135 +
136 + # Check for blockers in the other direction.
137 + depstr = " ".join(new_pkg.metadata[k] for k in dep_keys)
138 + try:
139 + portage.dep._dep_check_strict = False
140 + success, atoms = portage.dep_check(depstr,
141 + vardb, settings, myuse=new_pkg.use.enabled,
142 + trees=dep_check_trees, myroot=new_pkg.root)
143 + finally:
144 + portage.dep._dep_check_strict = True
145 + if not success:
146 + # We should never get this far with invalid deps.
147 + show_invalid_depstring_notice(new_pkg, depstr, atoms)
148 + assert False
149 +
150 + blocker_atoms = [atom.lstrip("!") for atom in atoms \
151 + if atom[:1] == "!"]
152 + if blocker_atoms:
153 + blocker_atoms = InternalPackageSet(initial_atoms=blocker_atoms)
154 + for inst_pkg in installed_pkgs:
155 + try:
156 + blocker_atoms.iterAtomsForPackage(inst_pkg).next()
157 + except (portage.exception.InvalidDependString, StopIteration):
158 + continue
159 + blocking_pkgs.add(inst_pkg)
160 +
161 + return blocking_pkgs
162 +
163
164 Copied: main/branches/prefix/pym/_emerge/FakeVartree.py (from rev 13669, main/trunk/pym/_emerge/FakeVartree.py)
165 ===================================================================
166 --- main/branches/prefix/pym/_emerge/FakeVartree.py (rev 0)
167 +++ main/branches/prefix/pym/_emerge/FakeVartree.py 2009-06-27 13:35:38 UTC (rev 13708)
168 @@ -0,0 +1,235 @@
169 +import os
170 +from itertools import izip
171 +
172 +# for an explanation on this logic, see pym/_emerge/__init__.py
173 +import sys
174 +if os.environ.__contains__("PORTAGE_PYTHONPATH"):
175 + sys.path.insert(0, os.environ["PORTAGE_PYTHONPATH"])
176 +else:
177 + sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "pym"))
178 +import portage
179 +
180 +from _emerge.Package import Package
181 +from _emerge.PackageVirtualDbapi import PackageVirtualDbapi
182 +
183 +class FakeVartree(portage.vartree):
184 + """This is implements an in-memory copy of a vartree instance that provides
185 + all the interfaces required for use by the depgraph. The vardb is locked
186 + during the constructor call just long enough to read a copy of the
187 + installed package information. This allows the depgraph to do it's
188 + dependency calculations without holding a lock on the vardb. It also
189 + allows things like vardb global updates to be done in memory so that the
190 + user doesn't necessarily need write access to the vardb in cases where
191 + global updates are necessary (updates are performed when necessary if there
192 + is not a matching ebuild in the tree)."""
193 + def __init__(self, root_config, pkg_cache=None, acquire_lock=1):
194 + self._root_config = root_config
195 + if pkg_cache is None:
196 + pkg_cache = {}
197 + real_vartree = root_config.trees["vartree"]
198 + portdb = root_config.trees["porttree"].dbapi
199 + self.root = real_vartree.root
200 + self.settings = real_vartree.settings
201 + mykeys = list(real_vartree.dbapi._aux_cache_keys)
202 + if "_mtime_" not in mykeys:
203 + mykeys.append("_mtime_")
204 + self._db_keys = mykeys
205 + self._pkg_cache = pkg_cache
206 + self.dbapi = PackageVirtualDbapi(real_vartree.settings)
207 + vdb_path = os.path.join(self.root, portage.VDB_PATH)
208 + try:
209 + # At least the parent needs to exist for the lock file.
210 + portage.util.ensure_dirs(vdb_path)
211 + except portage.exception.PortageException:
212 + pass
213 + vdb_lock = None
214 + try:
215 + if acquire_lock and os.access(vdb_path, os.W_OK):
216 + vdb_lock = portage.locks.lockdir(vdb_path)
217 + real_dbapi = real_vartree.dbapi
218 + slot_counters = {}
219 + for cpv in real_dbapi.cpv_all():
220 + cache_key = ("installed", self.root, cpv, "nomerge")
221 + pkg = self._pkg_cache.get(cache_key)
222 + if pkg is not None:
223 + metadata = pkg.metadata
224 + else:
225 + metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
226 + myslot = metadata["SLOT"]
227 + mycp = portage.dep_getkey(cpv)
228 + myslot_atom = "%s:%s" % (mycp, myslot)
229 + try:
230 + mycounter = long(metadata["COUNTER"])
231 + except ValueError:
232 + mycounter = 0
233 + metadata["COUNTER"] = str(mycounter)
234 + other_counter = slot_counters.get(myslot_atom, None)
235 + if other_counter is not None:
236 + if other_counter > mycounter:
237 + continue
238 + slot_counters[myslot_atom] = mycounter
239 + if pkg is None:
240 + pkg = Package(built=True, cpv=cpv,
241 + installed=True, metadata=metadata,
242 + root_config=root_config, type_name="installed")
243 + self._pkg_cache[pkg] = pkg
244 + self.dbapi.cpv_inject(pkg)
245 + real_dbapi.flush_cache()
246 + finally:
247 + if vdb_lock:
248 + portage.locks.unlockdir(vdb_lock)
249 + # Populate the old-style virtuals using the cached values.
250 + if not self.settings.treeVirtuals:
251 + self.settings.treeVirtuals = portage.util.map_dictlist_vals(
252 + portage.getCPFromCPV, self.get_all_provides())
253 +
254 + # Intialize variables needed for lazy cache pulls of the live ebuild
255 + # metadata. This ensures that the vardb lock is released ASAP, without
256 + # being delayed in case cache generation is triggered.
257 + self._aux_get = self.dbapi.aux_get
258 + self.dbapi.aux_get = self._aux_get_wrapper
259 + self._match = self.dbapi.match
260 + self.dbapi.match = self._match_wrapper
261 + self._aux_get_history = set()
262 + self._portdb_keys = ["EAPI", "DEPEND", "RDEPEND", "PDEPEND"]
263 + self._portdb = portdb
264 + self._global_updates = None
265 +
266 + def _match_wrapper(self, cpv, use_cache=1):
267 + """
268 + Make sure the metadata in Package instances gets updated for any
269 + cpv that is returned from a match() call, since the metadata can
270 + be accessed directly from the Package instance instead of via
271 + aux_get().
272 + """
273 + matches = self._match(cpv, use_cache=use_cache)
274 + for cpv in matches:
275 + if cpv in self._aux_get_history:
276 + continue
277 + self._aux_get_wrapper(cpv, [])
278 + return matches
279 +
280 + def _aux_get_wrapper(self, pkg, wants):
281 + if pkg in self._aux_get_history:
282 + return self._aux_get(pkg, wants)
283 + self._aux_get_history.add(pkg)
284 + try:
285 + # Use the live ebuild metadata if possible.
286 + live_metadata = dict(izip(self._portdb_keys,
287 + self._portdb.aux_get(pkg, self._portdb_keys)))
288 + if not portage.eapi_is_supported(live_metadata["EAPI"]):
289 + raise KeyError(pkg)
290 + self.dbapi.aux_update(pkg, live_metadata)
291 + except (KeyError, portage.exception.PortageException):
292 + if self._global_updates is None:
293 + self._global_updates = \
294 + grab_global_updates(self._portdb.porttree_root)
295 + perform_global_updates(
296 + pkg, self.dbapi, self._global_updates)
297 + return self._aux_get(pkg, wants)
298 +
299 + def sync(self, acquire_lock=1):
300 + """
301 + Call this method to synchronize state with the real vardb
302 + after one or more packages may have been installed or
303 + uninstalled.
304 + """
305 + vdb_path = os.path.join(self.root, portage.VDB_PATH)
306 + try:
307 + # At least the parent needs to exist for the lock file.
308 + portage.util.ensure_dirs(vdb_path)
309 + except portage.exception.PortageException:
310 + pass
311 + vdb_lock = None
312 + try:
313 + if acquire_lock and os.access(vdb_path, os.W_OK):
314 + vdb_lock = portage.locks.lockdir(vdb_path)
315 + self._sync()
316 + finally:
317 + if vdb_lock:
318 + portage.locks.unlockdir(vdb_lock)
319 +
320 + def _sync(self):
321 +
322 + real_vardb = self._root_config.trees["vartree"].dbapi
323 + current_cpv_set = frozenset(real_vardb.cpv_all())
324 + pkg_vardb = self.dbapi
325 + aux_get_history = self._aux_get_history
326 +
327 + # Remove any packages that have been uninstalled.
328 + for pkg in list(pkg_vardb):
329 + if pkg.cpv not in current_cpv_set:
330 + pkg_vardb.cpv_remove(pkg)
331 + aux_get_history.discard(pkg.cpv)
332 +
333 + # Validate counters and timestamps.
334 + slot_counters = {}
335 + root = self.root
336 + validation_keys = ["COUNTER", "_mtime_"]
337 + for cpv in current_cpv_set:
338 +
339 + pkg_hash_key = ("installed", root, cpv, "nomerge")
340 + pkg = pkg_vardb.get(pkg_hash_key)
341 + if pkg is not None:
342 + counter, mtime = real_vardb.aux_get(cpv, validation_keys)
343 + try:
344 + counter = long(counter)
345 + except ValueError:
346 + counter = 0
347 +
348 + if counter != pkg.counter or \
349 + mtime != pkg.mtime:
350 + pkg_vardb.cpv_remove(pkg)
351 + aux_get_history.discard(pkg.cpv)
352 + pkg = None
353 +
354 + if pkg is None:
355 + pkg = self._pkg(cpv)
356 +
357 + other_counter = slot_counters.get(pkg.slot_atom)
358 + if other_counter is not None:
359 + if other_counter > pkg.counter:
360 + continue
361 +
362 + slot_counters[pkg.slot_atom] = pkg.counter
363 + pkg_vardb.cpv_inject(pkg)
364 +
365 + real_vardb.flush_cache()
366 +
367 + def _pkg(self, cpv):
368 + root_config = self._root_config
369 + real_vardb = root_config.trees["vartree"].dbapi
370 + pkg = Package(cpv=cpv, installed=True,
371 + metadata=izip(self._db_keys,
372 + real_vardb.aux_get(cpv, self._db_keys)),
373 + root_config=root_config,
374 + type_name="installed")
375 +
376 + try:
377 + mycounter = long(pkg.metadata["COUNTER"])
378 + except ValueError:
379 + mycounter = 0
380 + pkg.metadata["COUNTER"] = str(mycounter)
381 +
382 + return pkg
383 +
384 +def grab_global_updates(portdir):
385 + from portage.update import grab_updates, parse_updates
386 + updpath = os.path.join(portdir, "profiles", "updates")
387 + try:
388 + rawupdates = grab_updates(updpath)
389 + except portage.exception.DirectoryNotFound:
390 + rawupdates = []
391 + upd_commands = []
392 + for mykey, mystat, mycontent in rawupdates:
393 + commands, errors = parse_updates(mycontent)
394 + upd_commands.extend(commands)
395 + return upd_commands
396 +
397 +def perform_global_updates(mycpv, mydb, mycommands):
398 + from portage.update import update_dbentries
399 + aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
400 + aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
401 + updates = update_dbentries(mycommands, aux_dict)
402 + if updates:
403 + mydb.aux_update(mycpv, updates)
404
405 Copied: main/branches/prefix/pym/_emerge/MergeListItem.py (from rev 13669, main/trunk/pym/_emerge/MergeListItem.py)
406 ===================================================================
407 --- main/branches/prefix/pym/_emerge/MergeListItem.py (rev 0)
408 +++ main/branches/prefix/pym/_emerge/MergeListItem.py 2009-06-27 13:35:38 UTC (rev 13708)
409 @@ -0,0 +1,146 @@
410 +import os
411 +
412 +from portage.output import colorize
413 +
414 +from _emerge.Binpkg import Binpkg
415 +from _emerge.CompositeTask import CompositeTask
416 +from _emerge.EbuildBuild import EbuildBuild
417 +from _emerge.PackageUninstall import PackageUninstall
418 +
419 +class MergeListItem(CompositeTask):
420 +
421 + """
422 + TODO: For parallel scheduling, everything here needs asynchronous
423 + execution support (start, poll, and wait methods).
424 + """
425 +
426 + __slots__ = ("args_set",
427 + "binpkg_opts", "build_opts", "config_pool", "emerge_opts",
428 + "find_blockers", "logger", "mtimedb", "pkg",
429 + "pkg_count", "pkg_to_replace", "prefetcher",
430 + "settings", "statusMessage", "world_atom") + \
431 + ("_install_task",)
432 +
433 + def _start(self):
434 +
435 + pkg = self.pkg
436 + build_opts = self.build_opts
437 +
438 + if pkg.installed:
439 + # uninstall, executed by self.merge()
440 + self.returncode = os.EX_OK
441 + self.wait()
442 + return
443 +
444 + args_set = self.args_set
445 + find_blockers = self.find_blockers
446 + logger = self.logger
447 + mtimedb = self.mtimedb
448 + pkg_count = self.pkg_count
449 + scheduler = self.scheduler
450 + settings = self.settings
451 + world_atom = self.world_atom
452 + ldpath_mtimes = mtimedb["ldpath"]
453 +
454 + action_desc = "Emerging"
455 + preposition = "for"
456 + if pkg.type_name == "binary":
457 + action_desc += " binary"
458 +
459 + if build_opts.fetchonly:
460 + action_desc = "Fetching"
461 +
462 + msg = "%s (%s of %s) %s" % \
463 + (action_desc,
464 + colorize("MERGE_LIST_PROGRESS", str(pkg_count.curval)),
465 + colorize("MERGE_LIST_PROGRESS", str(pkg_count.maxval)),
466 + colorize("GOOD", pkg.cpv))
467 +
468 + portdb = pkg.root_config.trees["porttree"].dbapi
469 + portdir_repo_name = portdb._repository_map.get(portdb.porttree_root)
470 + if portdir_repo_name:
471 + pkg_repo_name = pkg.metadata.get("repository")
472 + if pkg_repo_name != portdir_repo_name:
473 + if not pkg_repo_name:
474 + pkg_repo_name = "unknown repo"
475 + msg += " from %s" % pkg_repo_name
476 +
477 + if pkg.root != "/":
478 + msg += " %s %s" % (preposition, pkg.root)
479 +
480 + if not build_opts.pretend:
481 + self.statusMessage(msg)
482 + logger.log(" >>> emerge (%s of %s) %s to %s" % \
483 + (pkg_count.curval, pkg_count.maxval, pkg.cpv, pkg.root))
484 +
485 + if pkg.type_name == "ebuild":
486 +
487 + build = EbuildBuild(args_set=args_set,
488 + background=self.background,
489 + config_pool=self.config_pool,
490 + find_blockers=find_blockers,
491 + ldpath_mtimes=ldpath_mtimes, logger=logger,
492 + opts=build_opts, pkg=pkg, pkg_count=pkg_count,
493 + prefetcher=self.prefetcher, scheduler=scheduler,
494 + settings=settings, world_atom=world_atom)
495 +
496 + self._install_task = build
497 + self._start_task(build, self._default_final_exit)
498 + return
499 +
500 + elif pkg.type_name == "binary":
501 +
502 + binpkg = Binpkg(background=self.background,
503 + find_blockers=find_blockers,
504 + ldpath_mtimes=ldpath_mtimes, logger=logger,
505 + opts=self.binpkg_opts, pkg=pkg, pkg_count=pkg_count,
506 + prefetcher=self.prefetcher, settings=settings,
507 + scheduler=scheduler, world_atom=world_atom)
508 +
509 + self._install_task = binpkg
510 + self._start_task(binpkg, self._default_final_exit)
511 + return
512 +
513 + def _poll(self):
514 + self._install_task.poll()
515 + return self.returncode
516 +
517 + def _wait(self):
518 + self._install_task.wait()
519 + return self.returncode
520 +
521 + def merge(self):
522 +
523 + pkg = self.pkg
524 + build_opts = self.build_opts
525 + find_blockers = self.find_blockers
526 + logger = self.logger
527 + mtimedb = self.mtimedb
528 + pkg_count = self.pkg_count
529 + prefetcher = self.prefetcher
530 + scheduler = self.scheduler
531 + settings = self.settings
532 + world_atom = self.world_atom
533 + ldpath_mtimes = mtimedb["ldpath"]
534 +
535 + if pkg.installed:
536 + if not (build_opts.buildpkgonly or \
537 + build_opts.fetchonly or build_opts.pretend):
538 +
539 + uninstall = PackageUninstall(background=self.background,
540 + ldpath_mtimes=ldpath_mtimes, opts=self.emerge_opts,
541 + pkg=pkg, scheduler=scheduler, settings=settings)
542 +
543 + uninstall.start()
544 + retval = uninstall.wait()
545 + if retval != os.EX_OK:
546 + return retval
547 + return os.EX_OK
548 +
549 + if build_opts.fetchonly or \
550 + build_opts.buildpkgonly:
551 + return self.returncode
552 +
553 + retval = self._install_task.install()
554 + return retval
555 +
556
557 Copied: main/branches/prefix/pym/_emerge/MetadataRegen.py (from rev 13669, main/trunk/pym/_emerge/MetadataRegen.py)
558 ===================================================================
559 --- main/branches/prefix/pym/_emerge/MetadataRegen.py (rev 0)
560 +++ main/branches/prefix/pym/_emerge/MetadataRegen.py 2009-06-27 13:35:38 UTC (rev 13708)
561 @@ -0,0 +1,169 @@
562 +# for an explanation on this logic, see pym/_emerge/__init__.py
563 +import os
564 +import sys
565 +if os.environ.__contains__("PORTAGE_PYTHONPATH"):
566 + sys.path.insert(0, os.environ["PORTAGE_PYTHONPATH"])
567 +else:
568 + sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "pym"))
569 +import portage
570 +
571 +from _emerge.EbuildMetadataPhase import EbuildMetadataPhase
572 +from _emerge.PollScheduler import PollScheduler
573 +
574 +class MetadataRegen(PollScheduler):
575 +
576 + def __init__(self, portdb, cp_iter=None, consumer=None,
577 + max_jobs=None, max_load=None):
578 + PollScheduler.__init__(self)
579 + self._portdb = portdb
580 + self._global_cleanse = False
581 + if cp_iter is None:
582 + cp_iter = self._iter_every_cp()
583 + # We can globally cleanse stale cache only if we
584 + # iterate over every single cp.
585 + self._global_cleanse = True
586 + self._cp_iter = cp_iter
587 + self._consumer = consumer
588 +
589 + if max_jobs is None:
590 + max_jobs = 1
591 +
592 + self._max_jobs = max_jobs
593 + self._max_load = max_load
594 + self._sched_iface = self._sched_iface_class(
595 + register=self._register,
596 + schedule=self._schedule_wait,
597 + unregister=self._unregister)
598 +
599 + self._valid_pkgs = set()
600 + self._cp_set = set()
601 + self._process_iter = self._iter_metadata_processes()
602 + self.returncode = os.EX_OK
603 + self._error_count = 0
604 +
605 + def _iter_every_cp(self):
606 + every_cp = self._portdb.cp_all()
607 + every_cp.sort(reverse=True)
608 + try:
609 + while True:
610 + yield every_cp.pop()
611 + except IndexError:
612 + pass
613 +
614 + def _iter_metadata_processes(self):
615 + portdb = self._portdb
616 + valid_pkgs = self._valid_pkgs
617 + cp_set = self._cp_set
618 + consumer = self._consumer
619 +
620 + for cp in self._cp_iter:
621 + cp_set.add(cp)
622 + portage.writemsg_stdout("Processing %s\n" % cp)
623 + cpv_list = portdb.cp_list(cp)
624 + for cpv in cpv_list:
625 + valid_pkgs.add(cpv)
626 + ebuild_path, repo_path = portdb.findname2(cpv)
627 + metadata, st, emtime = portdb._pull_valid_cache(
628 + cpv, ebuild_path, repo_path)
629 + if metadata is not None:
630 + if consumer is not None:
631 + consumer(cpv, ebuild_path,
632 + repo_path, metadata)
633 + continue
634 +
635 + yield EbuildMetadataPhase(cpv=cpv, ebuild_path=ebuild_path,
636 + ebuild_mtime=emtime,
637 + metadata_callback=portdb._metadata_callback,
638 + portdb=portdb, repo_path=repo_path,
639 + settings=portdb.doebuild_settings)
640 +
641 + def run(self):
642 +
643 + portdb = self._portdb
644 + from portage.cache.cache_errors import CacheError
645 + dead_nodes = {}
646 +
647 + while self._schedule():
648 + self._poll_loop()
649 +
650 + while self._jobs:
651 + self._poll_loop()
652 +
653 + if self._global_cleanse:
654 + for mytree in portdb.porttrees:
655 + try:
656 + dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
657 + except CacheError, e:
658 + portage.writemsg("Error listing cache entries for " + \
659 + "'%s': %s, continuing...\n" % (mytree, e),
660 + noiselevel=-1)
661 + del e
662 + dead_nodes = None
663 + break
664 + else:
665 + cp_set = self._cp_set
666 + cpv_getkey = portage.cpv_getkey
667 + for mytree in portdb.porttrees:
668 + try:
669 + dead_nodes[mytree] = set(cpv for cpv in \
670 + portdb.auxdb[mytree].iterkeys() \
671 + if cpv_getkey(cpv) in cp_set)
672 + except CacheError, e:
673 + portage.writemsg("Error listing cache entries for " + \
674 + "'%s': %s, continuing...\n" % (mytree, e),
675 + noiselevel=-1)
676 + del e
677 + dead_nodes = None
678 + break
679 +
680 + if dead_nodes:
681 + for y in self._valid_pkgs:
682 + for mytree in portdb.porttrees:
683 + if portdb.findname2(y, mytree=mytree)[0]:
684 + dead_nodes[mytree].discard(y)
685 +
686 + for mytree, nodes in dead_nodes.iteritems():
687 + auxdb = portdb.auxdb[mytree]
688 + for y in nodes:
689 + try:
690 + del auxdb[y]
691 + except (KeyError, CacheError):
692 + pass
693 +
694 + def _schedule_tasks(self):
695 + """
696 + @rtype: bool
697 + @returns: True if there may be remaining tasks to schedule,
698 + False otherwise.
699 + """
700 + while self._can_add_job():
701 + try:
702 + metadata_process = self._process_iter.next()
703 + except StopIteration:
704 + return False
705 +
706 + self._jobs += 1
707 + metadata_process.scheduler = self._sched_iface
708 + metadata_process.addExitListener(self._metadata_exit)
709 + metadata_process.start()
710 + return True
711 +
712 + def _metadata_exit(self, metadata_process):
713 + self._jobs -= 1
714 + if metadata_process.returncode != os.EX_OK:
715 + self.returncode = 1
716 + self._error_count += 1
717 + self._valid_pkgs.discard(metadata_process.cpv)
718 + portage.writemsg("Error processing %s, continuing...\n" % \
719 + (metadata_process.cpv,), noiselevel=-1)
720 +
721 + if self._consumer is not None:
722 + # On failure, still notify the consumer (in this case the metadata
723 + # argument is None).
724 + self._consumer(metadata_process.cpv,
725 + metadata_process.ebuild_path,
726 + metadata_process.repo_path,
727 + metadata_process.metadata)
728 +
729 + self._schedule()
730 +
731
732 Copied: main/branches/prefix/pym/_emerge/Package.py (from rev 13669, main/trunk/pym/_emerge/Package.py)
733 ===================================================================
734 --- main/branches/prefix/pym/_emerge/Package.py (rev 0)
735 +++ main/branches/prefix/pym/_emerge/Package.py 2009-06-27 13:35:38 UTC (rev 13708)
736 @@ -0,0 +1,187 @@
737 +import re
738 +from itertools import chain
739 +
740 +# for an explanation on this logic, see pym/_emerge/__init__.py
741 +import os
742 +import sys
743 +if os.environ.__contains__("PORTAGE_PYTHONPATH"):
744 + sys.path.insert(0, os.environ["PORTAGE_PYTHONPATH"])
745 +else:
746 + sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "pym"))
747 +import portage
748 +
749 +from portage.cache.mappings import slot_dict_class
750 +
751 +from _emerge.Task import Task
752 +
753 +class Package(Task):
754 +
755 + __hash__ = Task.__hash__
756 + __slots__ = ("built", "cpv", "depth",
757 + "installed", "metadata", "onlydeps", "operation",
758 + "root_config", "type_name",
759 + "category", "counter", "cp", "cpv_split",
760 + "inherited", "iuse", "mtime",
761 + "pf", "pv_split", "root", "slot", "slot_atom", "use")
762 +
763 + metadata_keys = [
764 + "CHOST", "COUNTER", "DEPEND", "EAPI",
765 + "INHERITED", "IUSE", "KEYWORDS",
766 + "LICENSE", "PDEPEND", "PROVIDE", "RDEPEND",
767 + "repository", "PROPERTIES", "RESTRICT", "SLOT", "USE", "_mtime_",
768 + "EPREFIX" ]
769 +
770 + def __init__(self, **kwargs):
771 + Task.__init__(self, **kwargs)
772 + self.root = self.root_config.root
773 + self.metadata = _PackageMetadataWrapper(self, self.metadata)
774 + self.cp = portage.cpv_getkey(self.cpv)
775 + slot = self.slot
776 + if not slot:
777 + # Avoid an InvalidAtom exception when creating slot_atom.
778 + # This package instance will be masked due to empty SLOT.
779 + slot = '0'
780 + self.slot_atom = portage.dep.Atom("%s:%s" % (self.cp, slot))
781 + self.category, self.pf = portage.catsplit(self.cpv)
782 + self.cpv_split = portage.catpkgsplit(self.cpv)
783 + self.pv_split = self.cpv_split[1:]
784 +
785 + class _use(object):
786 +
787 + __slots__ = ("__weakref__", "enabled")
788 +
789 + def __init__(self, use):
790 + self.enabled = frozenset(use)
791 +
792 + class _iuse(object):
793 +
794 + __slots__ = ("__weakref__", "all", "enabled", "disabled", "iuse_implicit", "regex", "tokens")
795 +
796 + def __init__(self, tokens, iuse_implicit):
797 + self.tokens = tuple(tokens)
798 + self.iuse_implicit = iuse_implicit
799 + enabled = []
800 + disabled = []
801 + other = []
802 + for x in tokens:
803 + prefix = x[:1]
804 + if prefix == "+":
805 + enabled.append(x[1:])
806 + elif prefix == "-":
807 + disabled.append(x[1:])
808 + else:
809 + other.append(x)
810 + self.enabled = frozenset(enabled)
811 + self.disabled = frozenset(disabled)
812 + self.all = frozenset(chain(enabled, disabled, other))
813 +
814 + def __getattribute__(self, name):
815 + if name == "regex":
816 + try:
817 + return object.__getattribute__(self, "regex")
818 + except AttributeError:
819 + all = object.__getattribute__(self, "all")
820 + iuse_implicit = object.__getattribute__(self, "iuse_implicit")
821 + # Escape anything except ".*" which is supposed
822 + # to pass through from _get_implicit_iuse()
823 + regex = (re.escape(x) for x in chain(all, iuse_implicit))
824 + regex = "^(%s)$" % "|".join(regex)
825 + regex = regex.replace("\\.\\*", ".*")
826 + self.regex = re.compile(regex)
827 + return object.__getattribute__(self, name)
828 +
829 + def _get_hash_key(self):
830 + hash_key = getattr(self, "_hash_key", None)
831 + if hash_key is None:
832 + if self.operation is None:
833 + self.operation = "merge"
834 + if self.onlydeps or self.installed:
835 + self.operation = "nomerge"
836 + self._hash_key = \
837 + (self.type_name, self.root, self.cpv, self.operation)
838 + return self._hash_key
839 +
840 + def __lt__(self, other):
841 + if other.cp != self.cp:
842 + return False
843 + if portage.pkgcmp(self.pv_split, other.pv_split) < 0:
844 + return True
845 + return False
846 +
847 + def __le__(self, other):
848 + if other.cp != self.cp:
849 + return False
850 + if portage.pkgcmp(self.pv_split, other.pv_split) <= 0:
851 + return True
852 + return False
853 +
854 + def __gt__(self, other):
855 + if other.cp != self.cp:
856 + return False
857 + if portage.pkgcmp(self.pv_split, other.pv_split) > 0:
858 + return True
859 + return False
860 +
861 + def __ge__(self, other):
862 + if other.cp != self.cp:
863 + return False
864 + if portage.pkgcmp(self.pv_split, other.pv_split) >= 0:
865 + return True
866 + return False
867 +
868 +_all_metadata_keys = set(x for x in portage.auxdbkeys \
869 + if not x.startswith("UNUSED_"))
870 +_all_metadata_keys.discard("CDEPEND")
871 +_all_metadata_keys.update(Package.metadata_keys)
872 +
873 +_PackageMetadataWrapperBase = slot_dict_class(_all_metadata_keys)
874 +
875 +class _PackageMetadataWrapper(_PackageMetadataWrapperBase):
876 + """
877 + Detect metadata updates and synchronize Package attributes.
878 + """
879 +
880 + __slots__ = ("_pkg",)
881 + _wrapped_keys = frozenset(
882 + ["COUNTER", "INHERITED", "IUSE", "SLOT", "USE", "_mtime_"])
883 +
884 + def __init__(self, pkg, metadata):
885 + _PackageMetadataWrapperBase.__init__(self)
886 + self._pkg = pkg
887 + self.update(metadata)
888 +
889 + def __setitem__(self, k, v):
890 + _PackageMetadataWrapperBase.__setitem__(self, k, v)
891 + if k in self._wrapped_keys:
892 + getattr(self, "_set_" + k.lower())(k, v)
893 +
894 + def _set_inherited(self, k, v):
895 + if isinstance(v, basestring):
896 + v = frozenset(v.split())
897 + self._pkg.inherited = v
898 +
899 + def _set_iuse(self, k, v):
900 + self._pkg.iuse = self._pkg._iuse(
901 + v.split(), self._pkg.root_config.iuse_implicit)
902 +
903 + def _set_slot(self, k, v):
904 + self._pkg.slot = v
905 +
906 + def _set_use(self, k, v):
907 + self._pkg.use = self._pkg._use(v.split())
908 +
909 + def _set_counter(self, k, v):
910 + if isinstance(v, basestring):
911 + try:
912 + v = long(v.strip())
913 + except ValueError:
914 + v = 0
915 + self._pkg.counter = v
916 +
917 + def _set__mtime_(self, k, v):
918 + if isinstance(v, basestring):
919 + try:
920 + v = long(v.strip())
921 + except ValueError:
922 + v = 0
923 + self._pkg.mtime = v
924
925 Copied: main/branches/prefix/pym/_emerge/PackageCounters.py (from rev 13669, main/trunk/pym/_emerge/PackageCounters.py)
926 ===================================================================
927 --- main/branches/prefix/pym/_emerge/PackageCounters.py (rev 0)
928 +++ main/branches/prefix/pym/_emerge/PackageCounters.py 2009-06-27 13:35:38 UTC (rev 13708)
929 @@ -0,0 +1,77 @@
930 +from portage.output import colorize, create_color_func
931 +bad = create_color_func("BAD")
932 +
933 +from _emerge.format_size import format_size
934 +
935 +class PackageCounters(object):
936 +
937 + def __init__(self):
938 + self.upgrades = 0
939 + self.downgrades = 0
940 + self.new = 0
941 + self.newslot = 0
942 + self.reinst = 0
943 + self.uninst = 0
944 + self.blocks = 0
945 + self.blocks_satisfied = 0
946 + self.totalsize = 0
947 + self.restrict_fetch = 0
948 + self.restrict_fetch_satisfied = 0
949 + self.interactive = 0
950 +
951 + def __str__(self):
952 + total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
953 + myoutput = []
954 + details = []
955 + myoutput.append("Total: %s package" % total_installs)
956 + if total_installs != 1:
957 + myoutput.append("s")
958 + if total_installs != 0:
959 + myoutput.append(" (")
960 + if self.upgrades > 0:
961 + details.append("%s upgrade" % self.upgrades)
962 + if self.upgrades > 1:
963 + details[-1] += "s"
964 + if self.downgrades > 0:
965 + details.append("%s downgrade" % self.downgrades)
966 + if self.downgrades > 1:
967 + details[-1] += "s"
968 + if self.new > 0:
969 + details.append("%s new" % self.new)
970 + if self.newslot > 0:
971 + details.append("%s in new slot" % self.newslot)
972 + if self.newslot > 1:
973 + details[-1] += "s"
974 + if self.reinst > 0:
975 + details.append("%s reinstall" % self.reinst)
976 + if self.reinst > 1:
977 + details[-1] += "s"
978 + if self.uninst > 0:
979 + details.append("%s uninstall" % self.uninst)
980 + if self.uninst > 1:
981 + details[-1] += "s"
982 + if self.interactive > 0:
983 + details.append("%s %s" % (self.interactive,
984 + colorize("WARN", "interactive")))
985 + myoutput.append(", ".join(details))
986 + if total_installs != 0:
987 + myoutput.append(")")
988 + myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
989 + if self.restrict_fetch:
990 + myoutput.append("\nFetch Restriction: %s package" % \
991 + self.restrict_fetch)
992 + if self.restrict_fetch > 1:
993 + myoutput.append("s")
994 + if self.restrict_fetch_satisfied < self.restrict_fetch:
995 + myoutput.append(bad(" (%s unsatisfied)") % \
996 + (self.restrict_fetch - self.restrict_fetch_satisfied))
997 + if self.blocks > 0:
998 + myoutput.append("\nConflict: %s block" % \
999 + self.blocks)
1000 + if self.blocks > 1:
1001 + myoutput.append("s")
1002 + if self.blocks_satisfied < self.blocks:
1003 + myoutput.append(bad(" (%s unsatisfied)") % \
1004 + (self.blocks - self.blocks_satisfied))
1005 + return "".join(myoutput)
1006 +
1007
1008 Copied: main/branches/prefix/pym/_emerge/PackageUninstall.py (from rev 13669, main/trunk/pym/_emerge/PackageUninstall.py)
1009 ===================================================================
1010 --- main/branches/prefix/pym/_emerge/PackageUninstall.py (rev 0)
1011 +++ main/branches/prefix/pym/_emerge/PackageUninstall.py 2009-06-27 13:35:38 UTC (rev 13708)
1012 @@ -0,0 +1,50 @@
1013 +import logging
1014 +# for an explanation on this logic, see pym/_emerge/__init__.py
1015 +import os
1016 +import sys
1017 +if os.environ.__contains__("PORTAGE_PYTHONPATH"):
1018 + sys.path.insert(0, os.environ["PORTAGE_PYTHONPATH"])
1019 +else:
1020 + sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "pym"))
1021 +import portage
1022 +
1023 +from _emerge.AsynchronousTask import AsynchronousTask
1024 +from _emerge.unmerge import unmerge
1025 +from _emerge.UninstallFailure import UninstallFailure
1026 +
1027 +class PackageUninstall(AsynchronousTask):
1028 +
1029 + __slots__ = ("ldpath_mtimes", "opts", "pkg", "scheduler", "settings")
1030 +
1031 + def _start(self):
1032 + try:
1033 + unmerge(self.pkg.root_config, self.opts, "unmerge",
1034 + [self.pkg.cpv], self.ldpath_mtimes, clean_world=0,
1035 + clean_delay=0, raise_on_error=1, scheduler=self.scheduler,
1036 + writemsg_level=self._writemsg_level)
1037 + except UninstallFailure, e:
1038 + self.returncode = e.status
1039 + else:
1040 + self.returncode = os.EX_OK
1041 + self.wait()
1042 +
1043 + def _writemsg_level(self, msg, level=0, noiselevel=0):
1044 +
1045 + log_path = self.settings.get("PORTAGE_LOG_FILE")
1046 + background = self.background
1047 +
1048 + if log_path is None:
1049 + if not (background and level < logging.WARNING):
1050 + portage.util.writemsg_level(msg,
1051 + level=level, noiselevel=noiselevel)
1052 + else:
1053 + if not background:
1054 + portage.util.writemsg_level(msg,
1055 + level=level, noiselevel=noiselevel)
1056 +
1057 + f = open(log_path, 'a')
1058 + try:
1059 + f.write(msg)
1060 + finally:
1061 + f.close()
1062 +
1063
1064 Copied: main/branches/prefix/pym/_emerge/RootConfig.py (from rev 13669, main/trunk/pym/_emerge/RootConfig.py)
1065 ===================================================================
1066 --- main/branches/prefix/pym/_emerge/RootConfig.py (rev 0)
1067 +++ main/branches/prefix/pym/_emerge/RootConfig.py 2009-06-27 13:35:38 UTC (rev 13708)
1068 @@ -0,0 +1,28 @@
1069 +from _emerge.PackageVirtualDbapi import PackageVirtualDbapi
1070 +
1071 +class RootConfig(object):
1072 + """This is used internally by depgraph to track information about a
1073 + particular $ROOT."""
1074 +
1075 + pkg_tree_map = {
1076 + "ebuild" : "porttree",
1077 + "binary" : "bintree",
1078 + "installed" : "vartree"
1079 + }
1080 +
1081 + tree_pkg_map = {}
1082 + for k, v in pkg_tree_map.iteritems():
1083 + tree_pkg_map[v] = k
1084 +
1085 + def __init__(self, settings, trees, setconfig):
1086 + self.trees = trees
1087 + self.settings = settings
1088 + self.iuse_implicit = tuple(sorted(settings._get_implicit_iuse()))
1089 + self.root = self.settings["ROOT"]
1090 + self.setconfig = setconfig
1091 + if setconfig is None:
1092 + self.sets = {}
1093 + else:
1094 + self.sets = self.setconfig.getSets()
1095 + self.visible_pkgs = PackageVirtualDbapi(self.settings)
1096 +
1097
1098 Modified: main/branches/prefix/pym/_emerge/__init__.py
1099 ===================================================================
1100 --- main/branches/prefix/pym/_emerge/__init__.py 2009-06-27 13:19:35 UTC (rev 13707)
1101 +++ main/branches/prefix/pym/_emerge/__init__.py 2009-06-27 13:35:38 UTC (rev 13708)
1102 @@ -35,17 +35,16 @@
1103
1104 from portage import digraph
1105 from portage.const import NEWS_LIB_PATH
1106 +from portage.cache.mappings import slot_dict_class
1107
1108 import _emerge.help
1109 import portage.xpak, commands, errno, re, socket, time
1110 from portage.output import blue, bold, colorize, darkblue, darkgreen, green, \
1111 - nc_len, red, teal, turquoise, xtermTitle, \
1112 + nc_len, red, teal, turquoise, \
1113 xtermTitleReset, yellow
1114 from portage.output import create_color_func
1115 good = create_color_func("GOOD")
1116 bad = create_color_func("BAD")
1117 -# white looks bad on terminals with white background
1118 -from portage.output import bold as white
1119
1120 import portage.elog
1121 import portage.dep
1122 @@ -70,15 +69,11 @@
1123 from _emerge.UnmergeDepPriority import UnmergeDepPriority
1124 from _emerge.DepPriorityNormalRange import DepPriorityNormalRange
1125 from _emerge.DepPrioritySatisfiedRange import DepPrioritySatisfiedRange
1126 -from _emerge.Task import Task
1127 +from _emerge.Package import Package
1128 from _emerge.Blocker import Blocker
1129 -from _emerge.AsynchronousTask import AsynchronousTask
1130 -from _emerge.CompositeTask import CompositeTask
1131 +from _emerge.BlockerDB import BlockerDB
1132 from _emerge.EbuildFetcher import EbuildFetcher
1133 -from _emerge.EbuildBuild import EbuildBuild
1134 -from _emerge.EbuildMetadataPhase import EbuildMetadataPhase
1135 from _emerge.EbuildPhase import EbuildPhase
1136 -from _emerge.Binpkg import Binpkg
1137 from _emerge.BinpkgPrefetcher import BinpkgPrefetcher
1138 from _emerge.PackageMerge import PackageMerge
1139 from _emerge.DependencyArg import DependencyArg
1140 @@ -93,50 +88,22 @@
1141 from _emerge.SequentialTaskQueue import SequentialTaskQueue
1142 from _emerge.ProgressHandler import ProgressHandler
1143 from _emerge.stdout_spinner import stdout_spinner
1144 -from _emerge.UninstallFailure import UninstallFailure
1145 from _emerge.JobStatusDisplay import JobStatusDisplay
1146 from _emerge.PollScheduler import PollScheduler
1147 +from _emerge.search import search
1148 +from _emerge.visible import visible
1149 +from _emerge.emergelog import emergelog, _emerge_log_dir
1150 +from _emerge.userquery import userquery
1151 +from _emerge.countdown import countdown
1152 +from _emerge.unmerge import unmerge
1153 +from _emerge.MergeListItem import MergeListItem
1154 +from _emerge.MetadataRegen import MetadataRegen
1155 +from _emerge.RootConfig import RootConfig
1156 +from _emerge.format_size import format_size
1157 +from _emerge.PackageCounters import PackageCounters
1158 +from _emerge.FakeVartree import FakeVartree
1159 +from _emerge.show_invalid_depstring_notice import show_invalid_depstring_notice
1160
1161 -def userquery(prompt, responses=None, colours=None):
1162 - """Displays a prompt and a set of responses, then waits for a response
1163 - which is checked against the responses and the first to match is
1164 - returned. An empty response will match the first value in responses. The
1165 - input buffer is *not* cleared prior to the prompt!
1166 -
1167 - prompt: a String.
1168 - responses: a List of Strings.
1169 - colours: a List of Functions taking and returning a String, used to
1170 - process the responses for display. Typically these will be functions
1171 - like red() but could be e.g. lambda x: "DisplayString".
1172 - If responses is omitted, defaults to ["Yes", "No"], [green, red].
1173 - If only colours is omitted, defaults to [bold, ...].
1174 -
1175 - Returns a member of the List responses. (If called without optional
1176 - arguments, returns "Yes" or "No".)
1177 - KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
1178 - printed."""
1179 - if responses is None:
1180 - responses = ["Yes", "No"]
1181 - colours = [
1182 - create_color_func("PROMPT_CHOICE_DEFAULT"),
1183 - create_color_func("PROMPT_CHOICE_OTHER")
1184 - ]
1185 - elif colours is None:
1186 - colours=[bold]
1187 - colours=(colours*len(responses))[:len(responses)]
1188 - print bold(prompt),
1189 - try:
1190 - while True:
1191 - response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
1192 - for key in responses:
1193 - # An empty response will match the first value in responses.
1194 - if response.upper()==key[:len(response)].upper():
1195 - return key
1196 - print "Sorry, response '%s' not understood." % response,
1197 - except (EOFError, KeyboardInterrupt):
1198 - print "Interrupted."
1199 - sys.exit(1)
1200 -
1201 actions = frozenset([
1202 "clean", "config", "depclean",
1203 "info", "list-sets", "metadata",
1204 @@ -191,63 +158,6 @@
1205 "v":"--verbose", "V":"--version"
1206 }
1207
1208 -_emerge_log_dir = '/var/log'
1209 -
1210 -def emergelog(xterm_titles, mystr, short_msg=None):
1211 - if xterm_titles and short_msg:
1212 - if "HOSTNAME" in os.environ:
1213 - short_msg = os.environ["HOSTNAME"]+": "+short_msg
1214 - xtermTitle(short_msg)
1215 - try:
1216 - file_path = os.path.join(_emerge_log_dir, 'emerge.log')
1217 - mylogfile = open(file_path, "a")
1218 - portage.util.apply_secpass_permissions(file_path,
1219 - uid=portage.portage_uid, gid=portage.portage_gid,
1220 - mode=0660)
1221 - mylock = None
1222 - try:
1223 - mylock = portage.locks.lockfile(mylogfile)
1224 - # seek because we may have gotten held up by the lock.
1225 - # if so, we may not be positioned at the end of the file.
1226 - mylogfile.seek(0, 2)
1227 - mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
1228 - mylogfile.flush()
1229 - finally:
1230 - if mylock:
1231 - portage.locks.unlockfile(mylock)
1232 - mylogfile.close()
1233 - except (IOError,OSError,portage.exception.PortageException), e:
1234 - if secpass >= 1:
1235 - print >> sys.stderr, "emergelog():",e
1236 -
1237 -def countdown(secs=5, doing="Starting"):
1238 - if secs:
1239 - print ">>> Waiting",secs,"seconds before starting..."
1240 - print ">>> (Control-C to abort)...\n"+doing+" in: ",
1241 - ticks=range(secs)
1242 - ticks.reverse()
1243 - for sec in ticks:
1244 - sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
1245 - sys.stdout.flush()
1246 - time.sleep(1)
1247 - print
1248 -
1249 -# formats a size given in bytes nicely
1250 -def format_size(mysize):
1251 - if isinstance(mysize, basestring):
1252 - return mysize
1253 - if 0 != mysize % 1024:
1254 - # Always round up to the next kB so that it doesn't show 0 kB when
1255 - # some small file still needs to be fetched.
1256 - mysize += 1024 - mysize % 1024
1257 - mystr=str(mysize/1024)
1258 - mycount=len(mystr)
1259 - while (mycount > 3):
1260 - mycount-=3
1261 - mystr=mystr[:mycount]+","+mystr[mycount:]
1262 - return mystr+" kB"
1263 -
1264 -
1265 def getgccversion(chost):
1266 """
1267 rtype: C{str}
1268 @@ -344,394 +254,6 @@
1269 myparams.add("complete")
1270 return myparams
1271
1272 -# search functionality
1273 -class search(object):
1274 -
1275 - #
1276 - # class constants
1277 - #
1278 - VERSION_SHORT=1
1279 - VERSION_RELEASE=2
1280 -
1281 - #
1282 - # public interface
1283 - #
1284 - def __init__(self, root_config, spinner, searchdesc,
1285 - verbose, usepkg, usepkgonly):
1286 - """Searches the available and installed packages for the supplied search key.
1287 - The list of available and installed packages is created at object instantiation.
1288 - This makes successive searches faster."""
1289 - self.settings = root_config.settings
1290 - self.vartree = root_config.trees["vartree"]
1291 - self.spinner = spinner
1292 - self.verbose = verbose
1293 - self.searchdesc = searchdesc
1294 - self.root_config = root_config
1295 - self.setconfig = root_config.setconfig
1296 - self.matches = {"pkg" : []}
1297 - self.mlen = 0
1298 -
1299 - def fake_portdb():
1300 - pass
1301 - self.portdb = fake_portdb
1302 - for attrib in ("aux_get", "cp_all",
1303 - "xmatch", "findname", "getFetchMap"):
1304 - setattr(fake_portdb, attrib, getattr(self, "_"+attrib))
1305 -
1306 - self._dbs = []
1307 -
1308 - portdb = root_config.trees["porttree"].dbapi
1309 - bindb = root_config.trees["bintree"].dbapi
1310 - vardb = root_config.trees["vartree"].dbapi
1311 -
1312 - if not usepkgonly and portdb._have_root_eclass_dir:
1313 - self._dbs.append(portdb)
1314 -
1315 - if (usepkg or usepkgonly) and bindb.cp_all():
1316 - self._dbs.append(bindb)
1317 -
1318 - self._dbs.append(vardb)
1319 - self._portdb = portdb
1320 -
1321 - def _cp_all(self):
1322 - cp_all = set()
1323 - for db in self._dbs:
1324 - cp_all.update(db.cp_all())
1325 - return list(sorted(cp_all))
1326 -
1327 - def _aux_get(self, *args, **kwargs):
1328 - for db in self._dbs:
1329 - try:
1330 - return db.aux_get(*args, **kwargs)
1331 - except KeyError:
1332 - pass
1333 - raise
1334 -
1335 - def _findname(self, *args, **kwargs):
1336 - for db in self._dbs:
1337 - if db is not self._portdb:
1338 - # We don't want findname to return anything
1339 - # unless it's an ebuild in a portage tree.
1340 - # Otherwise, it's already built and we don't
1341 - # care about it.
1342 - continue
1343 - func = getattr(db, "findname", None)
1344 - if func:
1345 - value = func(*args, **kwargs)
1346 - if value:
1347 - return value
1348 - return None
1349 -
1350 - def _getFetchMap(self, *args, **kwargs):
1351 - for db in self._dbs:
1352 - func = getattr(db, "getFetchMap", None)
1353 - if func:
1354 - value = func(*args, **kwargs)
1355 - if value:
1356 - return value
1357 - return {}
1358 -
1359 - def _visible(self, db, cpv, metadata):
1360 - installed = db is self.vartree.dbapi
1361 - built = installed or db is not self._portdb
1362 - pkg_type = "ebuild"
1363 - if installed:
1364 - pkg_type = "installed"
1365 - elif built:
1366 - pkg_type = "binary"
1367 - return visible(self.settings,
1368 - Package(type_name=pkg_type, root_config=self.root_config,
1369 - cpv=cpv, built=built, installed=installed, metadata=metadata))
1370 -
1371 - def _xmatch(self, level, atom):
1372 - """
1373 - This method does not expand old-style virtuals because it
1374 - is restricted to returning matches for a single ${CATEGORY}/${PN}
1375 - and old-style virual matches unreliable for that when querying
1376 - multiple package databases. If necessary, old-style virtuals
1377 - can be performed on atoms prior to calling this method.
1378 - """
1379 - cp = portage.dep_getkey(atom)
1380 - if level == "match-all":
1381 - matches = set()
1382 - for db in self._dbs:
1383 - if hasattr(db, "xmatch"):
1384 - matches.update(db.xmatch(level, atom))
1385 - else:
1386 - matches.update(db.match(atom))
1387 - result = list(x for x in matches if portage.cpv_getkey(x) == cp)
1388 - db._cpv_sort_ascending(result)
1389 - elif level == "match-visible":
1390 - matches = set()
1391 - for db in self._dbs:
1392 - if hasattr(db, "xmatch"):
1393 - matches.update(db.xmatch(level, atom))
1394 - else:
1395 - db_keys = list(db._aux_cache_keys)
1396 - for cpv in db.match(atom):
1397 - metadata = izip(db_keys,
1398 - db.aux_get(cpv, db_keys))
1399 - if not self._visible(db, cpv, metadata):
1400 - continue
1401 - matches.add(cpv)
1402 - result = list(x for x in matches if portage.cpv_getkey(x) == cp)
1403 - db._cpv_sort_ascending(result)
1404 - elif level == "bestmatch-visible":
1405 - result = None
1406 - for db in self._dbs:
1407 - if hasattr(db, "xmatch"):
1408 - cpv = db.xmatch("bestmatch-visible", atom)
1409 - if not cpv or portage.cpv_getkey(cpv) != cp:
1410 - continue
1411 - if not result or cpv == portage.best([cpv, result]):
1412 - result = cpv
1413 - else:
1414 - db_keys = Package.metadata_keys
1415 - # break out of this loop with highest visible
1416 - # match, checked in descending order
1417 - for cpv in reversed(db.match(atom)):
1418 - if portage.cpv_getkey(cpv) != cp:
1419 - continue
1420 - metadata = izip(db_keys,
1421 - db.aux_get(cpv, db_keys))
1422 - if not self._visible(db, cpv, metadata):
1423 - continue
1424 - if not result or cpv == portage.best([cpv, result]):
1425 - result = cpv
1426 - break
1427 - else:
1428 - raise NotImplementedError(level)
1429 - return result
1430 -
1431 - def execute(self,searchkey):
1432 - """Performs the search for the supplied search key"""
1433 - match_category = 0
1434 - self.searchkey=searchkey
1435 - self.packagematches = []
1436 - if self.searchdesc:
1437 - self.searchdesc=1
1438 - self.matches = {"pkg":[], "desc":[], "set":[]}
1439 - else:
1440 - self.searchdesc=0
1441 - self.matches = {"pkg":[], "set":[]}
1442 - print "Searching... ",
1443 -
1444 - regexsearch = False
1445 - if self.searchkey.startswith('%'):
1446 - regexsearch = True
1447 - self.searchkey = self.searchkey[1:]
1448 - if self.searchkey.startswith('@'):
1449 - match_category = 1
1450 - self.searchkey = self.searchkey[1:]
1451 - if regexsearch:
1452 - self.searchre=re.compile(self.searchkey,re.I)
1453 - else:
1454 - self.searchre=re.compile(re.escape(self.searchkey), re.I)
1455 - for package in self.portdb.cp_all():
1456 - self.spinner.update()
1457 -
1458 - if match_category:
1459 - match_string = package[:]
1460 - else:
1461 - match_string = package.split("/")[-1]
1462 -
1463 - masked=0
1464 - if self.searchre.search(match_string):
1465 - if not self.portdb.xmatch("match-visible", package):
1466 - masked=1
1467 - self.matches["pkg"].append([package,masked])
1468 - elif self.searchdesc: # DESCRIPTION searching
1469 - full_package = self.portdb.xmatch("bestmatch-visible", package)
1470 - if not full_package:
1471 - #no match found; we don't want to query description
1472 - full_package = portage.best(
1473 - self.portdb.xmatch("match-all", package))
1474 - if not full_package:
1475 - continue
1476 - else:
1477 - masked=1
1478 - try:
1479 - full_desc = self.portdb.aux_get(
1480 - full_package, ["DESCRIPTION"])[0]
1481 - except KeyError:
1482 - print "emerge: search: aux_get() failed, skipping"
1483 - continue
1484 - if self.searchre.search(full_desc):
1485 - self.matches["desc"].append([full_package,masked])
1486 -
1487 - self.sdict = self.setconfig.getSets()
1488 - for setname in self.sdict:
1489 - self.spinner.update()
1490 - if match_category:
1491 - match_string = setname
1492 - else:
1493 - match_string = setname.split("/")[-1]
1494 -
1495 - if self.searchre.search(match_string):
1496 - self.matches["set"].append([setname, False])
1497 - elif self.searchdesc:
1498 - if self.searchre.search(
1499 - self.sdict[setname].getMetadata("DESCRIPTION")):
1500 - self.matches["set"].append([setname, False])
1501 -
1502 - self.mlen=0
1503 - for mtype in self.matches:
1504 - self.matches[mtype].sort()
1505 - self.mlen += len(self.matches[mtype])
1506 -
1507 - def addCP(self, cp):
1508 - if not self.portdb.xmatch("match-all", cp):
1509 - return
1510 - masked = 0
1511 - if not self.portdb.xmatch("bestmatch-visible", cp):
1512 - masked = 1
1513 - self.matches["pkg"].append([cp, masked])
1514 - self.mlen += 1
1515 -
1516 - def output(self):
1517 - """Outputs the results of the search."""
1518 - print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
1519 - print "[ Applications found : "+white(str(self.mlen))+" ]"
1520 - print " "
1521 - vardb = self.vartree.dbapi
1522 - for mtype in self.matches:
1523 - for match,masked in self.matches[mtype]:
1524 - full_package = None
1525 - if mtype == "pkg":
1526 - catpack = match
1527 - full_package = self.portdb.xmatch(
1528 - "bestmatch-visible", match)
1529 - if not full_package:
1530 - #no match found; we don't want to query description
1531 - masked=1
1532 - full_package = portage.best(
1533 - self.portdb.xmatch("match-all",match))
1534 - elif mtype == "desc":
1535 - full_package = match
1536 - match = portage.cpv_getkey(match)
1537 - elif mtype == "set":
1538 - print green("*")+" "+white(match)
1539 - print " ", darkgreen("Description:")+" ", self.sdict[match].getMetadata("DESCRIPTION")
1540 - print
1541 - if full_package:
1542 - try:
1543 - desc, homepage, license = self.portdb.aux_get(
1544 - full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
1545 - except KeyError:
1546 - print "emerge: search: aux_get() failed, skipping"
1547 - continue
1548 - if masked:
1549 - print green("*")+" "+white(match)+" "+red("[ Masked ]")
1550 - else:
1551 - print green("*")+" "+white(match)
1552 - myversion = self.getVersion(full_package, search.VERSION_RELEASE)
1553 -
1554 - mysum = [0,0]
1555 - file_size_str = None
1556 - mycat = match.split("/")[0]
1557 - mypkg = match.split("/")[1]
1558 - mycpv = match + "-" + myversion
1559 - myebuild = self.portdb.findname(mycpv)
1560 - if myebuild:
1561 - pkgdir = os.path.dirname(myebuild)
1562 - from portage import manifest
1563 - mf = manifest.Manifest(
1564 - pkgdir, self.settings["DISTDIR"])
1565 - try:
1566 - uri_map = self.portdb.getFetchMap(mycpv)
1567 - except portage.exception.InvalidDependString, e:
1568 - file_size_str = "Unknown (%s)" % (e,)
1569 - del e
1570 - else:
1571 - try:
1572 - mysum[0] = mf.getDistfilesSize(uri_map)
1573 - except KeyError, e:
1574 - file_size_str = "Unknown (missing " + \
1575 - "digest for %s)" % (e,)
1576 - del e
1577 -
1578 - available = False
1579 - for db in self._dbs:
1580 - if db is not vardb and \
1581 - db.cpv_exists(mycpv):
1582 - available = True
1583 - if not myebuild and hasattr(db, "bintree"):
1584 - myebuild = db.bintree.getname(mycpv)
1585 - try:
1586 - mysum[0] = os.stat(myebuild).st_size
1587 - except OSError:
1588 - myebuild = None
1589 - break
1590 -
1591 - if myebuild and file_size_str is None:
1592 - mystr = str(mysum[0] / 1024)
1593 - mycount = len(mystr)
1594 - while (mycount > 3):
1595 - mycount -= 3
1596 - mystr = mystr[:mycount] + "," + mystr[mycount:]
1597 - file_size_str = mystr + " kB"
1598 -
1599 - if self.verbose:
1600 - if available:
1601 - print " ", darkgreen("Latest version available:"),myversion
1602 - print " ", self.getInstallationStatus(mycat+'/'+mypkg)
1603 - if myebuild:
1604 - print " %s %s" % \
1605 - (darkgreen("Size of files:"), file_size_str)
1606 - print " ", darkgreen("Homepage:")+" ",homepage
1607 - print " ", darkgreen("Description:")+" ",desc
1608 - print " ", darkgreen("License:")+" ",license
1609 - print
1610 - #
1611 - # private interface
1612 - #
1613 - def getInstallationStatus(self,package):
1614 - installed_package = self.vartree.dep_bestmatch(package)
1615 - result = ""
1616 - version = self.getVersion(installed_package,search.VERSION_RELEASE)
1617 - if len(version) > 0:
1618 - result = darkgreen("Latest version installed:")+" "+version
1619 - else:
1620 - result = darkgreen("Latest version installed:")+" [ Not Installed ]"
1621 - return result
1622 -
1623 - def getVersion(self,full_package,detail):
1624 - if len(full_package) > 1:
1625 - package_parts = portage.catpkgsplit(full_package)
1626 - if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
1627 - result = package_parts[2]+ "-" + package_parts[3]
1628 - else:
1629 - result = package_parts[2]
1630 - else:
1631 - result = ""
1632 - return result
1633 -
1634 -class RootConfig(object):
1635 - """This is used internally by depgraph to track information about a
1636 - particular $ROOT."""
1637 -
1638 - pkg_tree_map = {
1639 - "ebuild" : "porttree",
1640 - "binary" : "bintree",
1641 - "installed" : "vartree"
1642 - }
1643 -
1644 - tree_pkg_map = {}
1645 - for k, v in pkg_tree_map.iteritems():
1646 - tree_pkg_map[v] = k
1647 -
1648 - def __init__(self, settings, trees, setconfig):
1649 - self.trees = trees
1650 - self.settings = settings
1651 - self.iuse_implicit = tuple(sorted(settings._get_implicit_iuse()))
1652 - self.root = self.settings["ROOT"]
1653 - self.setconfig = setconfig
1654 - if setconfig is None:
1655 - self.sets = {}
1656 - else:
1657 - self.sets = self.setconfig.getSets()
1658 - self.visible_pkgs = PackageVirtualDbapi(self.settings)
1659 -
1660 def create_world_atom(pkg, args_set, root_config):
1661 """Create a new atom for the world file if one does not exist. If the
1662 argument atom is precise enough to identify a specific slot then a slot
1663 @@ -854,266 +376,6 @@
1664
1665 return deep_system_deps
1666
1667 -class FakeVartree(portage.vartree):
1668 - """This is implements an in-memory copy of a vartree instance that provides
1669 - all the interfaces required for use by the depgraph. The vardb is locked
1670 - during the constructor call just long enough to read a copy of the
1671 - installed package information. This allows the depgraph to do it's
1672 - dependency calculations without holding a lock on the vardb. It also
1673 - allows things like vardb global updates to be done in memory so that the
1674 - user doesn't necessarily need write access to the vardb in cases where
1675 - global updates are necessary (updates are performed when necessary if there
1676 - is not a matching ebuild in the tree)."""
1677 - def __init__(self, root_config, pkg_cache=None, acquire_lock=1):
1678 - self._root_config = root_config
1679 - if pkg_cache is None:
1680 - pkg_cache = {}
1681 - real_vartree = root_config.trees["vartree"]
1682 - portdb = root_config.trees["porttree"].dbapi
1683 - self.root = real_vartree.root
1684 - self.settings = real_vartree.settings
1685 - mykeys = list(real_vartree.dbapi._aux_cache_keys)
1686 - if "_mtime_" not in mykeys:
1687 - mykeys.append("_mtime_")
1688 - self._db_keys = mykeys
1689 - self._pkg_cache = pkg_cache
1690 - self.dbapi = PackageVirtualDbapi(real_vartree.settings)
1691 - vdb_path = os.path.join(self.root, portage.VDB_PATH)
1692 - try:
1693 - # At least the parent needs to exist for the lock file.
1694 - portage.util.ensure_dirs(vdb_path)
1695 - except portage.exception.PortageException:
1696 - pass
1697 - vdb_lock = None
1698 - try:
1699 - if acquire_lock and os.access(vdb_path, os.W_OK):
1700 - vdb_lock = portage.locks.lockdir(vdb_path)
1701 - real_dbapi = real_vartree.dbapi
1702 - slot_counters = {}
1703 - for cpv in real_dbapi.cpv_all():
1704 - cache_key = ("installed", self.root, cpv, "nomerge")
1705 - pkg = self._pkg_cache.get(cache_key)
1706 - if pkg is not None:
1707 - metadata = pkg.metadata
1708 - else:
1709 - metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
1710 - myslot = metadata["SLOT"]
1711 - mycp = portage.dep_getkey(cpv)
1712 - myslot_atom = "%s:%s" % (mycp, myslot)
1713 - try:
1714 - mycounter = long(metadata["COUNTER"])
1715 - except ValueError:
1716 - mycounter = 0
1717 - metadata["COUNTER"] = str(mycounter)
1718 - other_counter = slot_counters.get(myslot_atom, None)
1719 - if other_counter is not None:
1720 - if other_counter > mycounter:
1721 - continue
1722 - slot_counters[myslot_atom] = mycounter
1723 - if pkg is None:
1724 - pkg = Package(built=True, cpv=cpv,
1725 - installed=True, metadata=metadata,
1726 - root_config=root_config, type_name="installed")
1727 - self._pkg_cache[pkg] = pkg
1728 - self.dbapi.cpv_inject(pkg)
1729 - real_dbapi.flush_cache()
1730 - finally:
1731 - if vdb_lock:
1732 - portage.locks.unlockdir(vdb_lock)
1733 - # Populate the old-style virtuals using the cached values.
1734 - if not self.settings.treeVirtuals:
1735 - self.settings.treeVirtuals = portage.util.map_dictlist_vals(
1736 - portage.getCPFromCPV, self.get_all_provides())
1737 -
1738 - # Intialize variables needed for lazy cache pulls of the live ebuild
1739 - # metadata. This ensures that the vardb lock is released ASAP, without
1740 - # being delayed in case cache generation is triggered.
1741 - self._aux_get = self.dbapi.aux_get
1742 - self.dbapi.aux_get = self._aux_get_wrapper
1743 - self._match = self.dbapi.match
1744 - self.dbapi.match = self._match_wrapper
1745 - self._aux_get_history = set()
1746 - self._portdb_keys = ["EAPI", "DEPEND", "RDEPEND", "PDEPEND"]
1747 - self._portdb = portdb
1748 - self._global_updates = None
1749 -
1750 - def _match_wrapper(self, cpv, use_cache=1):
1751 - """
1752 - Make sure the metadata in Package instances gets updated for any
1753 - cpv that is returned from a match() call, since the metadata can
1754 - be accessed directly from the Package instance instead of via
1755 - aux_get().
1756 - """
1757 - matches = self._match(cpv, use_cache=use_cache)
1758 - for cpv in matches:
1759 - if cpv in self._aux_get_history:
1760 - continue
1761 - self._aux_get_wrapper(cpv, [])
1762 - return matches
1763 -
1764 - def _aux_get_wrapper(self, pkg, wants):
1765 - if pkg in self._aux_get_history:
1766 - return self._aux_get(pkg, wants)
1767 - self._aux_get_history.add(pkg)
1768 - try:
1769 - # Use the live ebuild metadata if possible.
1770 - live_metadata = dict(izip(self._portdb_keys,
1771 - self._portdb.aux_get(pkg, self._portdb_keys)))
1772 - if not portage.eapi_is_supported(live_metadata["EAPI"]):
1773 - raise KeyError(pkg)
1774 - self.dbapi.aux_update(pkg, live_metadata)
1775 - except (KeyError, portage.exception.PortageException):
1776 - if self._global_updates is None:
1777 - self._global_updates = \
1778 - grab_global_updates(self._portdb.porttree_root)
1779 - perform_global_updates(
1780 - pkg, self.dbapi, self._global_updates)
1781 - return self._aux_get(pkg, wants)
1782 -
1783 - def sync(self, acquire_lock=1):
1784 - """
1785 - Call this method to synchronize state with the real vardb
1786 - after one or more packages may have been installed or
1787 - uninstalled.
1788 - """
1789 - vdb_path = os.path.join(self.root, portage.VDB_PATH)
1790 - try:
1791 - # At least the parent needs to exist for the lock file.
1792 - portage.util.ensure_dirs(vdb_path)
1793 - except portage.exception.PortageException:
1794 - pass
1795 - vdb_lock = None
1796 - try:
1797 - if acquire_lock and os.access(vdb_path, os.W_OK):
1798 - vdb_lock = portage.locks.lockdir(vdb_path)
1799 - self._sync()
1800 - finally:
1801 - if vdb_lock:
1802 - portage.locks.unlockdir(vdb_lock)
1803 -
1804 - def _sync(self):
1805 -
1806 - real_vardb = self._root_config.trees["vartree"].dbapi
1807 - current_cpv_set = frozenset(real_vardb.cpv_all())
1808 - pkg_vardb = self.dbapi
1809 - aux_get_history = self._aux_get_history
1810 -
1811 - # Remove any packages that have been uninstalled.
1812 - for pkg in list(pkg_vardb):
1813 - if pkg.cpv not in current_cpv_set:
1814 - pkg_vardb.cpv_remove(pkg)
1815 - aux_get_history.discard(pkg.cpv)
1816 -
1817 - # Validate counters and timestamps.
1818 - slot_counters = {}
1819 - root = self.root
1820 - validation_keys = ["COUNTER", "_mtime_"]
1821 - for cpv in current_cpv_set:
1822 -
1823 - pkg_hash_key = ("installed", root, cpv, "nomerge")
1824 - pkg = pkg_vardb.get(pkg_hash_key)
1825 - if pkg is not None:
1826 - counter, mtime = real_vardb.aux_get(cpv, validation_keys)
1827 - try:
1828 - counter = long(counter)
1829 - except ValueError:
1830 - counter = 0
1831 -
1832 - if counter != pkg.counter or \
1833 - mtime != pkg.mtime:
1834 - pkg_vardb.cpv_remove(pkg)
1835 - aux_get_history.discard(pkg.cpv)
1836 - pkg = None
1837 -
1838 - if pkg is None:
1839 - pkg = self._pkg(cpv)
1840 -
1841 - other_counter = slot_counters.get(pkg.slot_atom)
1842 - if other_counter is not None:
1843 - if other_counter > pkg.counter:
1844 - continue
1845 -
1846 - slot_counters[pkg.slot_atom] = pkg.counter
1847 - pkg_vardb.cpv_inject(pkg)
1848 -
1849 - real_vardb.flush_cache()
1850 -
1851 - def _pkg(self, cpv):
1852 - root_config = self._root_config
1853 - real_vardb = root_config.trees["vartree"].dbapi
1854 - pkg = Package(cpv=cpv, installed=True,
1855 - metadata=izip(self._db_keys,
1856 - real_vardb.aux_get(cpv, self._db_keys)),
1857 - root_config=root_config,
1858 - type_name="installed")
1859 -
1860 - try:
1861 - mycounter = long(pkg.metadata["COUNTER"])
1862 - except ValueError:
1863 - mycounter = 0
1864 - pkg.metadata["COUNTER"] = str(mycounter)
1865 -
1866 - return pkg
1867 -
1868 -def grab_global_updates(portdir):
1869 - from portage.update import grab_updates, parse_updates
1870 - updpath = os.path.join(portdir, "profiles", "updates")
1871 - try:
1872 - rawupdates = grab_updates(updpath)
1873 - except portage.exception.DirectoryNotFound:
1874 - rawupdates = []
1875 - upd_commands = []
1876 - for mykey, mystat, mycontent in rawupdates:
1877 - commands, errors = parse_updates(mycontent)
1878 - upd_commands.extend(commands)
1879 - return upd_commands
1880 -
1881 -def perform_global_updates(mycpv, mydb, mycommands):
1882 - from portage.update import update_dbentries
1883 - aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
1884 - aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
1885 - updates = update_dbentries(mycommands, aux_dict)
1886 - if updates:
1887 - mydb.aux_update(mycpv, updates)
1888 -
1889 -def visible(pkgsettings, pkg):
1890 - """
1891 - Check if a package is visible. This can raise an InvalidDependString
1892 - exception if LICENSE is invalid.
1893 - TODO: optionally generate a list of masking reasons
1894 - @rtype: Boolean
1895 - @returns: True if the package is visible, False otherwise.
1896 - """
1897 - if not pkg.metadata["SLOT"]:
1898 - return False
1899 - if not pkg.installed:
1900 - if not pkgsettings._accept_chost(pkg.cpv, pkg.metadata):
1901 - return False
1902 - if pkg.built and not pkg.installed:
1903 - # we can have an old binary which has no EPREFIX information
1904 - if "EPREFIX" not in pkg.metadata or not pkg.metadata["EPREFIX"]:
1905 - return False
1906 - if len(pkg.metadata["EPREFIX"].strip()) < len(pkgsettings["EPREFIX"]):
1907 - return False
1908 - eapi = pkg.metadata["EAPI"]
1909 - if not portage.eapi_is_supported(eapi):
1910 - return False
1911 - if not pkg.installed:
1912 - if portage._eapi_is_deprecated(eapi):
1913 - return False
1914 - if pkgsettings._getMissingKeywords(pkg.cpv, pkg.metadata):
1915 - return False
1916 - if pkgsettings._getMaskAtom(pkg.cpv, pkg.metadata):
1917 - return False
1918 - if pkgsettings._getProfileMaskAtom(pkg.cpv, pkg.metadata):
1919 - return False
1920 - try:
1921 - if pkgsettings._getMissingLicenses(pkg.cpv, pkg.metadata):
1922 - return False
1923 - except portage.exception.InvalidDependString:
1924 - return False
1925 - return True
1926 -
1927 def get_masking_status(pkg, pkgsettings, root_config):
1928
1929 mreasons = portage.getmaskingstatus(
1930 @@ -1212,487 +474,6 @@
1931 shown_licenses.add(l)
1932 return have_eapi_mask
1933
1934 -class Package(Task):
1935 -
1936 - __hash__ = Task.__hash__
1937 - __slots__ = ("built", "cpv", "depth",
1938 - "installed", "metadata", "onlydeps", "operation",
1939 - "root_config", "type_name",
1940 - "category", "counter", "cp", "cpv_split",
1941 - "inherited", "iuse", "mtime",
1942 - "pf", "pv_split", "root", "slot", "slot_atom", "use")
1943 -
1944 - metadata_keys = [
1945 - "CHOST", "COUNTER", "DEPEND", "EAPI",
1946 - "INHERITED", "IUSE", "KEYWORDS",
1947 - "LICENSE", "PDEPEND", "PROVIDE", "RDEPEND",
1948 - "repository", "PROPERTIES", "RESTRICT", "SLOT", "USE", "_mtime_",
1949 - "EPREFIX" ]
1950 -
1951 - def __init__(self, **kwargs):
1952 - Task.__init__(self, **kwargs)
1953 - self.root = self.root_config.root
1954 - self.metadata = _PackageMetadataWrapper(self, self.metadata)
1955 - self.cp = portage.cpv_getkey(self.cpv)
1956 - slot = self.slot
1957 - if not slot:
1958 - # Avoid an InvalidAtom exception when creating slot_atom.
1959 - # This package instance will be masked due to empty SLOT.
1960 - slot = '0'
1961 - self.slot_atom = portage.dep.Atom("%s:%s" % (self.cp, slot))
1962 - self.category, self.pf = portage.catsplit(self.cpv)
1963 - self.cpv_split = portage.catpkgsplit(self.cpv)
1964 - self.pv_split = self.cpv_split[1:]
1965 -
1966 - class _use(object):
1967 -
1968 - __slots__ = ("__weakref__", "enabled")
1969 -
1970 - def __init__(self, use):
1971 - self.enabled = frozenset(use)
1972 -
1973 - class _iuse(object):
1974 -
1975 - __slots__ = ("__weakref__", "all", "enabled", "disabled", "iuse_implicit", "regex", "tokens")
1976 -
1977 - def __init__(self, tokens, iuse_implicit):
1978 - self.tokens = tuple(tokens)
1979 - self.iuse_implicit = iuse_implicit
1980 - enabled = []
1981 - disabled = []
1982 - other = []
1983 - for x in tokens:
1984 - prefix = x[:1]
1985 - if prefix == "+":
1986 - enabled.append(x[1:])
1987 - elif prefix == "-":
1988 - disabled.append(x[1:])
1989 - else:
1990 - other.append(x)
1991 - self.enabled = frozenset(enabled)
1992 - self.disabled = frozenset(disabled)
1993 - self.all = frozenset(chain(enabled, disabled, other))
1994 -
1995 - def __getattribute__(self, name):
1996 - if name == "regex":
1997 - try:
1998 - return object.__getattribute__(self, "regex")
1999 - except AttributeError:
2000 - all = object.__getattribute__(self, "all")
2001 - iuse_implicit = object.__getattribute__(self, "iuse_implicit")
2002 - # Escape anything except ".*" which is supposed
2003 - # to pass through from _get_implicit_iuse()
2004 - regex = (re.escape(x) for x in chain(all, iuse_implicit))
2005 - regex = "^(%s)$" % "|".join(regex)
2006 - regex = regex.replace("\\.\\*", ".*")
2007 - self.regex = re.compile(regex)
2008 - return object.__getattribute__(self, name)
2009 -
2010 - def _get_hash_key(self):
2011 - hash_key = getattr(self, "_hash_key", None)
2012 - if hash_key is None:
2013 - if self.operation is None:
2014 - self.operation = "merge"
2015 - if self.onlydeps or self.installed:
2016 - self.operation = "nomerge"
2017 - self._hash_key = \
2018 - (self.type_name, self.root, self.cpv, self.operation)
2019 - return self._hash_key
2020 -
2021 - def __lt__(self, other):
2022 - if other.cp != self.cp:
2023 - return False
2024 - if portage.pkgcmp(self.pv_split, other.pv_split) < 0:
2025 - return True
2026 - return False
2027 -
2028 - def __le__(self, other):
2029 - if other.cp != self.cp:
2030 - return False
2031 - if portage.pkgcmp(self.pv_split, other.pv_split) <= 0:
2032 - return True
2033 - return False
2034 -
2035 - def __gt__(self, other):
2036 - if other.cp != self.cp:
2037 - return False
2038 - if portage.pkgcmp(self.pv_split, other.pv_split) > 0:
2039 - return True
2040 - return False
2041 -
2042 - def __ge__(self, other):
2043 - if other.cp != self.cp:
2044 - return False
2045 - if portage.pkgcmp(self.pv_split, other.pv_split) >= 0:
2046 - return True
2047 - return False
2048 -
2049 -_all_metadata_keys = set(x for x in portage.auxdbkeys \
2050 - if not x.startswith("UNUSED_"))
2051 -_all_metadata_keys.discard("CDEPEND")
2052 -_all_metadata_keys.update(Package.metadata_keys)
2053 -
2054 -from portage.cache.mappings import slot_dict_class
2055 -_PackageMetadataWrapperBase = slot_dict_class(_all_metadata_keys)
2056 -
2057 -class _PackageMetadataWrapper(_PackageMetadataWrapperBase):
2058 - """
2059 - Detect metadata updates and synchronize Package attributes.
2060 - """
2061 -
2062 - __slots__ = ("_pkg",)
2063 - _wrapped_keys = frozenset(
2064 - ["COUNTER", "INHERITED", "IUSE", "SLOT", "USE", "_mtime_"])
2065 -
2066 - def __init__(self, pkg, metadata):
2067 - _PackageMetadataWrapperBase.__init__(self)
2068 - self._pkg = pkg
2069 - self.update(metadata)
2070 -
2071 - def __setitem__(self, k, v):
2072 - _PackageMetadataWrapperBase.__setitem__(self, k, v)
2073 - if k in self._wrapped_keys:
2074 - getattr(self, "_set_" + k.lower())(k, v)
2075 -
2076 - def _set_inherited(self, k, v):
2077 - if isinstance(v, basestring):
2078 - v = frozenset(v.split())
2079 - self._pkg.inherited = v
2080 -
2081 - def _set_iuse(self, k, v):
2082 - self._pkg.iuse = self._pkg._iuse(
2083 - v.split(), self._pkg.root_config.iuse_implicit)
2084 -
2085 - def _set_slot(self, k, v):
2086 - self._pkg.slot = v
2087 -
2088 - def _set_use(self, k, v):
2089 - self._pkg.use = self._pkg._use(v.split())
2090 -
2091 - def _set_counter(self, k, v):
2092 - if isinstance(v, basestring):
2093 - try:
2094 - v = long(v.strip())
2095 - except ValueError:
2096 - v = 0
2097 - self._pkg.counter = v
2098 -
2099 - def _set__mtime_(self, k, v):
2100 - if isinstance(v, basestring):
2101 - try:
2102 - v = long(v.strip())
2103 - except ValueError:
2104 - v = 0
2105 - self._pkg.mtime = v
2106 -
2107 -class PackageUninstall(AsynchronousTask):
2108 -
2109 - __slots__ = ("ldpath_mtimes", "opts", "pkg", "scheduler", "settings")
2110 -
2111 - def _start(self):
2112 - try:
2113 - unmerge(self.pkg.root_config, self.opts, "unmerge",
2114 - [self.pkg.cpv], self.ldpath_mtimes, clean_world=0,
2115 - clean_delay=0, raise_on_error=1, scheduler=self.scheduler,
2116 - writemsg_level=self._writemsg_level)
2117 - except UninstallFailure, e:
2118 - self.returncode = e.status
2119 - else:
2120 - self.returncode = os.EX_OK
2121 - self.wait()
2122 -
2123 - def _writemsg_level(self, msg, level=0, noiselevel=0):
2124 -
2125 - log_path = self.settings.get("PORTAGE_LOG_FILE")
2126 - background = self.background
2127 -
2128 - if log_path is None:
2129 - if not (background and level < logging.WARNING):
2130 - portage.util.writemsg_level(msg,
2131 - level=level, noiselevel=noiselevel)
2132 - else:
2133 - if not background:
2134 - portage.util.writemsg_level(msg,
2135 - level=level, noiselevel=noiselevel)
2136 -
2137 - f = open(log_path, 'a')
2138 - try:
2139 - f.write(msg)
2140 - finally:
2141 - f.close()
2142 -
2143 -class MergeListItem(CompositeTask):
2144 -
2145 - """
2146 - TODO: For parallel scheduling, everything here needs asynchronous
2147 - execution support (start, poll, and wait methods).
2148 - """
2149 -
2150 - __slots__ = ("args_set",
2151 - "binpkg_opts", "build_opts", "config_pool", "emerge_opts",
2152 - "find_blockers", "logger", "mtimedb", "pkg",
2153 - "pkg_count", "pkg_to_replace", "prefetcher",
2154 - "settings", "statusMessage", "world_atom") + \
2155 - ("_install_task",)
2156 -
2157 - def _start(self):
2158 -
2159 - pkg = self.pkg
2160 - build_opts = self.build_opts
2161 -
2162 - if pkg.installed:
2163 - # uninstall, executed by self.merge()
2164 - self.returncode = os.EX_OK
2165 - self.wait()
2166 - return
2167 -
2168 - args_set = self.args_set
2169 - find_blockers = self.find_blockers
2170 - logger = self.logger
2171 - mtimedb = self.mtimedb
2172 - pkg_count = self.pkg_count
2173 - scheduler = self.scheduler
2174 - settings = self.settings
2175 - world_atom = self.world_atom
2176 - ldpath_mtimes = mtimedb["ldpath"]
2177 -
2178 - action_desc = "Emerging"
2179 - preposition = "for"
2180 - if pkg.type_name == "binary":
2181 - action_desc += " binary"
2182 -
2183 - if build_opts.fetchonly:
2184 - action_desc = "Fetching"
2185 -
2186 - msg = "%s (%s of %s) %s" % \
2187 - (action_desc,
2188 - colorize("MERGE_LIST_PROGRESS", str(pkg_count.curval)),
2189 - colorize("MERGE_LIST_PROGRESS", str(pkg_count.maxval)),
2190 - colorize("GOOD", pkg.cpv))
2191 -
2192 - portdb = pkg.root_config.trees["porttree"].dbapi
2193 - portdir_repo_name = portdb._repository_map.get(portdb.porttree_root)
2194 - if portdir_repo_name:
2195 - pkg_repo_name = pkg.metadata.get("repository")
2196 - if pkg_repo_name != portdir_repo_name:
2197 - if not pkg_repo_name:
2198 - pkg_repo_name = "unknown repo"
2199 - msg += " from %s" % pkg_repo_name
2200 -
2201 - if pkg.root != "/":
2202 - msg += " %s %s" % (preposition, pkg.root)
2203 -
2204 - if not build_opts.pretend:
2205 - self.statusMessage(msg)
2206 - logger.log(" >>> emerge (%s of %s) %s to %s" % \
2207 - (pkg_count.curval, pkg_count.maxval, pkg.cpv, pkg.root))
2208 -
2209 - if pkg.type_name == "ebuild":
2210 -
2211 - build = EbuildBuild(args_set=args_set,
2212 - background=self.background,
2213 - config_pool=self.config_pool,
2214 - find_blockers=find_blockers,
2215 - ldpath_mtimes=ldpath_mtimes, logger=logger,
2216 - opts=build_opts, pkg=pkg, pkg_count=pkg_count,
2217 - prefetcher=self.prefetcher, scheduler=scheduler,
2218 - settings=settings, world_atom=world_atom)
2219 -
2220 - self._install_task = build
2221 - self._start_task(build, self._default_final_exit)
2222 - return
2223 -
2224 - elif pkg.type_name == "binary":
2225 -
2226 - binpkg = Binpkg(background=self.background,
2227 - find_blockers=find_blockers,
2228 - ldpath_mtimes=ldpath_mtimes, logger=logger,
2229 - opts=self.binpkg_opts, pkg=pkg, pkg_count=pkg_count,
2230 - prefetcher=self.prefetcher, settings=settings,
2231 - scheduler=scheduler, world_atom=world_atom)
2232 -
2233 - self._install_task = binpkg
2234 - self._start_task(binpkg, self._default_final_exit)
2235 - return
2236 -
2237 - def _poll(self):
2238 - self._install_task.poll()
2239 - return self.returncode
2240 -
2241 - def _wait(self):
2242 - self._install_task.wait()
2243 - return self.returncode
2244 -
2245 - def merge(self):
2246 -
2247 - pkg = self.pkg
2248 - build_opts = self.build_opts
2249 - find_blockers = self.find_blockers
2250 - logger = self.logger
2251 - mtimedb = self.mtimedb
2252 - pkg_count = self.pkg_count
2253 - prefetcher = self.prefetcher
2254 - scheduler = self.scheduler
2255 - settings = self.settings
2256 - world_atom = self.world_atom
2257 - ldpath_mtimes = mtimedb["ldpath"]
2258 -
2259 - if pkg.installed:
2260 - if not (build_opts.buildpkgonly or \
2261 - build_opts.fetchonly or build_opts.pretend):
2262 -
2263 - uninstall = PackageUninstall(background=self.background,
2264 - ldpath_mtimes=ldpath_mtimes, opts=self.emerge_opts,
2265 - pkg=pkg, scheduler=scheduler, settings=settings)
2266 -
2267 - uninstall.start()
2268 - retval = uninstall.wait()
2269 - if retval != os.EX_OK:
2270 - return retval
2271 - return os.EX_OK
2272 -
2273 - if build_opts.fetchonly or \
2274 - build_opts.buildpkgonly:
2275 - return self.returncode
2276 -
2277 - retval = self._install_task.install()
2278 - return retval
2279 -
2280 -class BlockerDB(object):
2281 -
2282 - def __init__(self, root_config):
2283 - self._root_config = root_config
2284 - self._vartree = root_config.trees["vartree"]
2285 - self._portdb = root_config.trees["porttree"].dbapi
2286 -
2287 - self._dep_check_trees = None
2288 - self._fake_vartree = None
2289 -
2290 - def _get_fake_vartree(self, acquire_lock=0):
2291 - fake_vartree = self._fake_vartree
2292 - if fake_vartree is None:
2293 - fake_vartree = FakeVartree(self._root_config,
2294 - acquire_lock=acquire_lock)
2295 - self._fake_vartree = fake_vartree
2296 - self._dep_check_trees = { self._vartree.root : {
2297 - "porttree" : fake_vartree,
2298 - "vartree" : fake_vartree,
2299 - }}
2300 - else:
2301 - fake_vartree.sync(acquire_lock=acquire_lock)
2302 - return fake_vartree
2303 -
2304 - def findInstalledBlockers(self, new_pkg, acquire_lock=0):
2305 - blocker_cache = BlockerCache(self._vartree.root, self._vartree.dbapi)
2306 - dep_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
2307 - settings = self._vartree.settings
2308 - stale_cache = set(blocker_cache)
2309 - fake_vartree = self._get_fake_vartree(acquire_lock=acquire_lock)
2310 - dep_check_trees = self._dep_check_trees
2311 - vardb = fake_vartree.dbapi
2312 - installed_pkgs = list(vardb)
2313 -
2314 - for inst_pkg in installed_pkgs:
2315 - stale_cache.discard(inst_pkg.cpv)
2316 - cached_blockers = blocker_cache.get(inst_pkg.cpv)
2317 - if cached_blockers is not None and \
2318 - cached_blockers.counter != long(inst_pkg.metadata["COUNTER"]):
2319 - cached_blockers = None
2320 - if cached_blockers is not None:
2321 - blocker_atoms = cached_blockers.atoms
2322 - else:
2323 - # Use aux_get() to trigger FakeVartree global
2324 - # updates on *DEPEND when appropriate.
2325 - depstr = " ".join(vardb.aux_get(inst_pkg.cpv, dep_keys))
2326 - try:
2327 - portage.dep._dep_check_strict = False
2328 - success, atoms = portage.dep_check(depstr,
2329 - vardb, settings, myuse=inst_pkg.use.enabled,
2330 - trees=dep_check_trees, myroot=inst_pkg.root)
2331 - finally:
2332 - portage.dep._dep_check_strict = True
2333 - if not success:
2334 - pkg_location = os.path.join(inst_pkg.root,
2335 - portage.VDB_PATH, inst_pkg.category, inst_pkg.pf)
2336 - portage.writemsg("!!! %s/*DEPEND: %s\n" % \
2337 - (pkg_location, atoms), noiselevel=-1)
2338 - continue
2339 -
2340 - blocker_atoms = [atom for atom in atoms \
2341 - if atom.startswith("!")]
2342 - blocker_atoms.sort()
2343 - counter = long(inst_pkg.metadata["COUNTER"])
2344 - blocker_cache[inst_pkg.cpv] = \
2345 - blocker_cache.BlockerData(counter, blocker_atoms)
2346 - for cpv in stale_cache:
2347 - del blocker_cache[cpv]
2348 - blocker_cache.flush()
2349 -
2350 - blocker_parents = digraph()
2351 - blocker_atoms = []
2352 - for pkg in installed_pkgs:
2353 - for blocker_atom in blocker_cache[pkg.cpv].atoms:
2354 - blocker_atom = blocker_atom.lstrip("!")
2355 - blocker_atoms.append(blocker_atom)
2356 - blocker_parents.add(blocker_atom, pkg)
2357 -
2358 - blocker_atoms = InternalPackageSet(initial_atoms=blocker_atoms)
2359 - blocking_pkgs = set()
2360 - for atom in blocker_atoms.iterAtomsForPackage(new_pkg):
2361 - blocking_pkgs.update(blocker_parents.parent_nodes(atom))
2362 -
2363 - # Check for blockers in the other direction.
2364 - depstr = " ".join(new_pkg.metadata[k] for k in dep_keys)
2365 - try:
2366 - portage.dep._dep_check_strict = False
2367 - success, atoms = portage.dep_check(depstr,
2368 - vardb, settings, myuse=new_pkg.use.enabled,
2369 - trees=dep_check_trees, myroot=new_pkg.root)
2370 - finally:
2371 - portage.dep._dep_check_strict = True
2372 - if not success:
2373 - # We should never get this far with invalid deps.
2374 - show_invalid_depstring_notice(new_pkg, depstr, atoms)
2375 - assert False
2376 -
2377 - blocker_atoms = [atom.lstrip("!") for atom in atoms \
2378 - if atom[:1] == "!"]
2379 - if blocker_atoms:
2380 - blocker_atoms = InternalPackageSet(initial_atoms=blocker_atoms)
2381 - for inst_pkg in installed_pkgs:
2382 - try:
2383 - blocker_atoms.iterAtomsForPackage(inst_pkg).next()
2384 - except (portage.exception.InvalidDependString, StopIteration):
2385 - continue
2386 - blocking_pkgs.add(inst_pkg)
2387 -
2388 - return blocking_pkgs
2389 -
2390 -def show_invalid_depstring_notice(parent_node, depstring, error_msg):
2391 -
2392 - msg1 = "\n\n!!! Invalid or corrupt dependency specification: " + \
2393 - "\n\n%s\n\n%s\n\n%s\n\n" % (error_msg, parent_node, depstring)
2394 - p_type, p_root, p_key, p_status = parent_node
2395 - msg = []
2396 - if p_status == "nomerge":
2397 - category, pf = portage.catsplit(p_key)
2398 - pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
2399 - msg.append("Portage is unable to process the dependencies of the ")
2400 - msg.append("'%s' package. " % p_key)
2401 - msg.append("In order to correct this problem, the package ")
2402 - msg.append("should be uninstalled, reinstalled, or upgraded. ")
2403 - msg.append("As a temporary workaround, the --nodeps option can ")
2404 - msg.append("be used to ignore all dependencies. For reference, ")
2405 - msg.append("the problematic dependencies can be found in the ")
2406 - msg.append("*DEPEND files located in '%s/'." % pkg_location)
2407 - else:
2408 - msg.append("This package can not be installed. ")
2409 - msg.append("Please notify the '%s' package maintainer " % p_key)
2410 - msg.append("about this problem.")
2411 -
2412 - msg2 = "".join("%s\n" % line for line in textwrap.wrap("".join(msg), 72))
2413 - writemsg_level(msg1 + msg2, level=logging.ERROR, noiselevel=-1)
2414 -
2415 class depgraph(object):
2416
2417 pkg_tree_map = RootConfig.pkg_tree_map
2418 @@ -6400,78 +5181,6 @@
2419 metadata = self._cpv_pkg_map[cpv].metadata
2420 return [metadata.get(x, "") for x in wants]
2421
2422 -class PackageCounters(object):
2423 -
2424 - def __init__(self):
2425 - self.upgrades = 0
2426 - self.downgrades = 0
2427 - self.new = 0
2428 - self.newslot = 0
2429 - self.reinst = 0
2430 - self.uninst = 0
2431 - self.blocks = 0
2432 - self.blocks_satisfied = 0
2433 - self.totalsize = 0
2434 - self.restrict_fetch = 0
2435 - self.restrict_fetch_satisfied = 0
2436 - self.interactive = 0
2437 -
2438 - def __str__(self):
2439 - total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
2440 - myoutput = []
2441 - details = []
2442 - myoutput.append("Total: %s package" % total_installs)
2443 - if total_installs != 1:
2444 - myoutput.append("s")
2445 - if total_installs != 0:
2446 - myoutput.append(" (")
2447 - if self.upgrades > 0:
2448 - details.append("%s upgrade" % self.upgrades)
2449 - if self.upgrades > 1:
2450 - details[-1] += "s"
2451 - if self.downgrades > 0:
2452 - details.append("%s downgrade" % self.downgrades)
2453 - if self.downgrades > 1:
2454 - details[-1] += "s"
2455 - if self.new > 0:
2456 - details.append("%s new" % self.new)
2457 - if self.newslot > 0:
2458 - details.append("%s in new slot" % self.newslot)
2459 - if self.newslot > 1:
2460 - details[-1] += "s"
2461 - if self.reinst > 0:
2462 - details.append("%s reinstall" % self.reinst)
2463 - if self.reinst > 1:
2464 - details[-1] += "s"
2465 - if self.uninst > 0:
2466 - details.append("%s uninstall" % self.uninst)
2467 - if self.uninst > 1:
2468 - details[-1] += "s"
2469 - if self.interactive > 0:
2470 - details.append("%s %s" % (self.interactive,
2471 - colorize("WARN", "interactive")))
2472 - myoutput.append(", ".join(details))
2473 - if total_installs != 0:
2474 - myoutput.append(")")
2475 - myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
2476 - if self.restrict_fetch:
2477 - myoutput.append("\nFetch Restriction: %s package" % \
2478 - self.restrict_fetch)
2479 - if self.restrict_fetch > 1:
2480 - myoutput.append("s")
2481 - if self.restrict_fetch_satisfied < self.restrict_fetch:
2482 - myoutput.append(bad(" (%s unsatisfied)") % \
2483 - (self.restrict_fetch - self.restrict_fetch_satisfied))
2484 - if self.blocks > 0:
2485 - myoutput.append("\nConflict: %s block" % \
2486 - self.blocks)
2487 - if self.blocks > 1:
2488 - myoutput.append("s")
2489 - if self.blocks_satisfied < self.blocks:
2490 - myoutput.append(bad(" (%s unsatisfied)") % \
2491 - (self.blocks - self.blocks_satisfied))
2492 - return "".join(myoutput)
2493 -
2494 class Scheduler(PollScheduler):
2495
2496 _opts_ignore_blockers = \
2497 @@ -8065,663 +6774,6 @@
2498
2499 return pkg
2500
2501 -class MetadataRegen(PollScheduler):
2502 -
2503 - def __init__(self, portdb, cp_iter=None, consumer=None,
2504 - max_jobs=None, max_load=None):
2505 - PollScheduler.__init__(self)
2506 - self._portdb = portdb
2507 - self._global_cleanse = False
2508 - if cp_iter is None:
2509 - cp_iter = self._iter_every_cp()
2510 - # We can globally cleanse stale cache only if we
2511 - # iterate over every single cp.
2512 - self._global_cleanse = True
2513 - self._cp_iter = cp_iter
2514 - self._consumer = consumer
2515 -
2516 - if max_jobs is None:
2517 - max_jobs = 1
2518 -
2519 - self._max_jobs = max_jobs
2520 - self._max_load = max_load
2521 - self._sched_iface = self._sched_iface_class(
2522 - register=self._register,
2523 - schedule=self._schedule_wait,
2524 - unregister=self._unregister)
2525 -
2526 - self._valid_pkgs = set()
2527 - self._cp_set = set()
2528 - self._process_iter = self._iter_metadata_processes()
2529 - self.returncode = os.EX_OK
2530 - self._error_count = 0
2531 -
2532 - def _iter_every_cp(self):
2533 - every_cp = self._portdb.cp_all()
2534 - every_cp.sort(reverse=True)
2535 - try:
2536 - while True:
2537 - yield every_cp.pop()
2538 - except IndexError:
2539 - pass
2540 -
2541 - def _iter_metadata_processes(self):
2542 - portdb = self._portdb
2543 - valid_pkgs = self._valid_pkgs
2544 - cp_set = self._cp_set
2545 - consumer = self._consumer
2546 -
2547 - for cp in self._cp_iter:
2548 - cp_set.add(cp)
2549 - portage.writemsg_stdout("Processing %s\n" % cp)
2550 - cpv_list = portdb.cp_list(cp)
2551 - for cpv in cpv_list:
2552 - valid_pkgs.add(cpv)
2553 - ebuild_path, repo_path = portdb.findname2(cpv)
2554 - metadata, st, emtime = portdb._pull_valid_cache(
2555 - cpv, ebuild_path, repo_path)
2556 - if metadata is not None:
2557 - if consumer is not None:
2558 - consumer(cpv, ebuild_path,
2559 - repo_path, metadata)
2560 - continue
2561 -
2562 - yield EbuildMetadataPhase(cpv=cpv, ebuild_path=ebuild_path,
2563 - ebuild_mtime=emtime,
2564 - metadata_callback=portdb._metadata_callback,
2565 - portdb=portdb, repo_path=repo_path,
2566 - settings=portdb.doebuild_settings)
2567 -
2568 - def run(self):
2569 -
2570 - portdb = self._portdb
2571 - from portage.cache.cache_errors import CacheError
2572 - dead_nodes = {}
2573 -
2574 - while self._schedule():
2575 - self._poll_loop()
2576 -
2577 - while self._jobs:
2578 - self._poll_loop()
2579 -
2580 - if self._global_cleanse:
2581 - for mytree in portdb.porttrees:
2582 - try:
2583 - dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
2584 - except CacheError, e:
2585 - portage.writemsg("Error listing cache entries for " + \
2586 - "'%s': %s, continuing...\n" % (mytree, e),
2587 - noiselevel=-1)
2588 - del e
2589 - dead_nodes = None
2590 - break
2591 - else:
2592 - cp_set = self._cp_set
2593 - cpv_getkey = portage.cpv_getkey
2594 - for mytree in portdb.porttrees:
2595 - try:
2596 - dead_nodes[mytree] = set(cpv for cpv in \
2597 - portdb.auxdb[mytree].iterkeys() \
2598 - if cpv_getkey(cpv) in cp_set)
2599 - except CacheError, e:
2600 - portage.writemsg("Error listing cache entries for " + \
2601 - "'%s': %s, continuing...\n" % (mytree, e),
2602 - noiselevel=-1)
2603 - del e
2604 - dead_nodes = None
2605 - break
2606 -
2607 - if dead_nodes:
2608 - for y in self._valid_pkgs:
2609 - for mytree in portdb.porttrees:
2610 - if portdb.findname2(y, mytree=mytree)[0]:
2611 - dead_nodes[mytree].discard(y)
2612 -
2613 - for mytree, nodes in dead_nodes.iteritems():
2614 - auxdb = portdb.auxdb[mytree]
2615 - for y in nodes:
2616 - try:
2617 - del auxdb[y]
2618 - except (KeyError, CacheError):
2619 - pass
2620 -
2621 - def _schedule_tasks(self):
2622 - """
2623 - @rtype: bool
2624 - @returns: True if there may be remaining tasks to schedule,
2625 - False otherwise.
2626 - """
2627 - while self._can_add_job():
2628 - try:
2629 - metadata_process = self._process_iter.next()
2630 - except StopIteration:
2631 - return False
2632 -
2633 - self._jobs += 1
2634 - metadata_process.scheduler = self._sched_iface
2635 - metadata_process.addExitListener(self._metadata_exit)
2636 - metadata_process.start()
2637 - return True
2638 -
2639 - def _metadata_exit(self, metadata_process):
2640 - self._jobs -= 1
2641 - if metadata_process.returncode != os.EX_OK:
2642 - self.returncode = 1
2643 - self._error_count += 1
2644 - self._valid_pkgs.discard(metadata_process.cpv)
2645 - portage.writemsg("Error processing %s, continuing...\n" % \
2646 - (metadata_process.cpv,), noiselevel=-1)
2647 -
2648 - if self._consumer is not None:
2649 - # On failure, still notify the consumer (in this case the metadata
2650 - # argument is None).
2651 - self._consumer(metadata_process.cpv,
2652 - metadata_process.ebuild_path,
2653 - metadata_process.repo_path,
2654 - metadata_process.metadata)
2655 -
2656 - self._schedule()
2657 -
2658 -def unmerge(root_config, myopts, unmerge_action,
2659 - unmerge_files, ldpath_mtimes, autoclean=0,
2660 - clean_world=1, clean_delay=1, ordered=0, raise_on_error=0,
2661 - scheduler=None, writemsg_level=portage.util.writemsg_level):
2662 -
2663 - if clean_world:
2664 - clean_world = myopts.get('--deselect') != 'n'
2665 - quiet = "--quiet" in myopts
2666 - settings = root_config.settings
2667 - sets = root_config.sets
2668 - vartree = root_config.trees["vartree"]
2669 - candidate_catpkgs=[]
2670 - global_unmerge=0
2671 - xterm_titles = "notitles" not in settings.features
2672 - out = portage.output.EOutput()
2673 - pkg_cache = {}
2674 - db_keys = list(vartree.dbapi._aux_cache_keys)
2675 -
2676 - def _pkg(cpv):
2677 - pkg = pkg_cache.get(cpv)
2678 - if pkg is None:
2679 - pkg = Package(cpv=cpv, installed=True,
2680 - metadata=izip(db_keys, vartree.dbapi.aux_get(cpv, db_keys)),
2681 - root_config=root_config,
2682 - type_name="installed")
2683 - pkg_cache[cpv] = pkg
2684 - return pkg
2685 -
2686 - vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
2687 - try:
2688 - # At least the parent needs to exist for the lock file.
2689 - portage.util.ensure_dirs(vdb_path)
2690 - except portage.exception.PortageException:
2691 - pass
2692 - vdb_lock = None
2693 - try:
2694 - if os.access(vdb_path, os.W_OK):
2695 - vdb_lock = portage.locks.lockdir(vdb_path)
2696 - realsyslist = sets["system"].getAtoms()
2697 - syslist = []
2698 - for x in realsyslist:
2699 - mycp = portage.dep_getkey(x)
2700 - if mycp in settings.getvirtuals():
2701 - providers = []
2702 - for provider in settings.getvirtuals()[mycp]:
2703 - if vartree.dbapi.match(provider):
2704 - providers.append(provider)
2705 - if len(providers) == 1:
2706 - syslist.extend(providers)
2707 - else:
2708 - syslist.append(mycp)
2709 -
2710 - mysettings = portage.config(clone=settings)
2711 -
2712 - if not unmerge_files:
2713 - if unmerge_action == "unmerge":
2714 - print
2715 - print bold("emerge unmerge") + " can only be used with specific package names"
2716 - print
2717 - return 0
2718 - else:
2719 - global_unmerge = 1
2720 -
2721 - localtree = vartree
2722 - # process all arguments and add all
2723 - # valid db entries to candidate_catpkgs
2724 - if global_unmerge:
2725 - if not unmerge_files:
2726 - candidate_catpkgs.extend(vartree.dbapi.cp_all())
2727 - else:
2728 - #we've got command-line arguments
2729 - if not unmerge_files:
2730 - print "\nNo packages to unmerge have been provided.\n"
2731 - return 0
2732 - for x in unmerge_files:
2733 - arg_parts = x.split('/')
2734 - if x[0] not in [".","/"] and \
2735 - arg_parts[-1][-7:] != ".ebuild":
2736 - #possible cat/pkg or dep; treat as such
2737 - candidate_catpkgs.append(x)
2738 - elif unmerge_action in ["prune","clean"]:
2739 - print "\n!!! Prune and clean do not accept individual" + \
2740 - " ebuilds as arguments;\n skipping.\n"
2741 - continue
2742 - else:
2743 - # it appears that the user is specifying an installed
2744 - # ebuild and we're in "unmerge" mode, so it's ok.
2745 - if not os.path.exists(x):
2746 - print "\n!!! The path '"+x+"' doesn't exist.\n"
2747 - return 0
2748 -
2749 - absx = os.path.abspath(x)
2750 - sp_absx = absx.split("/")
2751 - if sp_absx[-1][-7:] == ".ebuild":
2752 - del sp_absx[-1]
2753 - absx = "/".join(sp_absx)
2754 -
2755 - sp_absx_len = len(sp_absx)
2756 -
2757 - vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
2758 - vdb_len = len(vdb_path)
2759 -
2760 - sp_vdb = vdb_path.split("/")
2761 - sp_vdb_len = len(sp_vdb)
2762 -
2763 - if not os.path.exists(absx+"/CONTENTS"):
2764 - print "!!! Not a valid db dir: "+str(absx)
2765 - return 0
2766 -
2767 - if sp_absx_len <= sp_vdb_len:
2768 - # The Path is shorter... so it can't be inside the vdb.
2769 - print sp_absx
2770 - print absx
2771 - print "\n!!!",x,"cannot be inside "+ \
2772 - vdb_path+"; aborting.\n"
2773 - return 0
2774 -
2775 - for idx in range(0,sp_vdb_len):
2776 - if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
2777 - print sp_absx
2778 - print absx
2779 - print "\n!!!", x, "is not inside "+\
2780 - vdb_path+"; aborting.\n"
2781 - return 0
2782 -
2783 - print "="+"/".join(sp_absx[sp_vdb_len:])
2784 - candidate_catpkgs.append(
2785 - "="+"/".join(sp_absx[sp_vdb_len:]))
2786 -
2787 - newline=""
2788 - if (not "--quiet" in myopts):
2789 - newline="\n"
2790 - if settings["ROOT"] != "/":
2791 - writemsg_level(darkgreen(newline+ \
2792 - ">>> Using system located in ROOT tree %s\n" % \
2793 - settings["ROOT"]))
2794 -
2795 - if (("--pretend" in myopts) or ("--ask" in myopts)) and \
2796 - not ("--quiet" in myopts):
2797 - writemsg_level(darkgreen(newline+\
2798 - ">>> These are the packages that would be unmerged:\n"))
2799 -
2800 - # Preservation of order is required for --depclean and --prune so
2801 - # that dependencies are respected. Use all_selected to eliminate
2802 - # duplicate packages since the same package may be selected by
2803 - # multiple atoms.
2804 - pkgmap = []
2805 - all_selected = set()
2806 - for x in candidate_catpkgs:
2807 - # cycle through all our candidate deps and determine
2808 - # what will and will not get unmerged
2809 - try:
2810 - mymatch = vartree.dbapi.match(x)
2811 - except portage.exception.AmbiguousPackageName, errpkgs:
2812 - print "\n\n!!! The short ebuild name \"" + \
2813 - x + "\" is ambiguous. Please specify"
2814 - print "!!! one of the following fully-qualified " + \
2815 - "ebuild names instead:\n"
2816 - for i in errpkgs[0]:
2817 - print " " + green(i)
2818 - print
2819 - sys.exit(1)
2820 -
2821 - if not mymatch and x[0] not in "<>=~":
2822 - mymatch = localtree.dep_match(x)
2823 - if not mymatch:
2824 - portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
2825 - (x, unmerge_action), noiselevel=-1)
2826 - continue
2827 -
2828 - pkgmap.append(
2829 - {"protected": set(), "selected": set(), "omitted": set()})
2830 - mykey = len(pkgmap) - 1
2831 - if unmerge_action=="unmerge":
2832 - for y in mymatch:
2833 - if y not in all_selected:
2834 - pkgmap[mykey]["selected"].add(y)
2835 - all_selected.add(y)
2836 - elif unmerge_action == "prune":
2837 - if len(mymatch) == 1:
2838 - continue
2839 - best_version = mymatch[0]
2840 - best_slot = vartree.getslot(best_version)
2841 - best_counter = vartree.dbapi.cpv_counter(best_version)
2842 - for mypkg in mymatch[1:]:
2843 - myslot = vartree.getslot(mypkg)
2844 - mycounter = vartree.dbapi.cpv_counter(mypkg)
2845 - if (myslot == best_slot and mycounter > best_counter) or \
2846 - mypkg == portage.best([mypkg, best_version]):
2847 - if myslot == best_slot:
2848 - if mycounter < best_counter:
2849 - # On slot collision, keep the one with the
2850 - # highest counter since it is the most
2851 - # recently installed.
2852 - continue
2853 - best_version = mypkg
2854 - best_slot = myslot
2855 - best_counter = mycounter
2856 - pkgmap[mykey]["protected"].add(best_version)
2857 - pkgmap[mykey]["selected"].update(mypkg for mypkg in mymatch \
2858 - if mypkg != best_version and mypkg not in all_selected)
2859 - all_selected.update(pkgmap[mykey]["selected"])
2860 - else:
2861 - # unmerge_action == "clean"
2862 - slotmap={}
2863 - for mypkg in mymatch:
2864 - if unmerge_action == "clean":
2865 - myslot = localtree.getslot(mypkg)
2866 - else:
2867 - # since we're pruning, we don't care about slots
2868 - # and put all the pkgs in together
2869 - myslot = 0
2870 - if myslot not in slotmap:
2871 - slotmap[myslot] = {}
2872 - slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)] = mypkg
2873 -
2874 - for mypkg in vartree.dbapi.cp_list(
2875 - portage.dep_getkey(mymatch[0])):
2876 - myslot = vartree.getslot(mypkg)
2877 - if myslot not in slotmap:
2878 - slotmap[myslot] = {}
2879 - slotmap[myslot][vartree.dbapi.cpv_counter(mypkg)] = mypkg
2880 -
2881 - for myslot in slotmap:
2882 - counterkeys = slotmap[myslot].keys()
2883 - if not counterkeys:
2884 - continue
2885 - counterkeys.sort()
2886 - pkgmap[mykey]["protected"].add(
2887 - slotmap[myslot][counterkeys[-1]])
2888 - del counterkeys[-1]
2889 -
2890 - for counter in counterkeys[:]:
2891 - mypkg = slotmap[myslot][counter]
2892 - if mypkg not in mymatch:
2893 - counterkeys.remove(counter)
2894 - pkgmap[mykey]["protected"].add(
2895 - slotmap[myslot][counter])
2896 -
2897 - #be pretty and get them in order of merge:
2898 - for ckey in counterkeys:
2899 - mypkg = slotmap[myslot][ckey]
2900 - if mypkg not in all_selected:
2901 - pkgmap[mykey]["selected"].add(mypkg)
2902 - all_selected.add(mypkg)
2903 - # ok, now the last-merged package
2904 - # is protected, and the rest are selected
2905 - numselected = len(all_selected)
2906 - if global_unmerge and not numselected:
2907 - portage.writemsg_stdout("\n>>> No outdated packages were found on your system.\n")
2908 - return 0
2909 -
2910 - if not numselected:
2911 - portage.writemsg_stdout(
2912 - "\n>>> No packages selected for removal by " + \
2913 - unmerge_action + "\n")
2914 - return 0
2915 - finally:
2916 - if vdb_lock:
2917 - vartree.dbapi.flush_cache()
2918 - portage.locks.unlockdir(vdb_lock)
2919 -
2920 - from portage.sets.base import EditablePackageSet
2921 -
2922 - # generate a list of package sets that are directly or indirectly listed in "world",
2923 - # as there is no persistent list of "installed" sets
2924 - installed_sets = ["world"]
2925 - stop = False
2926 - pos = 0
2927 - while not stop:
2928 - stop = True
2929 - pos = len(installed_sets)
2930 - for s in installed_sets[pos - 1:]:
2931 - if s not in sets:
2932 - continue
2933 - candidates = [x[len(SETPREFIX):] for x in sets[s].getNonAtoms() if x.startswith(SETPREFIX)]
2934 - if candidates:
2935 - stop = False
2936 - installed_sets += candidates
2937 - installed_sets = [x for x in installed_sets if x not in root_config.setconfig.active]
2938 - del stop, pos
2939 -
2940 - # we don't want to unmerge packages that are still listed in user-editable package sets
2941 - # listed in "world" as they would be remerged on the next update of "world" or the
2942 - # relevant package sets.
2943 - unknown_sets = set()
2944 - for cp in xrange(len(pkgmap)):
2945 - for cpv in pkgmap[cp]["selected"].copy():
2946 - try:
2947 - pkg = _pkg(cpv)
2948 - except KeyError:
2949 - # It could have been uninstalled
2950 - # by a concurrent process.
2951 - continue
2952 -
2953 - if unmerge_action != "clean" and \
2954 - root_config.root == "/" and \
2955 - portage.match_from_list(
2956 - portage.const.PORTAGE_PACKAGE_ATOM, [pkg]):
2957 - msg = ("Not unmerging package %s since there is no valid " + \
2958 - "reason for portage to unmerge itself.") % (pkg.cpv,)
2959 - for line in textwrap.wrap(msg, 75):
2960 - out.eerror(line)
2961 - # adjust pkgmap so the display output is correct
2962 - pkgmap[cp]["selected"].remove(cpv)
2963 - all_selected.remove(cpv)
2964 - pkgmap[cp]["protected"].add(cpv)
2965 - continue
2966 -
2967 - parents = []
2968 - for s in installed_sets:
2969 - # skip sets that the user requested to unmerge, and skip world
2970 - # unless we're unmerging a package set (as the package would be
2971 - # removed from "world" later on)
2972 - if s in root_config.setconfig.active or (s == "world" and not root_config.setconfig.active):
2973 - continue
2974 -
2975 - if s not in sets:
2976 - if s in unknown_sets:
2977 - continue
2978 - unknown_sets.add(s)
2979 - out = portage.output.EOutput()
2980 - out.eerror(("Unknown set '@%s' in " + \
2981 - "%svar/lib/portage/world_sets") % \
2982 - (s, root_config.root))
2983 - continue
2984 -
2985 - # only check instances of EditablePackageSet as other classes are generally used for
2986 - # special purposes and can be ignored here (and are usually generated dynamically, so the
2987 - # user can't do much about them anyway)
2988 - if isinstance(sets[s], EditablePackageSet):
2989 -
2990 - # This is derived from a snippet of code in the
2991 - # depgraph._iter_atoms_for_pkg() method.
2992 - for atom in sets[s].iterAtomsForPackage(pkg):
2993 - inst_matches = vartree.dbapi.match(atom)
2994 - inst_matches.reverse() # descending order
2995 - higher_slot = None
2996 - for inst_cpv in inst_matches:
2997 - try:
2998 - inst_pkg = _pkg(inst_cpv)
2999 - except KeyError:
3000 - # It could have been uninstalled
3001 - # by a concurrent process.
3002 - continue
3003 -
3004 - if inst_pkg.cp != atom.cp:
3005 - continue
3006 - if pkg >= inst_pkg:
3007 - # This is descending order, and we're not
3008 - # interested in any versions <= pkg given.
3009 - break
3010 - if pkg.slot_atom != inst_pkg.slot_atom:
3011 - higher_slot = inst_pkg
3012 - break
3013 - if higher_slot is None:
3014 - parents.append(s)
3015 - break
3016 - if parents:
3017 - #print colorize("WARN", "Package %s is going to be unmerged," % cpv)
3018 - #print colorize("WARN", "but still listed in the following package sets:")
3019 - #print " %s\n" % ", ".join(parents)
3020 - print colorize("WARN", "Not unmerging package %s as it is" % cpv)
3021 - print colorize("WARN", "still referenced by the following package sets:")
3022 - print " %s\n" % ", ".join(parents)
3023 - # adjust pkgmap so the display output is correct
3024 - pkgmap[cp]["selected"].remove(cpv)
3025 - all_selected.remove(cpv)
3026 - pkgmap[cp]["protected"].add(cpv)
3027 -
3028 - del installed_sets
3029 -
3030 - numselected = len(all_selected)
3031 - if not numselected:
3032 - writemsg_level(
3033 - "\n>>> No packages selected for removal by " + \
3034 - unmerge_action + "\n")
3035 - return 0
3036 -
3037 - # Unmerge order only matters in some cases
3038 - if not ordered:
3039 - unordered = {}
3040 - for d in pkgmap:
3041 - selected = d["selected"]
3042 - if not selected:
3043 - continue
3044 - cp = portage.cpv_getkey(iter(selected).next())
3045 - cp_dict = unordered.get(cp)
3046 - if cp_dict is None:
3047 - cp_dict = {}
3048 - unordered[cp] = cp_dict
3049 - for k in d:
3050 - cp_dict[k] = set()
3051 - for k, v in d.iteritems():
3052 - cp_dict[k].update(v)
3053 - pkgmap = [unordered[cp] for cp in sorted(unordered)]
3054 -
3055 - for x in xrange(len(pkgmap)):
3056 - selected = pkgmap[x]["selected"]
3057 - if not selected:
3058 - continue
3059 - for mytype, mylist in pkgmap[x].iteritems():
3060 - if mytype == "selected":
3061 - continue
3062 - mylist.difference_update(all_selected)
3063 - cp = portage.cpv_getkey(iter(selected).next())
3064 - for y in localtree.dep_match(cp):
3065 - if y not in pkgmap[x]["omitted"] and \
3066 - y not in pkgmap[x]["selected"] and \
3067 - y not in pkgmap[x]["protected"] and \
3068 - y not in all_selected:
3069 - pkgmap[x]["omitted"].add(y)
3070 - if global_unmerge and not pkgmap[x]["selected"]:
3071 - #avoid cluttering the preview printout with stuff that isn't getting unmerged
3072 - continue
3073 - if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and cp in syslist:
3074 - writemsg_level(colorize("BAD","\a\n\n!!! " + \
3075 - "'%s' is part of your system profile.\n" % cp),
3076 - level=logging.WARNING, noiselevel=-1)
3077 - writemsg_level(colorize("WARN","\a!!! Unmerging it may " + \
3078 - "be damaging to your system.\n\n"),
3079 - level=logging.WARNING, noiselevel=-1)
3080 - if clean_delay and "--pretend" not in myopts and "--ask" not in myopts:
3081 - countdown(int(settings["EMERGE_WARNING_DELAY"]),
3082 - colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
3083 - if not quiet:
3084 - writemsg_level("\n %s\n" % (bold(cp),), noiselevel=-1)
3085 - else:
3086 - writemsg_level(bold(cp) + ": ", noiselevel=-1)
3087 - for mytype in ["selected","protected","omitted"]:
3088 - if not quiet:
3089 - writemsg_level((mytype + ": ").rjust(14), noiselevel=-1)
3090 - if pkgmap[x][mytype]:
3091 - sorted_pkgs = [portage.catpkgsplit(mypkg)[1:] for mypkg in pkgmap[x][mytype]]
3092 - sorted_pkgs.sort(key=cmp_sort_key(portage.pkgcmp))
3093 - for pn, ver, rev in sorted_pkgs:
3094 - if rev == "r0":
3095 - myversion = ver
3096 - else:
3097 - myversion = ver + "-" + rev
3098 - if mytype == "selected":
3099 - writemsg_level(
3100 - colorize("UNMERGE_WARN", myversion + " "),
3101 - noiselevel=-1)
3102 - else:
3103 - writemsg_level(
3104 - colorize("GOOD", myversion + " "), noiselevel=-1)
3105 - else:
3106 - writemsg_level("none ", noiselevel=-1)
3107 - if not quiet:
3108 - writemsg_level("\n", noiselevel=-1)
3109 - if quiet:
3110 - writemsg_level("\n", noiselevel=-1)
3111 -
3112 - writemsg_level("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
3113 - " packages are slated for removal.\n")
3114 - writemsg_level(">>> " + colorize("GOOD", "'Protected'") + \
3115 - " and " + colorize("GOOD", "'omitted'") + \
3116 - " packages will not be removed.\n\n")
3117 -
3118 - if "--pretend" in myopts:
3119 - #we're done... return
3120 - return 0
3121 - if "--ask" in myopts:
3122 - if userquery("Would you like to unmerge these packages?")=="No":
3123 - # enter pretend mode for correct formatting of results
3124 - myopts["--pretend"] = True
3125 - print
3126 - print "Quitting."
3127 - print
3128 - return 0
3129 - #the real unmerging begins, after a short delay....
3130 - if clean_delay and not autoclean:
3131 - countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
3132 -
3133 - for x in xrange(len(pkgmap)):
3134 - for y in pkgmap[x]["selected"]:
3135 - writemsg_level(">>> Unmerging "+y+"...\n", noiselevel=-1)
3136 - emergelog(xterm_titles, "=== Unmerging... ("+y+")")
3137 - mysplit = y.split("/")
3138 - #unmerge...
3139 - retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
3140 - mysettings, unmerge_action not in ["clean","prune"],
3141 - vartree=vartree, ldpath_mtimes=ldpath_mtimes,
3142 - scheduler=scheduler)
3143 -
3144 - if retval != os.EX_OK:
3145 - emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
3146 - if raise_on_error:
3147 - raise UninstallFailure(retval)
3148 - sys.exit(retval)
3149 - else:
3150 - if clean_world and hasattr(sets["world"], "cleanPackage"):
3151 - sets["world"].cleanPackage(vartree.dbapi, y)
3152 - emergelog(xterm_titles, " >>> unmerge success: "+y)
3153 - if clean_world and hasattr(sets["world"], "remove"):
3154 - for s in root_config.setconfig.active:
3155 - sets["world"].remove(SETPREFIX+s)
3156 - return 1
3157 -
3158 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
3159
3160 if os.path.exists(EPREFIX + "/usr/bin/install-info"):
3161
3162 Copied: main/branches/prefix/pym/_emerge/countdown.py (from rev 13669, main/trunk/pym/_emerge/countdown.py)
3163 ===================================================================
3164 --- main/branches/prefix/pym/_emerge/countdown.py (rev 0)
3165 +++ main/branches/prefix/pym/_emerge/countdown.py 2009-06-27 13:35:38 UTC (rev 13708)
3166 @@ -0,0 +1,17 @@
3167 +import sys
3168 +import time
3169 +
3170 +from portage.output import colorize
3171 +
3172 +def countdown(secs=5, doing="Starting"):
3173 + if secs:
3174 + print ">>> Waiting",secs,"seconds before starting..."
3175 + print ">>> (Control-C to abort)...\n"+doing+" in: ",
3176 + ticks=range(secs)
3177 + ticks.reverse()
3178 + for sec in ticks:
3179 + sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
3180 + sys.stdout.flush()
3181 + time.sleep(1)
3182 + print
3183 +
3184
3185 Copied: main/branches/prefix/pym/_emerge/emergelog.py (from rev 13669, main/trunk/pym/_emerge/emergelog.py)
3186 ===================================================================
3187 --- main/branches/prefix/pym/_emerge/emergelog.py (rev 0)
3188 +++ main/branches/prefix/pym/_emerge/emergelog.py 2009-06-27 13:35:38 UTC (rev 13708)
3189 @@ -0,0 +1,43 @@
3190 +import os
3191 +import sys
3192 +import time
3193 +# for an explanation on this logic, see pym/_emerge/__init__.py
3194 +import os
3195 +import sys
3196 +if os.environ.__contains__("PORTAGE_PYTHONPATH"):
3197 + sys.path.insert(0, os.environ["PORTAGE_PYTHONPATH"])
3198 +else:
3199 + sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "pym"))
3200 +import portage
3201 +
3202 +from portage.data import secpass
3203 +from portage.output import xtermTitle
3204 +
3205 +_emerge_log_dir = '/var/log'
3206 +
3207 +def emergelog(xterm_titles, mystr, short_msg=None):
3208 + if xterm_titles and short_msg:
3209 + if "HOSTNAME" in os.environ:
3210 + short_msg = os.environ["HOSTNAME"]+": "+short_msg
3211 + xtermTitle(short_msg)
3212 + try:
3213 + file_path = os.path.join(_emerge_log_dir, 'emerge.log')
3214 + mylogfile = open(file_path, "a")
3215 + portage.util.apply_secpass_permissions(file_path,
3216 + uid=portage.portage_uid, gid=portage.portage_gid,
3217 + mode=0660)
3218 + mylock = None
3219 + try:
3220 + mylock = portage.locks.lockfile(mylogfile)
3221 + # seek because we may have gotten held up by the lock.
3222 + # if so, we may not be positioned at the end of the file.
3223 + mylogfile.seek(0, 2)
3224 + mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
3225 + mylogfile.flush()
3226 + finally:
3227 + if mylock:
3228 + portage.locks.unlockfile(mylock)
3229 + mylogfile.close()
3230 + except (IOError,OSError,portage.exception.PortageException), e:
3231 + if secpass >= 1:
3232 + print >> sys.stderr, "emergelog():",e
3233
3234 Copied: main/branches/prefix/pym/_emerge/format_size.py (from rev 13669, main/trunk/pym/_emerge/format_size.py)
3235 ===================================================================
3236 --- main/branches/prefix/pym/_emerge/format_size.py (rev 0)
3237 +++ main/branches/prefix/pym/_emerge/format_size.py 2009-06-27 13:35:38 UTC (rev 13708)
3238 @@ -0,0 +1,16 @@
3239 +
3240 +# formats a size given in bytes nicely
3241 +def format_size(mysize):
3242 + if isinstance(mysize, basestring):
3243 + return mysize
3244 + if 0 != mysize % 1024:
3245 + # Always round up to the next kB so that it doesn't show 0 kB when
3246 + # some small file still needs to be fetched.
3247 + mysize += 1024 - mysize % 1024
3248 + mystr=str(mysize/1024)
3249 + mycount=len(mystr)
3250 + while (mycount > 3):
3251 + mycount-=3
3252 + mystr=mystr[:mycount]+","+mystr[mycount:]
3253 + return mystr+" kB"
3254 +
3255
3256 Copied: main/branches/prefix/pym/_emerge/search.py (from rev 13669, main/trunk/pym/_emerge/search.py)
3257 ===================================================================
3258 --- main/branches/prefix/pym/_emerge/search.py (rev 0)
3259 +++ main/branches/prefix/pym/_emerge/search.py 2009-06-27 13:35:38 UTC (rev 13708)
3260 @@ -0,0 +1,379 @@
3261 +import os
3262 +import re
3263 +from itertools import izip
3264 +
3265 +# for an explanation on this logic, see pym/_emerge/__init__.py
3266 +import os
3267 +import sys
3268 +if os.environ.__contains__("PORTAGE_PYTHONPATH"):
3269 + sys.path.insert(0, os.environ["PORTAGE_PYTHONPATH"])
3270 +else:
3271 + sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "pym"))
3272 +import portage
3273 +
3274 +from portage.output import bold as white, darkgreen, green, red
3275 +
3276 +from _emerge.Package import Package
3277 +from _emerge.visible import visible
3278 +
3279 +class search(object):
3280 +
3281 + #
3282 + # class constants
3283 + #
3284 + VERSION_SHORT=1
3285 + VERSION_RELEASE=2
3286 +
3287 + #
3288 + # public interface
3289 + #
3290 + def __init__(self, root_config, spinner, searchdesc,
3291 + verbose, usepkg, usepkgonly):
3292 + """Searches the available and installed packages for the supplied search key.
3293 + The list of available and installed packages is created at object instantiation.
3294 + This makes successive searches faster."""
3295 + self.settings = root_config.settings
3296 + self.vartree = root_config.trees["vartree"]
3297 + self.spinner = spinner
3298 + self.verbose = verbose
3299 + self.searchdesc = searchdesc
3300 + self.root_config = root_config
3301 + self.setconfig = root_config.setconfig
3302 + self.matches = {"pkg" : []}
3303 + self.mlen = 0
3304 +
3305 + def fake_portdb():
3306 + pass
3307 + self.portdb = fake_portdb
3308 + for attrib in ("aux_get", "cp_all",
3309 + "xmatch", "findname", "getFetchMap"):
3310 + setattr(fake_portdb, attrib, getattr(self, "_"+attrib))
3311 +
3312 + self._dbs = []
3313 +
3314 + portdb = root_config.trees["porttree"].dbapi
3315 + bindb = root_config.trees["bintree"].dbapi
3316 + vardb = root_config.trees["vartree"].dbapi
3317 +
3318 + if not usepkgonly and portdb._have_root_eclass_dir:
3319 + self._dbs.append(portdb)
3320 +
3321 + if (usepkg or usepkgonly) and bindb.cp_all():
3322 + self._dbs.append(bindb)
3323 +
3324 + self._dbs.append(vardb)
3325 + self._portdb = portdb
3326 +
3327 + def _cp_all(self):
3328 + cp_all = set()
3329 + for db in self._dbs:
3330 + cp_all.update(db.cp_all())
3331 + return list(sorted(cp_all))
3332 +
3333 + def _aux_get(self, *args, **kwargs):
3334 + for db in self._dbs:
3335 + try:
3336 + return db.aux_get(*args, **kwargs)
3337 + except KeyError:
3338 + pass
3339 + raise
3340 +
3341 + def _findname(self, *args, **kwargs):
3342 + for db in self._dbs:
3343 + if db is not self._portdb:
3344 + # We don't want findname to return anything
3345 + # unless it's an ebuild in a portage tree.
3346 + # Otherwise, it's already built and we don't
3347 + # care about it.
3348 + continue
3349 + func = getattr(db, "findname", None)
3350 + if func:
3351 + value = func(*args, **kwargs)
3352 + if value:
3353 + return value
3354 + return None
3355 +
3356 + def _getFetchMap(self, *args, **kwargs):
3357 + for db in self._dbs:
3358 + func = getattr(db, "getFetchMap", None)
3359 + if func:
3360 + value = func(*args, **kwargs)
3361 + if value:
3362 + return value
3363 + return {}
3364 +
3365 + def _visible(self, db, cpv, metadata):
3366 + installed = db is self.vartree.dbapi
3367 + built = installed or db is not self._portdb
3368 + pkg_type = "ebuild"
3369 + if installed:
3370 + pkg_type = "installed"
3371 + elif built:
3372 + pkg_type = "binary"
3373 + return visible(self.settings,
3374 + Package(type_name=pkg_type, root_config=self.root_config,
3375 + cpv=cpv, built=built, installed=installed, metadata=metadata))
3376 +
3377 + def _xmatch(self, level, atom):
3378 + """
3379 + This method does not expand old-style virtuals because it
3380 + is restricted to returning matches for a single ${CATEGORY}/${PN}
3381 + and old-style virual matches unreliable for that when querying
3382 + multiple package databases. If necessary, old-style virtuals
3383 + can be performed on atoms prior to calling this method.
3384 + """
3385 + cp = portage.dep_getkey(atom)
3386 + if level == "match-all":
3387 + matches = set()
3388 + for db in self._dbs:
3389 + if hasattr(db, "xmatch"):
3390 + matches.update(db.xmatch(level, atom))
3391 + else:
3392 + matches.update(db.match(atom))
3393 + result = list(x for x in matches if portage.cpv_getkey(x) == cp)
3394 + db._cpv_sort_ascending(result)
3395 + elif level == "match-visible":
3396 + matches = set()
3397 + for db in self._dbs:
3398 + if hasattr(db, "xmatch"):
3399 + matches.update(db.xmatch(level, atom))
3400 + else:
3401 + db_keys = list(db._aux_cache_keys)
3402 + for cpv in db.match(atom):
3403 + metadata = izip(db_keys,
3404 + db.aux_get(cpv, db_keys))
3405 + if not self._visible(db, cpv, metadata):
3406 + continue
3407 + matches.add(cpv)
3408 + result = list(x for x in matches if portage.cpv_getkey(x) == cp)
3409 + db._cpv_sort_ascending(result)
3410 + elif level == "bestmatch-visible":
3411 + result = None
3412 + for db in self._dbs:
3413 + if hasattr(db, "xmatch"):
3414 + cpv = db.xmatch("bestmatch-visible", atom)
3415 + if not cpv or portage.cpv_getkey(cpv) != cp:
3416 + continue
3417 + if not result or cpv == portage.best([cpv, result]):
3418 + result = cpv
3419 + else:
3420 + db_keys = Package.metadata_keys
3421 + # break out of this loop with highest visible
3422 + # match, checked in descending order
3423 + for cpv in reversed(db.match(atom)):
3424 + if portage.cpv_getkey(cpv) != cp:
3425 + continue
3426 + metadata = izip(db_keys,
3427 + db.aux_get(cpv, db_keys))
3428 + if not self._visible(db, cpv, metadata):
3429 + continue
3430 + if not result or cpv == portage.best([cpv, result]):
3431 + result = cpv
3432 + break
3433 + else:
3434 + raise NotImplementedError(level)
3435 + return result
3436 +
3437 + def execute(self,searchkey):
3438 + """Performs the search for the supplied search key"""
3439 + match_category = 0
3440 + self.searchkey=searchkey
3441 + self.packagematches = []
3442 + if self.searchdesc:
3443 + self.searchdesc=1
3444 + self.matches = {"pkg":[], "desc":[], "set":[]}
3445 + else:
3446 + self.searchdesc=0
3447 + self.matches = {"pkg":[], "set":[]}
3448 + print "Searching... ",
3449 +
3450 + regexsearch = False
3451 + if self.searchkey.startswith('%'):
3452 + regexsearch = True
3453 + self.searchkey = self.searchkey[1:]
3454 + if self.searchkey.startswith('@'):
3455 + match_category = 1
3456 + self.searchkey = self.searchkey[1:]
3457 + if regexsearch:
3458 + self.searchre=re.compile(self.searchkey,re.I)
3459 + else:
3460 + self.searchre=re.compile(re.escape(self.searchkey), re.I)
3461 + for package in self.portdb.cp_all():
3462 + self.spinner.update()
3463 +
3464 + if match_category:
3465 + match_string = package[:]
3466 + else:
3467 + match_string = package.split("/")[-1]
3468 +
3469 + masked=0
3470 + if self.searchre.search(match_string):
3471 + if not self.portdb.xmatch("match-visible", package):
3472 + masked=1
3473 + self.matches["pkg"].append([package,masked])
3474 + elif self.searchdesc: # DESCRIPTION searching
3475 + full_package = self.portdb.xmatch("bestmatch-visible", package)
3476 + if not full_package:
3477 + #no match found; we don't want to query description
3478 + full_package = portage.best(
3479 + self.portdb.xmatch("match-all", package))
3480 + if not full_package:
3481 + continue
3482 + else:
3483 + masked=1
3484 + try:
3485 + full_desc = self.portdb.aux_get(
3486 + full_package, ["DESCRIPTION"])[0]
3487 + except KeyError:
3488 + print "emerge: search: aux_get() failed, skipping"
3489 + continue
3490 + if self.searchre.search(full_desc):
3491 + self.matches["desc"].append([full_package,masked])
3492 +
3493 + self.sdict = self.setconfig.getSets()
3494 + for setname in self.sdict:
3495 + self.spinner.update()
3496 + if match_category:
3497 + match_string = setname
3498 + else:
3499 + match_string = setname.split("/")[-1]
3500 +
3501 + if self.searchre.search(match_string):
3502 + self.matches["set"].append([setname, False])
3503 + elif self.searchdesc:
3504 + if self.searchre.search(
3505 + self.sdict[setname].getMetadata("DESCRIPTION")):
3506 + self.matches["set"].append([setname, False])
3507 +
3508 + self.mlen=0
3509 + for mtype in self.matches:
3510 + self.matches[mtype].sort()
3511 + self.mlen += len(self.matches[mtype])
3512 +
3513 + def addCP(self, cp):
3514 + if not self.portdb.xmatch("match-all", cp):
3515 + return
3516 + masked = 0
3517 + if not self.portdb.xmatch("bestmatch-visible", cp):
3518 + masked = 1
3519 + self.matches["pkg"].append([cp, masked])
3520 + self.mlen += 1
3521 +
3522 + def output(self):
3523 + """Outputs the results of the search."""
3524 + print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
3525 + print "[ Applications found : "+white(str(self.mlen))+" ]"
3526 + print " "
3527 + vardb = self.vartree.dbapi
3528 + for mtype in self.matches:
3529 + for match,masked in self.matches[mtype]:
3530 + full_package = None
3531 + if mtype == "pkg":
3532 + catpack = match
3533 + full_package = self.portdb.xmatch(
3534 + "bestmatch-visible", match)
3535 + if not full_package:
3536 + #no match found; we don't want to query description
3537 + masked=1
3538 + full_package = portage.best(
3539 + self.portdb.xmatch("match-all",match))
3540 + elif mtype == "desc":
3541 + full_package = match
3542 + match = portage.cpv_getkey(match)
3543 + elif mtype == "set":
3544 + print green("*")+" "+white(match)
3545 + print " ", darkgreen("Description:")+" ", self.sdict[match].getMetadata("DESCRIPTION")
3546 + print
3547 + if full_package:
3548 + try:
3549 + desc, homepage, license = self.portdb.aux_get(
3550 + full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
3551 + except KeyError:
3552 + print "emerge: search: aux_get() failed, skipping"
3553 + continue
3554 + if masked:
3555 + print green("*")+" "+white(match)+" "+red("[ Masked ]")
3556 + else:
3557 + print green("*")+" "+white(match)
3558 + myversion = self.getVersion(full_package, search.VERSION_RELEASE)
3559 +
3560 + mysum = [0,0]
3561 + file_size_str = None
3562 + mycat = match.split("/")[0]
3563 + mypkg = match.split("/")[1]
3564 + mycpv = match + "-" + myversion
3565 + myebuild = self.portdb.findname(mycpv)
3566 + if myebuild:
3567 + pkgdir = os.path.dirname(myebuild)
3568 + from portage import manifest
3569 + mf = manifest.Manifest(
3570 + pkgdir, self.settings["DISTDIR"])
3571 + try:
3572 + uri_map = self.portdb.getFetchMap(mycpv)
3573 + except portage.exception.InvalidDependString, e:
3574 + file_size_str = "Unknown (%s)" % (e,)
3575 + del e
3576 + else:
3577 + try:
3578 + mysum[0] = mf.getDistfilesSize(uri_map)
3579 + except KeyError, e:
3580 + file_size_str = "Unknown (missing " + \
3581 + "digest for %s)" % (e,)
3582 + del e
3583 +
3584 + available = False
3585 + for db in self._dbs:
3586 + if db is not vardb and \
3587 + db.cpv_exists(mycpv):
3588 + available = True
3589 + if not myebuild and hasattr(db, "bintree"):
3590 + myebuild = db.bintree.getname(mycpv)
3591 + try:
3592 + mysum[0] = os.stat(myebuild).st_size
3593 + except OSError:
3594 + myebuild = None
3595 + break
3596 +
3597 + if myebuild and file_size_str is None:
3598 + mystr = str(mysum[0] / 1024)
3599 + mycount = len(mystr)
3600 + while (mycount > 3):
3601 + mycount -= 3
3602 + mystr = mystr[:mycount] + "," + mystr[mycount:]
3603 + file_size_str = mystr + " kB"
3604 +
3605 + if self.verbose:
3606 + if available:
3607 + print " ", darkgreen("Latest version available:"),myversion
3608 + print " ", self.getInstallationStatus(mycat+'/'+mypkg)
3609 + if myebuild:
3610 + print " %s %s" % \
3611 + (darkgreen("Size of files:"), file_size_str)
3612 + print " ", darkgreen("Homepage:")+" ",homepage
3613 + print " ", darkgreen("Description:")+" ",desc
3614 + print " ", darkgreen("License:")+" ",license
3615 + print
3616 + #
3617 + # private interface
3618 + #
3619 + def getInstallationStatus(self,package):
3620 + installed_package = self.vartree.dep_bestmatch(package)
3621 + result = ""
3622 + version = self.getVersion(installed_package,search.VERSION_RELEASE)
3623 + if len(version) > 0:
3624 + result = darkgreen("Latest version installed:")+" "+version
3625 + else:
3626 + result = darkgreen("Latest version installed:")+" [ Not Installed ]"
3627 + return result
3628 +
3629 + def getVersion(self,full_package,detail):
3630 + if len(full_package) > 1:
3631 + package_parts = portage.catpkgsplit(full_package)
3632 + if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
3633 + result = package_parts[2]+ "-" + package_parts[3]
3634 + else:
3635 + result = package_parts[2]
3636 + else:
3637 + result = ""
3638 + return result
3639 +
3640
3641 Copied: main/branches/prefix/pym/_emerge/show_invalid_depstring_notice.py (from rev 13669, main/trunk/pym/_emerge/show_invalid_depstring_notice.py)
3642 ===================================================================
3643 --- main/branches/prefix/pym/_emerge/show_invalid_depstring_notice.py (rev 0)
3644 +++ main/branches/prefix/pym/_emerge/show_invalid_depstring_notice.py 2009-06-27 13:35:38 UTC (rev 13708)
3645 @@ -0,0 +1,40 @@
3646 +import logging
3647 +import os
3648 +import textwrap
3649 +
3650 +# for an explanation on this logic, see pym/_emerge/__init__.py
3651 +import os
3652 +import sys
3653 +if os.environ.__contains__("PORTAGE_PYTHONPATH"):
3654 + sys.path.insert(0, os.environ["PORTAGE_PYTHONPATH"])
3655 +else:
3656 + sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "pym"))
3657 +import portage
3658 +
3659 +from portage.util import writemsg_level
3660 +
3661 +def show_invalid_depstring_notice(parent_node, depstring, error_msg):
3662 +
3663 + msg1 = "\n\n!!! Invalid or corrupt dependency specification: " + \
3664 + "\n\n%s\n\n%s\n\n%s\n\n" % (error_msg, parent_node, depstring)
3665 + p_type, p_root, p_key, p_status = parent_node
3666 + msg = []
3667 + if p_status == "nomerge":
3668 + category, pf = portage.catsplit(p_key)
3669 + pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
3670 + msg.append("Portage is unable to process the dependencies of the ")
3671 + msg.append("'%s' package. " % p_key)
3672 + msg.append("In order to correct this problem, the package ")
3673 + msg.append("should be uninstalled, reinstalled, or upgraded. ")
3674 + msg.append("As a temporary workaround, the --nodeps option can ")
3675 + msg.append("be used to ignore all dependencies. For reference, ")
3676 + msg.append("the problematic dependencies can be found in the ")
3677 + msg.append("*DEPEND files located in '%s/'." % pkg_location)
3678 + else:
3679 + msg.append("This package can not be installed. ")
3680 + msg.append("Please notify the '%s' package maintainer " % p_key)
3681 + msg.append("about this problem.")
3682 +
3683 + msg2 = "".join("%s\n" % line for line in textwrap.wrap("".join(msg), 72))
3684 + writemsg_level(msg1 + msg2, level=logging.ERROR, noiselevel=-1)
3685 +
3686
3687 Copied: main/branches/prefix/pym/_emerge/unmerge.py (from rev 13669, main/trunk/pym/_emerge/unmerge.py)
3688 ===================================================================
3689 --- main/branches/prefix/pym/_emerge/unmerge.py (rev 0)
3690 +++ main/branches/prefix/pym/_emerge/unmerge.py 2009-06-27 13:35:38 UTC (rev 13708)
3691 @@ -0,0 +1,525 @@
3692 +import logging
3693 +import os
3694 +import sys
3695 +import textwrap
3696 +from itertools import izip
3697 +
3698 +# for an explanation on this logic, see pym/_emerge/__init__.py
3699 +import os
3700 +import sys
3701 +if os.environ.__contains__("PORTAGE_PYTHONPATH"):
3702 + sys.path.insert(0, os.environ["PORTAGE_PYTHONPATH"])
3703 +else:
3704 + sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "pym"))
3705 +import portage
3706 +
3707 +from portage.output import bold, colorize, darkgreen, green
3708 +from portage.sets import SETPREFIX
3709 +from portage.util import cmp_sort_key
3710 +
3711 +from _emerge.emergelog import emergelog
3712 +from _emerge.Package import Package
3713 +from _emerge.UninstallFailure import UninstallFailure
3714 +from _emerge.userquery import userquery
3715 +from _emerge.countdown import countdown
3716 +
3717 +def unmerge(root_config, myopts, unmerge_action,
3718 + unmerge_files, ldpath_mtimes, autoclean=0,
3719 + clean_world=1, clean_delay=1, ordered=0, raise_on_error=0,
3720 + scheduler=None, writemsg_level=portage.util.writemsg_level):
3721 +
3722 + if clean_world:
3723 + clean_world = myopts.get('--deselect') != 'n'
3724 + quiet = "--quiet" in myopts
3725 + settings = root_config.settings
3726 + sets = root_config.sets
3727 + vartree = root_config.trees["vartree"]
3728 + candidate_catpkgs=[]
3729 + global_unmerge=0
3730 + xterm_titles = "notitles" not in settings.features
3731 + out = portage.output.EOutput()
3732 + pkg_cache = {}
3733 + db_keys = list(vartree.dbapi._aux_cache_keys)
3734 +
3735 + def _pkg(cpv):
3736 + pkg = pkg_cache.get(cpv)
3737 + if pkg is None:
3738 + pkg = Package(cpv=cpv, installed=True,
3739 + metadata=izip(db_keys, vartree.dbapi.aux_get(cpv, db_keys)),
3740 + root_config=root_config,
3741 + type_name="installed")
3742 + pkg_cache[cpv] = pkg
3743 + return pkg
3744 +
3745 + vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3746 + try:
3747 + # At least the parent needs to exist for the lock file.
3748 + portage.util.ensure_dirs(vdb_path)
3749 + except portage.exception.PortageException:
3750 + pass
3751 + vdb_lock = None
3752 + try:
3753 + if os.access(vdb_path, os.W_OK):
3754 + vdb_lock = portage.locks.lockdir(vdb_path)
3755 + realsyslist = sets["system"].getAtoms()
3756 + syslist = []
3757 + for x in realsyslist:
3758 + mycp = portage.dep_getkey(x)
3759 + if mycp in settings.getvirtuals():
3760 + providers = []
3761 + for provider in settings.getvirtuals()[mycp]:
3762 + if vartree.dbapi.match(provider):
3763 + providers.append(provider)
3764 + if len(providers) == 1:
3765 + syslist.extend(providers)
3766 + else:
3767 + syslist.append(mycp)
3768 +
3769 + mysettings = portage.config(clone=settings)
3770 +
3771 + if not unmerge_files:
3772 + if unmerge_action == "unmerge":
3773 + print
3774 + print bold("emerge unmerge") + " can only be used with specific package names"
3775 + print
3776 + return 0
3777 + else:
3778 + global_unmerge = 1
3779 +
3780 + localtree = vartree
3781 + # process all arguments and add all
3782 + # valid db entries to candidate_catpkgs
3783 + if global_unmerge:
3784 + if not unmerge_files:
3785 + candidate_catpkgs.extend(vartree.dbapi.cp_all())
3786 + else:
3787 + #we've got command-line arguments
3788 + if not unmerge_files:
3789 + print "\nNo packages to unmerge have been provided.\n"
3790 + return 0
3791 + for x in unmerge_files:
3792 + arg_parts = x.split('/')
3793 + if x[0] not in [".","/"] and \
3794 + arg_parts[-1][-7:] != ".ebuild":
3795 + #possible cat/pkg or dep; treat as such
3796 + candidate_catpkgs.append(x)
3797 + elif unmerge_action in ["prune","clean"]:
3798 + print "\n!!! Prune and clean do not accept individual" + \
3799 + " ebuilds as arguments;\n skipping.\n"
3800 + continue
3801 + else:
3802 + # it appears that the user is specifying an installed
3803 + # ebuild and we're in "unmerge" mode, so it's ok.
3804 + if not os.path.exists(x):
3805 + print "\n!!! The path '"+x+"' doesn't exist.\n"
3806 + return 0
3807 +
3808 + absx = os.path.abspath(x)
3809 + sp_absx = absx.split("/")
3810 + if sp_absx[-1][-7:] == ".ebuild":
3811 + del sp_absx[-1]
3812 + absx = "/".join(sp_absx)
3813 +
3814 + sp_absx_len = len(sp_absx)
3815 +
3816 + vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3817 + vdb_len = len(vdb_path)
3818 +
3819 + sp_vdb = vdb_path.split("/")
3820 + sp_vdb_len = len(sp_vdb)
3821 +
3822 + if not os.path.exists(absx+"/CONTENTS"):
3823 + print "!!! Not a valid db dir: "+str(absx)
3824 + return 0
3825 +
3826 + if sp_absx_len <= sp_vdb_len:
3827 + # The Path is shorter... so it can't be inside the vdb.
3828 + print sp_absx
3829 + print absx
3830 + print "\n!!!",x,"cannot be inside "+ \
3831 + vdb_path+"; aborting.\n"
3832 + return 0
3833 +
3834 + for idx in range(0,sp_vdb_len):
3835 + if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
3836 + print sp_absx
3837 + print absx
3838 + print "\n!!!", x, "is not inside "+\
3839 + vdb_path+"; aborting.\n"
3840 + return 0
3841 +
3842 + print "="+"/".join(sp_absx[sp_vdb_len:])
3843 + candidate_catpkgs.append(
3844 + "="+"/".join(sp_absx[sp_vdb_len:]))
3845 +
3846 + newline=""
3847 + if (not "--quiet" in myopts):
3848 + newline="\n"
3849 + if settings["ROOT"] != "/":
3850 + writemsg_level(darkgreen(newline+ \
3851 + ">>> Using system located in ROOT tree %s\n" % \
3852 + settings["ROOT"]))
3853 +
3854 + if (("--pretend" in myopts) or ("--ask" in myopts)) and \
3855 + not ("--quiet" in myopts):
3856 + writemsg_level(darkgreen(newline+\
3857 + ">>> These are the packages that would be unmerged:\n"))
3858 +
3859 + # Preservation of order is required for --depclean and --prune so
3860 + # that dependencies are respected. Use all_selected to eliminate
3861 + # duplicate packages since the same package may be selected by
3862 + # multiple atoms.
3863 + pkgmap = []
3864 + all_selected = set()
3865 + for x in candidate_catpkgs:
3866 + # cycle through all our candidate deps and determine
3867 + # what will and will not get unmerged
3868 + try:
3869 + mymatch = vartree.dbapi.match(x)
3870 + except portage.exception.AmbiguousPackageName, errpkgs:
3871 + print "\n\n!!! The short ebuild name \"" + \
3872 + x + "\" is ambiguous. Please specify"
3873 + print "!!! one of the following fully-qualified " + \
3874 + "ebuild names instead:\n"
3875 + for i in errpkgs[0]:
3876 + print " " + green(i)
3877 + print
3878 + sys.exit(1)
3879 +
3880 + if not mymatch and x[0] not in "<>=~":
3881 + mymatch = localtree.dep_match(x)
3882 + if not mymatch:
3883 + portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
3884 + (x, unmerge_action), noiselevel=-1)
3885 + continue
3886 +
3887 + pkgmap.append(
3888 + {"protected": set(), "selected": set(), "omitted": set()})
3889 + mykey = len(pkgmap) - 1
3890 + if unmerge_action=="unmerge":
3891 + for y in mymatch:
3892 + if y not in all_selected:
3893 + pkgmap[mykey]["selected"].add(y)
3894 + all_selected.add(y)
3895 + elif unmerge_action == "prune":
3896 + if len(mymatch) == 1:
3897 + continue
3898 + best_version = mymatch[0]
3899 + best_slot = vartree.getslot(best_version)
3900 + best_counter = vartree.dbapi.cpv_counter(best_version)
3901 + for mypkg in mymatch[1:]:
3902 + myslot = vartree.getslot(mypkg)
3903 + mycounter = vartree.dbapi.cpv_counter(mypkg)
3904 + if (myslot == best_slot and mycounter > best_counter) or \
3905 + mypkg == portage.best([mypkg, best_version]):
3906 + if myslot == best_slot:
3907 + if mycounter < best_counter:
3908 + # On slot collision, keep the one with the
3909 + # highest counter since it is the most
3910 + # recently installed.
3911 + continue
3912 + best_version = mypkg
3913 + best_slot = myslot
3914 + best_counter = mycounter
3915 + pkgmap[mykey]["protected"].add(best_version)
3916 + pkgmap[mykey]["selected"].update(mypkg for mypkg in mymatch \
3917 + if mypkg != best_version and mypkg not in all_selected)
3918 + all_selected.update(pkgmap[mykey]["selected"])
3919 + else:
3920 + # unmerge_action == "clean"
3921 + slotmap={}
3922 + for mypkg in mymatch:
3923 + if unmerge_action == "clean":
3924 + myslot = localtree.getslot(mypkg)
3925 + else:
3926 + # since we're pruning, we don't care about slots
3927 + # and put all the pkgs in together
3928 + myslot = 0
3929 + if myslot not in slotmap:
3930 + slotmap[myslot] = {}
3931 + slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)] = mypkg
3932 +
3933 + for mypkg in vartree.dbapi.cp_list(
3934 + portage.dep_getkey(mymatch[0])):
3935 + myslot = vartree.getslot(mypkg)
3936 + if myslot not in slotmap:
3937 + slotmap[myslot] = {}
3938 + slotmap[myslot][vartree.dbapi.cpv_counter(mypkg)] = mypkg
3939 +
3940 + for myslot in slotmap:
3941 + counterkeys = slotmap[myslot].keys()
3942 + if not counterkeys:
3943 + continue
3944 + counterkeys.sort()
3945 + pkgmap[mykey]["protected"].add(
3946 + slotmap[myslot][counterkeys[-1]])
3947 + del counterkeys[-1]
3948 +
3949 + for counter in counterkeys[:]:
3950 + mypkg = slotmap[myslot][counter]
3951 + if mypkg not in mymatch:
3952 + counterkeys.remove(counter)
3953 + pkgmap[mykey]["protected"].add(
3954 + slotmap[myslot][counter])
3955 +
3956 + #be pretty and get them in order of merge:
3957 + for ckey in counterkeys:
3958 + mypkg = slotmap[myslot][ckey]
3959 + if mypkg not in all_selected:
3960 + pkgmap[mykey]["selected"].add(mypkg)
3961 + all_selected.add(mypkg)
3962 + # ok, now the last-merged package
3963 + # is protected, and the rest are selected
3964 + numselected = len(all_selected)
3965 + if global_unmerge and not numselected:
3966 + portage.writemsg_stdout("\n>>> No outdated packages were found on your system.\n")
3967 + return 0
3968 +
3969 + if not numselected:
3970 + portage.writemsg_stdout(
3971 + "\n>>> No packages selected for removal by " + \
3972 + unmerge_action + "\n")
3973 + return 0
3974 + finally:
3975 + if vdb_lock:
3976 + vartree.dbapi.flush_cache()
3977 + portage.locks.unlockdir(vdb_lock)
3978 +
3979 + from portage.sets.base import EditablePackageSet
3980 +
3981 + # generate a list of package sets that are directly or indirectly listed in "world",
3982 + # as there is no persistent list of "installed" sets
3983 + installed_sets = ["world"]
3984 + stop = False
3985 + pos = 0
3986 + while not stop:
3987 + stop = True
3988 + pos = len(installed_sets)
3989 + for s in installed_sets[pos - 1:]:
3990 + if s not in sets:
3991 + continue
3992 + candidates = [x[len(SETPREFIX):] for x in sets[s].getNonAtoms() if x.startswith(SETPREFIX)]
3993 + if candidates:
3994 + stop = False
3995 + installed_sets += candidates
3996 + installed_sets = [x for x in installed_sets if x not in root_config.setconfig.active]
3997 + del stop, pos
3998 +
3999 + # we don't want to unmerge packages that are still listed in user-editable package sets
4000 + # listed in "world" as they would be remerged on the next update of "world" or the
4001 + # relevant package sets.
4002 + unknown_sets = set()
4003 + for cp in xrange(len(pkgmap)):
4004 + for cpv in pkgmap[cp]["selected"].copy():
4005 + try:
4006 + pkg = _pkg(cpv)
4007 + except KeyError:
4008 + # It could have been uninstalled
4009 + # by a concurrent process.
4010 + continue
4011 +
4012 + if unmerge_action != "clean" and \
4013 + root_config.root == "/" and \
4014 + portage.match_from_list(
4015 + portage.const.PORTAGE_PACKAGE_ATOM, [pkg]):
4016 + msg = ("Not unmerging package %s since there is no valid " + \
4017 + "reason for portage to unmerge itself.") % (pkg.cpv,)
4018 + for line in textwrap.wrap(msg, 75):
4019 + out.eerror(line)
4020 + # adjust pkgmap so the display output is correct
4021 + pkgmap[cp]["selected"].remove(cpv)
4022 + all_selected.remove(cpv)
4023 + pkgmap[cp]["protected"].add(cpv)
4024 + continue
4025 +
4026 + parents = []
4027 + for s in installed_sets:
4028 + # skip sets that the user requested to unmerge, and skip world
4029 + # unless we're unmerging a package set (as the package would be
4030 + # removed from "world" later on)
4031 + if s in root_config.setconfig.active or (s == "world" and not root_config.setconfig.active):
4032 + continue
4033 +
4034 + if s not in sets:
4035 + if s in unknown_sets:
4036 + continue
4037 + unknown_sets.add(s)
4038 + out = portage.output.EOutput()
4039 + out.eerror(("Unknown set '@%s' in " + \
4040 + "%svar/lib/portage/world_sets") % \
4041 + (s, root_config.root))
4042 + continue
4043 +
4044 + # only check instances of EditablePackageSet as other classes are generally used for
4045 + # special purposes and can be ignored here (and are usually generated dynamically, so the
4046 + # user can't do much about them anyway)
4047 + if isinstance(sets[s], EditablePackageSet):
4048 +
4049 + # This is derived from a snippet of code in the
4050 + # depgraph._iter_atoms_for_pkg() method.
4051 + for atom in sets[s].iterAtomsForPackage(pkg):
4052 + inst_matches = vartree.dbapi.match(atom)
4053 + inst_matches.reverse() # descending order
4054 + higher_slot = None
4055 + for inst_cpv in inst_matches:
4056 + try:
4057 + inst_pkg = _pkg(inst_cpv)
4058 + except KeyError:
4059 + # It could have been uninstalled
4060 + # by a concurrent process.
4061 + continue
4062 +
4063 + if inst_pkg.cp != atom.cp:
4064 + continue
4065 + if pkg >= inst_pkg:
4066 + # This is descending order, and we're not
4067 + # interested in any versions <= pkg given.
4068 + break
4069 + if pkg.slot_atom != inst_pkg.slot_atom:
4070 + higher_slot = inst_pkg
4071 + break
4072 + if higher_slot is None:
4073 + parents.append(s)
4074 + break
4075 + if parents:
4076 + #print colorize("WARN", "Package %s is going to be unmerged," % cpv)
4077 + #print colorize("WARN", "but still listed in the following package sets:")
4078 + #print " %s\n" % ", ".join(parents)
4079 + print colorize("WARN", "Not unmerging package %s as it is" % cpv)
4080 + print colorize("WARN", "still referenced by the following package sets:")
4081 + print " %s\n" % ", ".join(parents)
4082 + # adjust pkgmap so the display output is correct
4083 + pkgmap[cp]["selected"].remove(cpv)
4084 + all_selected.remove(cpv)
4085 + pkgmap[cp]["protected"].add(cpv)
4086 +
4087 + del installed_sets
4088 +
4089 + numselected = len(all_selected)
4090 + if not numselected:
4091 + writemsg_level(
4092 + "\n>>> No packages selected for removal by " + \
4093 + unmerge_action + "\n")
4094 + return 0
4095 +
4096 + # Unmerge order only matters in some cases
4097 + if not ordered:
4098 + unordered = {}
4099 + for d in pkgmap:
4100 + selected = d["selected"]
4101 + if not selected:
4102 + continue
4103 + cp = portage.cpv_getkey(iter(selected).next())
4104 + cp_dict = unordered.get(cp)
4105 + if cp_dict is None:
4106 + cp_dict = {}
4107 + unordered[cp] = cp_dict
4108 + for k in d:
4109 + cp_dict[k] = set()
4110 + for k, v in d.iteritems():
4111 + cp_dict[k].update(v)
4112 + pkgmap = [unordered[cp] for cp in sorted(unordered)]
4113 +
4114 + for x in xrange(len(pkgmap)):
4115 + selected = pkgmap[x]["selected"]
4116 + if not selected:
4117 + continue
4118 + for mytype, mylist in pkgmap[x].iteritems():
4119 + if mytype == "selected":
4120 + continue
4121 + mylist.difference_update(all_selected)
4122 + cp = portage.cpv_getkey(iter(selected).next())
4123 + for y in localtree.dep_match(cp):
4124 + if y not in pkgmap[x]["omitted"] and \
4125 + y not in pkgmap[x]["selected"] and \
4126 + y not in pkgmap[x]["protected"] and \
4127 + y not in all_selected:
4128 + pkgmap[x]["omitted"].add(y)
4129 + if global_unmerge and not pkgmap[x]["selected"]:
4130 + #avoid cluttering the preview printout with stuff that isn't getting unmerged
4131 + continue
4132 + if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and cp in syslist:
4133 + writemsg_level(colorize("BAD","\a\n\n!!! " + \
4134 + "'%s' is part of your system profile.\n" % cp),
4135 + level=logging.WARNING, noiselevel=-1)
4136 + writemsg_level(colorize("WARN","\a!!! Unmerging it may " + \
4137 + "be damaging to your system.\n\n"),
4138 + level=logging.WARNING, noiselevel=-1)
4139 + if clean_delay and "--pretend" not in myopts and "--ask" not in myopts:
4140 + countdown(int(settings["EMERGE_WARNING_DELAY"]),
4141 + colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
4142 + if not quiet:
4143 + writemsg_level("\n %s\n" % (bold(cp),), noiselevel=-1)
4144 + else:
4145 + writemsg_level(bold(cp) + ": ", noiselevel=-1)
4146 + for mytype in ["selected","protected","omitted"]:
4147 + if not quiet:
4148 + writemsg_level((mytype + ": ").rjust(14), noiselevel=-1)
4149 + if pkgmap[x][mytype]:
4150 + sorted_pkgs = [portage.catpkgsplit(mypkg)[1:] for mypkg in pkgmap[x][mytype]]
4151 + sorted_pkgs.sort(key=cmp_sort_key(portage.pkgcmp))
4152 + for pn, ver, rev in sorted_pkgs:
4153 + if rev == "r0":
4154 + myversion = ver
4155 + else:
4156 + myversion = ver + "-" + rev
4157 + if mytype == "selected":
4158 + writemsg_level(
4159 + colorize("UNMERGE_WARN", myversion + " "),
4160 + noiselevel=-1)
4161 + else:
4162 + writemsg_level(
4163 + colorize("GOOD", myversion + " "), noiselevel=-1)
4164 + else:
4165 + writemsg_level("none ", noiselevel=-1)
4166 + if not quiet:
4167 + writemsg_level("\n", noiselevel=-1)
4168 + if quiet:
4169 + writemsg_level("\n", noiselevel=-1)
4170 +
4171 + writemsg_level("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
4172 + " packages are slated for removal.\n")
4173 + writemsg_level(">>> " + colorize("GOOD", "'Protected'") + \
4174 + " and " + colorize("GOOD", "'omitted'") + \
4175 + " packages will not be removed.\n\n")
4176 +
4177 + if "--pretend" in myopts:
4178 + #we're done... return
4179 + return 0
4180 + if "--ask" in myopts:
4181 + if userquery("Would you like to unmerge these packages?")=="No":
4182 + # enter pretend mode for correct formatting of results
4183 + myopts["--pretend"] = True
4184 + print
4185 + print "Quitting."
4186 + print
4187 + return 0
4188 + #the real unmerging begins, after a short delay....
4189 + if clean_delay and not autoclean:
4190 + countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
4191 +
4192 + for x in xrange(len(pkgmap)):
4193 + for y in pkgmap[x]["selected"]:
4194 + writemsg_level(">>> Unmerging "+y+"...\n", noiselevel=-1)
4195 + emergelog(xterm_titles, "=== Unmerging... ("+y+")")
4196 + mysplit = y.split("/")
4197 + #unmerge...
4198 + retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
4199 + mysettings, unmerge_action not in ["clean","prune"],
4200 + vartree=vartree, ldpath_mtimes=ldpath_mtimes,
4201 + scheduler=scheduler)
4202 +
4203 + if retval != os.EX_OK:
4204 + emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
4205 + if raise_on_error:
4206 + raise UninstallFailure(retval)
4207 + sys.exit(retval)
4208 + else:
4209 + if clean_world and hasattr(sets["world"], "cleanPackage"):
4210 + sets["world"].cleanPackage(vartree.dbapi, y)
4211 + emergelog(xterm_titles, " >>> unmerge success: "+y)
4212 + if clean_world and hasattr(sets["world"], "remove"):
4213 + for s in root_config.setconfig.active:
4214 + sets["world"].remove(SETPREFIX+s)
4215 + return 1
4216 +
4217
4218 Copied: main/branches/prefix/pym/_emerge/userquery.py (from rev 13669, main/trunk/pym/_emerge/userquery.py)
4219 ===================================================================
4220 --- main/branches/prefix/pym/_emerge/userquery.py (rev 0)
4221 +++ main/branches/prefix/pym/_emerge/userquery.py 2009-06-27 13:35:38 UTC (rev 13708)
4222 @@ -0,0 +1,44 @@
4223 +import sys
4224 +
4225 +from portage.output import bold, create_color_func
4226 +
4227 +def userquery(prompt, responses=None, colours=None):
4228 + """Displays a prompt and a set of responses, then waits for a response
4229 + which is checked against the responses and the first to match is
4230 + returned. An empty response will match the first value in responses. The
4231 + input buffer is *not* cleared prior to the prompt!
4232 +
4233 + prompt: a String.
4234 + responses: a List of Strings.
4235 + colours: a List of Functions taking and returning a String, used to
4236 + process the responses for display. Typically these will be functions
4237 + like red() but could be e.g. lambda x: "DisplayString".
4238 + If responses is omitted, defaults to ["Yes", "No"], [green, red].
4239 + If only colours is omitted, defaults to [bold, ...].
4240 +
4241 + Returns a member of the List responses. (If called without optional
4242 + arguments, returns "Yes" or "No".)
4243 + KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
4244 + printed."""
4245 + if responses is None:
4246 + responses = ["Yes", "No"]
4247 + colours = [
4248 + create_color_func("PROMPT_CHOICE_DEFAULT"),
4249 + create_color_func("PROMPT_CHOICE_OTHER")
4250 + ]
4251 + elif colours is None:
4252 + colours=[bold]
4253 + colours=(colours*len(responses))[:len(responses)]
4254 + print bold(prompt),
4255 + try:
4256 + while True:
4257 + response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
4258 + for key in responses:
4259 + # An empty response will match the first value in responses.
4260 + if response.upper()==key[:len(response)].upper():
4261 + return key
4262 + print "Sorry, response '%s' not understood." % response,
4263 + except (EOFError, KeyboardInterrupt):
4264 + print "Interrupted."
4265 + sys.exit(1)
4266 +
4267
4268 Copied: main/branches/prefix/pym/_emerge/visible.py (from rev 13669, main/trunk/pym/_emerge/visible.py)
4269 ===================================================================
4270 --- main/branches/prefix/pym/_emerge/visible.py (rev 0)
4271 +++ main/branches/prefix/pym/_emerge/visible.py 2009-06-27 13:35:38 UTC (rev 13708)
4272 @@ -0,0 +1,47 @@
4273 +# for an explanation on this logic, see pym/_emerge/__init__.py
4274 +import os
4275 +import sys
4276 +if os.environ.__contains__("PORTAGE_PYTHONPATH"):
4277 + sys.path.insert(0, os.environ["PORTAGE_PYTHONPATH"])
4278 +else:
4279 + sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "pym"))
4280 +import portage
4281 +
4282 +def visible(pkgsettings, pkg):
4283 + """
4284 + Check if a package is visible. This can raise an InvalidDependString
4285 + exception if LICENSE is invalid.
4286 + TODO: optionally generate a list of masking reasons
4287 + @rtype: Boolean
4288 + @returns: True if the package is visible, False otherwise.
4289 + """
4290 + if not pkg.metadata["SLOT"]:
4291 + return False
4292 + if not pkg.installed:
4293 + if not pkgsettings._accept_chost(pkg.cpv, pkg.metadata):
4294 + return False
4295 + if pkg.built and not pkg.installed:
4296 + # we can have an old binary which has no EPREFIX information
4297 + if "EPREFIX" not in pkg.metadata or not pkg.metadata["EPREFIX"]:
4298 + return False
4299 + if len(pkg.metadata["EPREFIX"].strip()) < len(pkgsettings["EPREFIX"]):
4300 + return False
4301 + eapi = pkg.metadata["EAPI"]
4302 + if not portage.eapi_is_supported(eapi):
4303 + return False
4304 + if not pkg.installed:
4305 + if portage._eapi_is_deprecated(eapi):
4306 + return False
4307 + if pkgsettings._getMissingKeywords(pkg.cpv, pkg.metadata):
4308 + return False
4309 + if pkgsettings._getMaskAtom(pkg.cpv, pkg.metadata):
4310 + return False
4311 + if pkgsettings._getProfileMaskAtom(pkg.cpv, pkg.metadata):
4312 + return False
4313 + try:
4314 + if pkgsettings._getMissingLicenses(pkg.cpv, pkg.metadata):
4315 + return False
4316 + except portage.exception.InvalidDependString:
4317 + return False
4318 + return True
4319 +