Gentoo Archives: gentoo-commits

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