Gentoo Archives: gentoo-commits

From: "Fabian Groffen (grobian)" <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r11172 - in main/branches/prefix: . man pym/_emerge pym/portage pym/portage/dbapi
Date: Wed, 23 Jul 2008 06:54:30
Message-Id: E1KLYF0-0001kt-0P@stork.gentoo.org
1 Author: grobian
2 Date: 2008-07-23 06:54:24 +0000 (Wed, 23 Jul 2008)
3 New Revision: 11172
4
5 Modified:
6 main/branches/prefix/NEWS
7 main/branches/prefix/man/emerge.1
8 main/branches/prefix/pym/_emerge/__init__.py
9 main/branches/prefix/pym/_emerge/help.py
10 main/branches/prefix/pym/portage/__init__.py
11 main/branches/prefix/pym/portage/dbapi/vartree.py
12 Log:
13 Merged from trunk 11157:11169
14
15 | 11158 | Fix --depclean/--prune to add lib providers and their |
16 | zmedico | dependencies to the graph and create a new clean list when |
17 | | necessary. This completes the fix for bug #230053. |
18
19 | 11159 | Adjust --fetchonly failure messages to work better with |
20 | zmedico | background mode. |
21
22 | 11160 | Adjust status messages for --fetchonly mode. |
23 | zmedico | |
24
25 | 11161 | Redirect dblink._preserve_libs() messages to the log when in |
26 | zmedico | background mode. |
27
28 | 11162 | Make --pretend disable background mode and imply --jobs=1. |
29 | zmedico | |
30
31 | 11163 | Disable "Installing" status messages when in --pretend or |
32 | zmedico | --buildpkgonly mode. |
33
34 | 11164 | Redirect build log eqawarn messages to the log file when in |
35 | zmedico | background mode. |
36
37 | 11165 | Show the number of failed packages in the status display. |
38 | zmedico | |
39
40 | 11166 | Fix resume_depgraph() so that it doesn't raise an |
41 | zmedico | AssertionError due to unsatisfied PDEPEND. |
42
43 | 11167 | In dblink.unmerge(), redirect preserve-libs "!needed" |
44 | zmedico | messages to the log file when in background mode. |
45
46 | 11168 | Update --depclean and --prune, removing warnings about |
47 | zmedico | libraries since those are now automatically accounted for. |
48
49 | 11169 | Handle UnsatisfiedResumeDep in |
50 | zmedico | Scheduler._calc_resume_list(). |
51
52
53 Modified: main/branches/prefix/NEWS
54 ===================================================================
55 --- main/branches/prefix/NEWS 2008-07-23 06:52:10 UTC (rev 11171)
56 +++ main/branches/prefix/NEWS 2008-07-23 06:54:24 UTC (rev 11172)
57 @@ -3,6 +3,8 @@
58 portage-2.2
59 -------------
60
61 +* Add link level dependency awareness to emerge --depclean and --prune actions
62 + in order to protect against uninstallation of required libraries.
63 * Add emerge --jobs and --load-average options which specify behavior
64 for building packages in parallel or for generating metadata in parallel
65 with emerge --regen.
66
67 Modified: main/branches/prefix/man/emerge.1
68 ===================================================================
69 --- main/branches/prefix/man/emerge.1 2008-07-23 06:52:10 UTC (rev 11171)
70 +++ main/branches/prefix/man/emerge.1 2008-07-23 06:54:24 UTC (rev 11172)
71 @@ -103,19 +103,22 @@
72 .BR \-\-depclean
73 Cleans the system by removing packages that are not associated
74 with explicitly merged packages. Depclean works by creating the
75 -full dependency tree from the system and world sets,
76 +full dependency tree from the @system and @world sets,
77 then comparing it to installed packages. Packages installed, but
78 not part of the dependency tree, will be uninstalled by depclean.
79 -Inexperienced users are advised to use \fB\-\-pretend\fR
80 -with this option in order to see a preview of which packages
81 -will be uninstalled.
82 +See \fB\-\-with\-bdeps\fR for behavior with respect to build time dependencies
83 +that are not strictly required. Packages that are part of the world set will
84 +always be kept. They can be manually added to this set with \fIemerge
85 +\-\-noreplace <atom>\fR. As a safety measure, depclean will not remove any
86 +packages unless *all* required dependencies have been resolved. As a
87 +consequence, it is often necessary to run \fIemerge \-\-update \-\-newuse
88 +\-\-deep \-\-oneshot @system @world\fR prior to depclean.
89
90 -\fBWARNING: Removing some
91 -packages may cause packages which link to the removed package
92 -to stop working and complain about missing libraries.\fR
93 -Rebuild the complaining package to fix this issue. Also see
94 -\fB\-\-with\-bdeps\fR for behavior with respect to build time dependencies that
95 -are not strictly required. Note that packages listed in
96 +\fBWARNING:\fR
97 +Inexperienced users are advised to use \fB\-\-pretend\fR with this
98 +option in order to see a preview of which packages
99 +will be uninstalled. Always study the list of packages
100 +to be cleaned for any obvious mistakes. Note that packages listed in
101 package.provided (see \fBportage\fR(5)) may be removed by
102 depclean, even if they are part of the world set.
103
104 @@ -150,11 +153,9 @@
105 .TP
106 .BR "\-\-prune " (\fB\-P\fR)
107 \fBWARNING: This action can remove important packages!\fR Removes all but the
108 -highest installed version of a package from your system. This action doesn't
109 -verify the possible binary compatibility between versions and can thus remove
110 -essential dependencies from your system. Use \fB\-\-prune\fR together with
111 -\fB\-\-verbose\fR to show reverse dependencies or with \fB\-\-nodeps\fR to
112 -ignore all dependencies.
113 +highest installed version of a package from your system. Use \fB\-\-prune\fR
114 +together with \fB\-\-verbose\fR to show reverse dependencies or with
115 +\fB\-\-nodeps\fR to ignore all dependencies.
116 .TP
117 .BR \-\-regen
118 Causes portage to check and update the dependency cache of all ebuilds in the
119
120 Modified: main/branches/prefix/pym/_emerge/__init__.py
121 ===================================================================
122 --- main/branches/prefix/pym/_emerge/__init__.py 2008-07-23 06:52:10 UTC (rev 11171)
123 +++ main/branches/prefix/pym/_emerge/__init__.py 2008-07-23 06:54:24 UTC (rev 11172)
124 @@ -29,6 +29,7 @@
125 import select
126 import shlex
127 import shutil
128 +import textwrap
129 import urlparse
130 import weakref
131 import gc
132 @@ -2429,8 +2430,9 @@
133
134 if opts.fetchonly:
135 if self._final_exit(fetcher) != os.EX_OK:
136 - eerror("!!! Fetch for %s failed, continuing..." % pkg.cpv,
137 - phase="unpack", key=pkg.cpv)
138 + if not self.background:
139 + eerror("Fetch for %s failed, continuing..." % pkg.cpv,
140 + phase="unpack", key=pkg.cpv)
141 self.wait()
142 return
143
144 @@ -2761,7 +2763,17 @@
145 def _ebuild_exit(self, ebuild_process):
146
147 if self.phase == "install":
148 - portage._check_build_log(self.settings)
149 + out = None
150 + log_path = self.settings.get("PORTAGE_LOG_FILE")
151 + log_file = None
152 + if self.background and log_path is not None:
153 + log_file = open(log_path, 'a')
154 + out = log_file
155 + try:
156 + portage._check_build_log(self.settings, out=out)
157 + finally:
158 + if log_file is not None:
159 + log_file.close()
160
161 if self._default_exit(ebuild_process) != os.EX_OK:
162 self.wait()
163 @@ -3391,6 +3403,9 @@
164 if pkg.type_name == "binary":
165 action_desc = "Extracting"
166
167 + if build_opts.fetchonly:
168 + action_desc = "Fetching"
169 +
170 if not build_opts.pretend:
171
172 self.statusMessage("%s (%s of %s) %s %s %s" % \
173 @@ -3499,9 +3514,12 @@
174 action_desc = "Installing"
175 preposition = "to"
176
177 - self.merge.statusMessage("%s %s %s %s" % \
178 - (action_desc, colorize("GOOD", pkg.cpv),
179 - preposition, pkg.root))
180 + if not self.merge.build_opts.fetchonly and \
181 + not self.merge.build_opts.pretend and \
182 + not self.merge.build_opts.buildpkgonly:
183 + self.merge.statusMessage("%s %s %s %s" % \
184 + (action_desc, colorize("GOOD", pkg.cpv),
185 + preposition, pkg.root))
186
187 self.returncode = self.merge.merge()
188 self.wait()
189 @@ -8448,8 +8466,8 @@
190
191 class JobStatusDisplay(object):
192
193 - _bound_properties = ("curval", "running")
194 - _jobs_column_width = 42
195 + _bound_properties = ("curval", "failed", "running")
196 + _jobs_column_width = 48
197
198 # Don't update the display unless at least this much
199 # time has passed, in units of seconds.
200 @@ -8577,6 +8595,7 @@
201
202 def _property_change(self, name, old_value, new_value):
203 self._changed = True
204 + self.display()
205
206 def _load_avg_str(self, digits=2):
207 try:
208 @@ -8613,7 +8632,7 @@
209 curval_str = str(self.curval)
210 maxval_str = str(self.maxval)
211 running_str = str(self.running)
212 - merges_str = str(self.merges)
213 + failed_str = str(self.failed)
214 load_avg_str = self._load_avg_str()
215
216 color_output = StringIO.StringIO()
217 @@ -8642,21 +8661,18 @@
218 f.pop_style()
219 f.add_literal_data(" running")
220
221 - #if self.merges:
222 - if False:
223 + if self.failed:
224 f.add_literal_data(", ")
225 f.push_style(number_style)
226 - f.add_literal_data(merges_str)
227 + f.add_literal_data(failed_str)
228 f.pop_style()
229 - f.add_literal_data(" merge")
230 - if self.merges != 1:
231 - f.add_literal_data("s")
232 + f.add_literal_data(" failed")
233
234 padding = self._jobs_column_width - len(plain_output.getvalue())
235 if padding > 0:
236 f.add_literal_data(padding * " ")
237
238 - f.add_literal_data("Load average: ")
239 + f.add_literal_data("Load avg: ")
240 f.add_literal_data(load_avg_str)
241
242 self._update(color_output.getvalue())
243 @@ -8843,7 +8859,8 @@
244 @rtype: bool
245 @returns: True if background mode is enabled, False otherwise.
246 """
247 - background = self._max_jobs > 1 or "--quiet" in self.myopts
248 + background = (self._max_jobs > 1 or "--quiet" in self.myopts) and \
249 + "--pretend" not in self.myopts
250
251 self._status_display.quiet = \
252 not background or \
253 @@ -9116,16 +9133,27 @@
254 "--fetch-all-uri" in self.myopts):
255 return
256
257 - sys.stderr.write("\n\n!!! Some fetch errors were " + \
258 - "encountered. Please see above for details.\n\n")
259 + if self._background:
260 + msg = "Some fetch errors were " + \
261 + "encountered. Please see %s for details." % \
262 + self._fetch_log
263 + else:
264 + msg = "Some fetch errors were " + \
265 + "encountered. Please see above for details."
266
267 + prefix = bad(" * ")
268 + msg = "".join("%s%s\n" % (prefix, line) \
269 + for line in textwrap.wrap(msg, 70))
270 + writemsg_level(msg, level=logging.ERROR, noiselevel=-1)
271 +
272 + msg = []
273 + msg.append("")
274 for cpv in failed_fetches:
275 - sys.stderr.write(" ")
276 - sys.stderr.write(cpv)
277 - sys.stderr.write("\n")
278 + msg.append(" %s" % cpv)
279 + msg.append("")
280 + writemsg_level("".join("%s%s\n" % (prefix, line) \
281 + for line in msg), level=logging.ERROR, noiselevel=-1)
282
283 - sys.stderr.write("\n")
284 -
285 def _is_restart_scheduled(self):
286 """
287 Check if the merge list contains a replacement
288 @@ -9254,6 +9282,9 @@
289 break
290
291 dropped_tasks = self._calc_resume_list()
292 + if dropped_tasks is None:
293 + break
294 +
295 clear_caches(self.trees)
296 if not self._mergelist:
297 break
298 @@ -9349,6 +9380,7 @@
299 pkg = merge.merge.pkg
300 if merge.returncode != os.EX_OK:
301 self._failed_pkgs.append((pkg, merge.returncode))
302 + self._status_display.failed = len(self._failed_pkgs)
303 return
304
305 self._task_complete(pkg)
306 @@ -9383,10 +9415,10 @@
307 self._status_display.merges = len(self._task_queues.merge)
308 else:
309 self._failed_pkgs.append((build.pkg, build.returncode))
310 + self._status_display.failed = len(self._failed_pkgs)
311 self._deallocate_config(build.settings)
312 self._jobs -= 1
313 self._status_display.running = self._jobs
314 - self._status_display.display()
315 self._schedule()
316
317 def _extract_exit(self, build):
318 @@ -9498,7 +9530,8 @@
319
320 # Only allow 1 job max if a restart is scheduled
321 # due to portage update.
322 - if self._is_restart_scheduled():
323 + if self._is_restart_scheduled() or \
324 + "--pretend" in self.myopts:
325 self._set_max_jobs(1)
326
327 merge_queue = self._task_queues.merge
328 @@ -9620,6 +9653,9 @@
329 """
330 Use the current resume list to calculate a new one,
331 dropping any packages with unsatisfied deps.
332 + @rtype: set
333 + @returns: a possibly empty set of dropped tasks, or
334 + None if an error occurs.
335 """
336 print colorize("GOOD", "*** Resuming merge...")
337
338 @@ -9641,13 +9677,47 @@
339 print "Calculating dependencies ",
340
341 myparams = create_depgraph_params(self.myopts, None)
342 - success, mydepgraph, dropped_tasks = resume_depgraph(
343 - self.settings, self.trees, self._mtimedb, self.myopts,
344 - myparams, self._spinner, skip_unsatisfied=True)
345 + success = False
346 + e = None
347 + try:
348 + success, mydepgraph, dropped_tasks = resume_depgraph(
349 + self.settings, self.trees, self._mtimedb, self.myopts,
350 + myparams, self._spinner, skip_unsatisfied=True)
351 + except depgraph.UnsatisfiedResumeDep, e:
352 + mydepgraph = e.depgraph
353 + dropped_tasks = set()
354
355 if show_spinner:
356 print "\b\b... done!"
357
358 + if e is not None:
359 + mydepgraph.display_problems()
360 + out = portage.output.EOutput()
361 + out.eerror("One or packages are either masked or " + \
362 + "have missing dependencies:")
363 + out.eerror("")
364 + indent = " "
365 + for dep in e.value:
366 + if dep.atom is None:
367 + out.eerror(indent + "Masked package:")
368 + out.eerror(2 * indent + str(dep.parent))
369 + out.eerror("")
370 + else:
371 + out.eerror(indent + str(dep.atom) + " pulled in by:")
372 + out.eerror(2 * indent + str(dep.parent))
373 + out.eerror("")
374 + msg = "The resume list contains packages " + \
375 + "that are either masked or have " + \
376 + "unsatisfied dependencies. " + \
377 + "Please restart/continue " + \
378 + "the operation manually, or use --skipfirst " + \
379 + "to skip the first package in the list and " + \
380 + "any other packages that may be " + \
381 + "masked or have missing dependencies."
382 + for line in textwrap.wrap(msg, 72):
383 + out.eerror(line)
384 + return None
385 +
386 if self._show_list():
387 mylist = mydepgraph.altlist()
388 if "--tree" in self.myopts:
389 @@ -9656,7 +9726,7 @@
390
391 mydepgraph.display_problems()
392 if not success:
393 - return (None, None)
394 + return None
395
396 mylist = mydepgraph.altlist()
397 mydepgraph.break_refs(mylist)
398 @@ -11515,8 +11585,10 @@
399 msg.append("\n")
400 msg.append("As a safety measure, depclean will not remove any packages\n")
401 msg.append("unless *all* required dependencies have been resolved. As a\n")
402 - msg.append("consequence, it is often necessary to run\n")
403 - msg.append(good("`emerge --update --newuse --deep world`") + " prior to depclean.\n")
404 + msg.append("consequence, it is often necessary to run %s\n" % \
405 + good("`emerge --update"))
406 + msg.append(good("--newuse --deep --oneshot @system @world`") + \
407 + " prior to depclean.\n")
408
409 if action == "depclean" and "--quiet" not in myopts and not myfiles:
410 portage.writemsg_stdout("\n")
411 @@ -11691,30 +11763,46 @@
412 if not success:
413 return 1
414
415 - unresolveable = set()
416 - for dep in resolver._initially_unsatisfied_deps:
417 - if isinstance(dep.parent, Package):
418 - unresolveable.add((dep.atom, dep.parent.cpv))
419 + def unresolved_deps():
420
421 - if unresolveable and not allow_missing_deps:
422 - print "Dependencies could not be completely resolved due to"
423 - print "the following required packages not being installed:"
424 - print
425 - for atom, parent in unresolveable:
426 - print atom, "required by", str(parent)
427 - if unresolveable and not allow_missing_deps:
428 - print
429 - print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
430 - print "%s? It may be necessary to manually uninstall packages that no longer" % action
431 - print "exist in the portage tree since it may not be possible to satisfy their"
432 - print "dependencies. Also, be aware of the --with-bdeps option that is documented"
433 - print "in " + good("`man emerge`") + "."
434 - print
435 - if action == "prune":
436 - print "If you would like to ignore dependencies then use %s." % \
437 - good("--nodeps")
438 - return
439 + unresolvable = set()
440 + for dep in resolver._initially_unsatisfied_deps:
441 + if isinstance(dep.parent, Package):
442 + unresolvable.add((dep.atom, dep.parent.cpv))
443 + if not unresolvable:
444 + return False
445
446 + if unresolvable and not allow_missing_deps:
447 + prefix = bad(" * ")
448 + msg = []
449 + msg.append("Dependencies could not be completely resolved due to")
450 + msg.append("the following required packages not being installed:")
451 + msg.append("")
452 + for atom, parent in unresolvable:
453 + msg.append(" %s pulled in by:" % (atom,))
454 + msg.append(" %s" % (parent,))
455 + msg.append("")
456 + msg.append("Have you forgotten to run " + \
457 + good("`emerge --update --newuse --deep world`") + " prior to")
458 + msg.append(("%s? It may be necessary to manually " + \
459 + "uninstall packages that no longer") % action)
460 + msg.append("exist in the portage tree since " + \
461 + "it may not be possible to satisfy their")
462 + msg.append("dependencies. Also, be aware of " + \
463 + "the --with-bdeps option that is documented")
464 + msg.append("in " + good("`man emerge`") + ".")
465 + if action == "prune":
466 + msg.append("")
467 + msg.append("If you would like to ignore " + \
468 + "dependencies then use %s." % good("--nodeps"))
469 + writemsg_level("".join("%s%s\n" % (prefix, line) for line in msg),
470 + level=logging.ERROR, noiselevel=-1)
471 + return True
472 + return False
473 +
474 + if unresolved_deps():
475 + return 1
476 +
477 graph = resolver.digraph.copy()
478 required_pkgs_total = 0
479 for node in graph:
480 @@ -11739,50 +11827,61 @@
481 msg.append("\n")
482 portage.writemsg_stdout("".join(msg), noiselevel=-1)
483
484 - cleanlist = []
485 - if action == "depclean":
486 - if args_set:
487 - for pkg in vardb:
488 - arg_atom = None
489 - try:
490 - arg_atom = args_set.findAtomForPackage(pkg)
491 - except portage.exception.InvalidDependString:
492 - # this error has already been displayed by now
493 - continue
494 - if arg_atom:
495 + def create_cleanlist():
496 + pkgs_to_remove = []
497 +
498 + if action == "depclean":
499 + if args_set:
500 +
501 + for pkg in vardb:
502 + arg_atom = None
503 + try:
504 + arg_atom = args_set.findAtomForPackage(pkg)
505 + except portage.exception.InvalidDependString:
506 + # this error has already been displayed by now
507 + continue
508 +
509 + if arg_atom:
510 + if pkg not in graph:
511 + pkgs_to_remove.append(pkg)
512 + elif "--verbose" in myopts:
513 + show_parents(pkg)
514 +
515 + else:
516 + for pkg in vardb:
517 if pkg not in graph:
518 - cleanlist.append(pkg)
519 + pkgs_to_remove.append(pkg)
520 elif "--verbose" in myopts:
521 show_parents(pkg)
522 - else:
523 - for pkg in vardb:
524 - if pkg not in graph:
525 - cleanlist.append(pkg)
526 - elif "--verbose" in myopts:
527 - show_parents(pkg)
528 - elif action == "prune":
529 - # Prune really uses all installed instead of world. It's not a real
530 - # reverse dependency so don't display it as such.
531 - graph.remove(set_args["world"])
532 - for atom in args_set:
533 - for pkg in vardb.match_pkgs(atom):
534 - if pkg not in graph:
535 - cleanlist.append(pkg)
536 - elif "--verbose" in myopts:
537 - show_parents(pkg)
538
539 - if not cleanlist:
540 - portage.writemsg_stdout(
541 - ">>> No packages selected for removal by %s\n" % action)
542 - if "--verbose" not in myopts:
543 - portage.writemsg_stdout(
544 - ">>> To see reverse dependencies, use %s\n" % \
545 - good("--verbose"))
546 - if action == "prune":
547 - portage.writemsg_stdout(
548 - ">>> To ignore dependencies, use %s\n" % \
549 - good("--nodeps"))
550 + elif action == "prune":
551 + # Prune really uses all installed instead of world. It's not
552 + # a real reverse dependency so don't display it as such.
553 + graph.remove(set_args["world"])
554
555 + for atom in args_set:
556 + for pkg in vardb.match_pkgs(atom):
557 + if pkg not in graph:
558 + pkgs_to_remove.append(pkg)
559 + elif "--verbose" in myopts:
560 + show_parents(pkg)
561 +
562 + if not pkgs_to_remove:
563 + writemsg_level(
564 + ">>> No packages selected for removal by %s\n" % action)
565 + if "--verbose" not in myopts:
566 + writemsg_level(
567 + ">>> To see reverse dependencies, use %s\n" % \
568 + good("--verbose"))
569 + if action == "prune":
570 + writemsg_level(
571 + ">>> To ignore dependencies, use %s\n" % \
572 + good("--nodeps"))
573 +
574 + return pkgs_to_remove
575 +
576 + cleanlist = create_cleanlist()
577 +
578 if len(cleanlist):
579 clean_set = set(cleanlist)
580
581 @@ -11933,9 +12032,37 @@
582 msg.append("")
583 writemsg_level("".join(prefix + "%s\n" % line for line in msg),
584 level=logging.WARNING, noiselevel=-1)
585 - # TODO: Add packages + deps to graph, and calculate new clean list.
586 - return 1
587
588 + # Add lib providers to the graph as children of lib consumers,
589 + # and also add any dependencies pulled in by the provider.
590 + writemsg_level(">>> Adding lib providers to graph...\n")
591 +
592 + for pkg, consumers in consumer_map.iteritems():
593 + for consumer_dblink in set(chain(*consumers.values())):
594 + consumer_pkg = vardb.get(("installed", myroot,
595 + consumer_dblink.mycpv, "nomerge"))
596 + resolver._add_pkg(pkg, consumer_pkg,
597 + priority=UnmergeDepPriority(runtime=True))
598 +
599 + writemsg_level("\nCalculating dependencies ")
600 + success = resolver._complete_graph()
601 + writemsg_level("\b\b... done!\n")
602 + resolver.display_problems()
603 + if not success:
604 + return 1
605 + if unresolved_deps():
606 + return 1
607 +
608 + graph = resolver.digraph.copy()
609 + required_pkgs_total = 0
610 + for node in graph:
611 + if isinstance(node, Package):
612 + required_pkgs_total += 1
613 + cleanlist = create_cleanlist()
614 + if not cleanlist:
615 + return 0
616 + clean_set = set(cleanlist)
617 +
618 # Use a topological sort to create an unmerge order such that
619 # each package is unmerged before it's dependencies. This is
620 # necessary to avoid breaking things that may need to run
621 @@ -12093,13 +12220,11 @@
622 if isinstance(x, list) and \
623 tuple(x) not in unsatisfied_parents]
624
625 - # It shouldn't happen, but if the size of mergelist
626 - # does not decrease for some reason then the loop
627 - # will be infinite. Therefore, if that case ever
628 - # occurs for some reason, raise the exception to
629 - # break out of the loop.
630 + # If the mergelist doesn't shrink then this loop is infinite.
631 if len(pruned_mergelist) == len(mergelist):
632 - raise AssertionError("tight loop")
633 + # This happens if a package can't be dropped because
634 + # it's already installed, but it has unsatisfied PDEPEND.
635 + raise
636 mergelist[:] = pruned_mergelist
637 dropped_tasks.update(unsatisfied_parents)
638 del e, graph, traversed_nodes, \
639
640 Modified: main/branches/prefix/pym/_emerge/help.py
641 ===================================================================
642 --- main/branches/prefix/pym/_emerge/help.py 2008-07-23 06:52:10 UTC (rev 11171)
643 +++ main/branches/prefix/pym/_emerge/help.py 2008-07-23 06:54:24 UTC (rev 11172)
644 @@ -66,35 +66,42 @@
645 print " file setup or other similar setups that the user may wish to run."
646 print
647 print " "+green("--depclean")
648 - paragraph = "Cleans the system by removing packages that are not associated " + \
649 - "with explicitly merged packages. Depclean works by creating the " + \
650 - "full dependency tree from the system and world sets, " + \
651 - "then comparing it to installed packages. Packages installed, but " + \
652 - "not part of the dependency tree, will be uninstalled by depclean. " + \
653 - "Inexperienced users are advised to use --pretend " + \
654 - "with this option in order to see a preview of which packages " + \
655 - "will be uninstalled."
656 +
657 + paragraph = "Cleans the system by removing packages that are " + \
658 + "not associated with explicitly merged packages. Depclean works " + \
659 + "by creating the full dependency tree from the @system and " + \
660 + "@world sets, then comparing it to installed packages. Packages " + \
661 + "installed, but not part of the dependency tree, will be " + \
662 + "uninstalled by depclean. See --with-bdeps for behavior with " + \
663 + "respect to build time dependencies that are not strictly " + \
664 + "required. Packages that are part of the world set will " + \
665 + "always be kept. They can be manually added to this set with " + \
666 + "emerge --noreplace <atom>. As a safety measure, depclean " + \
667 + "will not remove any packages unless *all* required dependencies " + \
668 + "have been resolved. As a consequence, it is often necessary to " + \
669 + "run emerge --update --newuse --deep --oneshot @system @world " + \
670 + "prior to depclean."
671 +
672 for line in wrap(paragraph, desc_width):
673 print desc_indent + line
674 print
675
676 - paragraph = "WARNING: Removing some " + \
677 - "packages may cause packages which link to the removed package " + \
678 - "to stop working and complain about missing libraries. " + \
679 - "Rebuild the complaining package to fix this issue. Also see " + \
680 - "--with-bdeps for behavior with respect to build time dependencies that " + \
681 - "are not strictly required. Note that packages listed in " + \
682 - "package.provided (see portage(5)) may be removed by " + \
683 - "depclean, even if they are part of the world set."
684 + paragraph = "WARNING: Inexperienced users are advised to use " + \
685 + "--pretend with this option in order to see a preview of which " + \
686 + "packages will be uninstalled. Always study the list of packages " + \
687 + "to be cleaned for any obvious mistakes. Note that packages " + \
688 + "listed in package.provided (see portage(5)) may be removed by " + \
689 + "depclean, even if they are part of the world set."
690 +
691 for line in wrap(paragraph, desc_width):
692 print desc_indent + line
693 print
694
695 - paragraph = "Depclean serves as a dependency aware " + \
696 - "version of --unmerge. When given one or more atoms, it will " + \
697 - "unmerge matched packages that have no reverse dependencies. Use " + \
698 - "--depclean together with --verbose to show reverse " + \
699 - "dependencies."
700 + paragraph = "Depclean serves as a dependency aware version of " + \
701 + "--unmerge. When given one or more atoms, it will unmerge " + \
702 + "matched packages that have no reverse dependencies. Use " + \
703 + "--depclean together with --verbose to show reverse dependencies."
704 +
705 for line in wrap(paragraph, desc_width):
706 print desc_indent + line
707 print
708 @@ -116,12 +123,13 @@
709 print
710 print " "+green("--prune")+" ("+green("-P")+" short option)"
711 print " "+turquoise("WARNING: This action can remove important packages!")
712 - print " Removes all but the highest installed version of a package"
713 - print " from your system. This action doesn't verify the possible binary"
714 - print " compatibility between versions and can thus remove essential"
715 - print " dependencies from your system. Use --prune together with"
716 - print " --verbose to show reverse dependencies or with --nodeps to"
717 - print " ignore all dependencies."
718 + paragraph = "Removes all but the highest installed version of a " + \
719 + "package from your system. Use --prune together with " + \
720 + "--verbose to show reverse dependencies or with --nodeps " + \
721 + "to ignore all dependencies. "
722 +
723 + for line in wrap(paragraph, desc_width):
724 + print desc_indent + line
725 print
726 print " "+green("--regen")
727 print " Causes portage to check and update the dependency cache of all"
728
729 Modified: main/branches/prefix/pym/portage/__init__.py
730 ===================================================================
731 --- main/branches/prefix/pym/portage/__init__.py 2008-07-23 06:52:10 UTC (rev 11171)
732 +++ main/branches/prefix/pym/portage/__init__.py 2008-07-23 06:54:24 UTC (rev 11172)
733 @@ -4312,7 +4312,7 @@
734 noiselevel=-1)
735 return retval
736
737 -def _check_build_log(mysettings):
738 +def _check_build_log(mysettings, out=None):
739 """
740 Search the content of $PORTAGE_LOG_FILE if it exists
741 and generate the following QA Notices when appropriate:
742 @@ -4357,7 +4357,7 @@
743 from portage.elog.messages import eqawarn
744 def _eqawarn(lines):
745 for line in lines:
746 - eqawarn(line, phase="install", key=mysettings.mycpv)
747 + eqawarn(line, phase="install", key=mysettings.mycpv, out=out)
748 from textwrap import wrap
749 wrap_width = 70
750
751
752 Modified: main/branches/prefix/pym/portage/dbapi/vartree.py
753 ===================================================================
754 --- main/branches/prefix/pym/portage/dbapi/vartree.py 2008-07-23 06:52:10 UTC (rev 11171)
755 +++ main/branches/prefix/pym/portage/dbapi/vartree.py 2008-07-23 06:54:24 UTC (rev 11172)
756 @@ -1680,6 +1680,7 @@
757 The caller must ensure that lockdb() and unlockdb() are called
758 before and after this method.
759 """
760 + showMessage = self._display_merge
761 if self.vartree.dbapi._categories is not None:
762 self.vartree.dbapi._categories = None
763 # When others_in_slot is supplied, the security check has already been
764 @@ -1835,7 +1836,7 @@
765 else:
766 obj_type = "obj"
767 os.unlink(obj)
768 - writemsg_stdout("<<< !needed %s %s\n" % (obj_type, obj))
769 + showMessage("<<< !needed %s %s\n" % (obj_type, obj))
770 except OSError, e:
771 if e.errno == errno.ENOENT:
772 pass
773 @@ -2264,6 +2265,7 @@
774 return False
775
776 def _preserve_libs(self, srcroot, destroot, mycontents, counter, inforoot):
777 + showMessage = self._display_merge
778 # read global reverse NEEDED map
779 linkmap = self.vartree.dbapi.linkmap
780 if ostype == "Darwin":
781 @@ -2360,9 +2362,11 @@
782 # skip existing files so the 'new' libs aren't overwritten
783 if os.path.exists(os.path.join(srcroot, x.lstrip(os.sep))):
784 continue
785 - print "injecting %s into %s" % (x, srcroot)
786 + showMessage("injecting %s into %s\n" % (x, srcroot),
787 + noiselevel=-1)
788 if not os.path.exists(os.path.join(destroot, x.lstrip(os.sep))):
789 - print "%s does not exist so can't be preserved" % x
790 + showMessage("%s does not exist so can't be preserved\n" % x,
791 + noiselevel=-1)
792 continue
793 mydir = os.path.join(srcroot, os.path.dirname(x).lstrip(os.sep))
794 if not os.path.exists(mydir):