1 # Copyright 2010-2013 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
4 """Resolver output display operation.
7 from __future__ import unicode_literals
16 from portage import os
17 from portage.dbapi.dep_expand import dep_expand
18 from portage.dep import cpvequal, _repo_separator, _slot_separator
19 from portage.eapi import _get_eapi_attrs
20 from portage.exception import InvalidDependString, SignatureException
21 from portage.package.ebuild.config import _get_feature_flags
22 from portage.package.ebuild._spawn_nofetch import spawn_nofetch
23 from portage.output import ( blue, colorize, create_color_func,
24 darkblue, darkgreen, green, nc_len, teal)
25 bad = create_color_func("BAD")
26 from portage.util import writemsg_stdout
27 from portage.versions import best
29 from _emerge.Blocker import Blocker
30 from _emerge.create_world_atom import create_world_atom
31 from _emerge.resolver.output_helpers import ( _DisplayConfig, _tree_display,
32 _PackageCounters, _create_use_string, _format_size, _calc_changelog, PkgInfo)
33 from _emerge.show_invalid_depstring_notice import show_invalid_depstring_notice
35 if sys.hexversion >= 0x3000000:
39 class Display(object):
40 """Formats and outputs the depgrah supplied it for merge/re-merge, etc.
44 @param favorites: defaults to []
45 @param verbosity: integer, defaults to None
52 self.counters = _PackageCounters()
59 self.myfetchlist = None
66 self.use_expand = None
67 self.use_expand_hidden = None
68 self.pkgsettings = None
69 self.forced_flags = None
72 self.blocker_style = None
75 def _blockers(self, pkg):
76 """Processes pkg for blockers and adds colorized strings to
77 self.print_msg and self.blockers
79 @param pkg: _emerge.Package.Package instance
81 Modifies class globals: self.blocker_style, self.resolved,
85 self.blocker_style = "PKG_BLOCKER_SATISFIED"
86 addl = "%s " % (colorize(self.blocker_style, "b"),)
88 self.blocker_style = "PKG_BLOCKER"
89 addl = "%s " % (colorize(self.blocker_style, "B"),)
90 addl += self.empty_space_in_brackets()
91 self.resolved = dep_expand(
92 str(pkg.atom).lstrip("!"), mydb=self.vardb,
93 settings=self.pkgsettings
95 if self.conf.columns and self.conf.quiet:
96 addl += " " + colorize(self.blocker_style, str(self.resolved))
98 addl = "[%s %s] %s%s" % \
99 (colorize(self.blocker_style, "blocks"),
101 colorize(self.blocker_style, str(self.resolved))
103 block_parents = self.conf.blocker_parents.parent_nodes(pkg)
104 block_parents = set([pnode[2] for pnode in block_parents])
105 block_parents = ", ".join(block_parents)
106 if self.resolved != pkg[2]:
107 addl += colorize(self.blocker_style,
108 " (\"%s\" is blocking %s)") % \
109 (str(pkg.atom).lstrip("!"), block_parents)
111 addl += colorize(self.blocker_style,
112 " (is blocking %s)") % block_parents
113 if isinstance(pkg, Blocker) and pkg.satisfied:
114 if not self.conf.columns:
115 self.print_msg.append(addl)
117 self.blockers.append(addl)
119 def _display_use(self, pkg, myoldbest, myinslotlist):
122 @param pkg: _emerge.Package.Package instance
123 @param myoldbest: list of installed versions
124 @param myinslotlist: list of installed slots
125 Modifies class globals: self.forced_flags, self.cur_iuse,
126 self.old_iuse, self.old_use, self.use_expand
129 self.forced_flags = set()
130 self.forced_flags.update(pkg.use.force)
131 self.forced_flags.update(pkg.use.mask)
133 self.cur_use = [flag for flag in self.conf.pkg_use_enabled(pkg) \
134 if flag in pkg.iuse.all]
135 self.cur_iuse = sorted(pkg.iuse.all)
137 if myoldbest and myinslotlist:
138 previous_cpv = myoldbest[0].cpv
140 previous_cpv = pkg.cpv
141 if self.vardb.cpv_exists(previous_cpv):
142 previous_pkg = self.vardb.match_pkgs('=' + previous_cpv)[0]
143 self.old_iuse = sorted(previous_pkg.iuse.all)
144 self.old_use = previous_pkg.use.enabled
151 self.old_use = [flag for flag in self.old_use if flag in self.old_iuse]
153 self.use_expand = pkg.use.expand
154 self.use_expand_hidden = pkg.use.expand_hidden
157 def include_mask_str(self):
158 return self.conf.verbosity > 1
160 def gen_mask_str(self, pkg):
162 @param pkg: _emerge.Package.Package instance
164 hardmasked = pkg.isHardMasked()
168 mask_str = colorize("BAD", "#")
170 keyword_mask = pkg.get_keyword_mask()
172 if keyword_mask is None:
174 elif keyword_mask == "missing":
175 mask_str = colorize("BAD", "*")
177 mask_str = colorize("WARN", "~")
181 def empty_space_in_brackets(self):
183 if self.include_mask_str():
184 # add column for mask status
188 def map_to_use_expand(self, myvals, forced_flags=False,
190 """Map use expand variables
193 @param forced_flags: bool
194 @param remove_hidden: bool
195 @rtype ret dictionary
196 or ret dict, forced dict.
200 for exp in self.use_expand:
203 for val in myvals[:]:
204 if val.startswith(exp.lower()+"_"):
205 if val in self.forced_flags:
206 forced[exp].add(val[len(exp)+1:])
207 ret[exp].append(val[len(exp)+1:])
210 forced["USE"] = [val for val in myvals \
211 if val in self.forced_flags]
213 for exp in self.use_expand_hidden:
220 def recheck_hidden(self, pkg):
221 """ Prevent USE_EXPAND_HIDDEN flags from being hidden if they
222 are the only thing that triggered reinstallation.
224 @param pkg: _emerge.Package.Package instance
225 Modifies self.use_expand_hidden, self.use_expand, self.verboseadd
227 reinst_flags_map = {}
228 reinstall_for_flags = self.conf.reinstall_nodes.get(pkg)
229 reinst_expand_map = None
230 if reinstall_for_flags:
231 reinst_flags_map = self.map_to_use_expand(
232 list(reinstall_for_flags), remove_hidden=False)
233 for k in list(reinst_flags_map):
234 if not reinst_flags_map[k]:
235 del reinst_flags_map[k]
236 if not reinst_flags_map.get("USE"):
237 reinst_expand_map = reinst_flags_map.copy()
238 reinst_expand_map.pop("USE", None)
239 if reinst_expand_map and \
240 not set(reinst_expand_map).difference(
241 self.use_expand_hidden):
242 self.use_expand_hidden = \
243 set(self.use_expand_hidden).difference(
246 cur_iuse_map, iuse_forced = \
247 self.map_to_use_expand(self.cur_iuse, forced_flags=True)
248 cur_use_map = self.map_to_use_expand(self.cur_use)
249 old_iuse_map = self.map_to_use_expand(self.old_iuse)
250 old_use_map = self.map_to_use_expand(self.old_use)
252 use_expand = sorted(self.use_expand)
253 use_expand.insert(0, "USE")
254 feature_flags = _get_feature_flags(_get_eapi_attrs(pkg.eapi))
256 for key in use_expand:
257 if key in self.use_expand_hidden:
259 self.verboseadd += _create_use_string(self.conf, key.upper(),
260 cur_iuse_map[key], iuse_forced[key],
261 cur_use_map[key], old_iuse_map[key],
262 old_use_map[key], self.is_new, feature_flags,
263 reinst_flags_map.get(key))
268 def pkgprint(pkg_str, pkg_info):
269 """Colorizes a string acording to pkg_info settings
271 @param pkg_str: string
272 @param pkg_info: dictionary
273 @rtype colorized string
278 return colorize("PKG_BINARY_MERGE_SYSTEM", pkg_str)
280 return colorize("PKG_BINARY_MERGE_WORLD", pkg_str)
282 return colorize("PKG_BINARY_MERGE", pkg_str)
285 return colorize("PKG_MERGE_SYSTEM", pkg_str)
287 return colorize("PKG_MERGE_WORLD", pkg_str)
289 return colorize("PKG_MERGE", pkg_str)
290 elif pkg_info.operation == "uninstall":
291 return colorize("PKG_UNINSTALL", pkg_str)
294 return colorize("PKG_NOMERGE_SYSTEM", pkg_str)
296 return colorize("PKG_NOMERGE_WORLD", pkg_str)
298 return colorize("PKG_NOMERGE", pkg_str)
301 def verbose_size(self, pkg, repoadd_set, pkg_info):
302 """Determines the size of the downloads required
304 @param pkg: _emerge.Package.Package instance
305 @param repoadd_set: set of repos to add
306 @param pkg_info: dictionary
307 Modifies class globals: self.myfetchlist, self.counters.totalsize,
308 self.verboseadd, repoadd_set.
311 if pkg.type_name in ("binary", "ebuild") and pkg_info.merge:
312 db = pkg.root_config.trees[
313 pkg.root_config.pkg_tree_map[pkg.type_name]].dbapi
315 if pkg.type_name == "ebuild":
316 kwargs["useflags"] = pkg_info.use
317 kwargs["myrepo"] = pkg.repo
320 myfilesdict = db.getfetchsizes(pkg.cpv,
321 **portage._native_kwargs(kwargs))
322 except InvalidDependString as e:
323 # FIXME: validate SRC_URI earlier
324 depstr, = db.aux_get(pkg.cpv,
325 ["SRC_URI"], myrepo=pkg.repo)
326 show_invalid_depstring_notice(
329 except SignatureException:
330 # missing/invalid binary package SIZE signature
332 if myfilesdict is None:
333 myfilesdict = "[empty/missing/bad digest]"
335 for myfetchfile in myfilesdict:
336 if myfetchfile not in self.myfetchlist:
337 mysize += myfilesdict[myfetchfile]
338 self.myfetchlist.add(myfetchfile)
340 self.counters.totalsize += mysize
341 self.verboseadd += _format_size(mysize)
343 if self.quiet_repo_display:
345 # assign index for a previous version in the same slot
346 slot_matches = self.vardb.match_pkgs(pkg.slot_atom)
348 repo_name_prev = slot_matches[0].repo
350 repo_name_prev = None
352 # now use the data to generate output
353 if pkg.installed or not slot_matches:
354 self.repoadd = self.conf.repo_display.repoStr(
355 pkg_info.repo_path_real)
357 repo_path_prev = None
359 repo_path_prev = self.portdb.getRepositoryPath(
361 if repo_path_prev == pkg_info.repo_path_real:
362 self.repoadd = self.conf.repo_display.repoStr(
363 pkg_info.repo_path_real)
365 self.repoadd = "%s=>%s" % (
366 self.conf.repo_display.repoStr(repo_path_prev),
367 self.conf.repo_display.repoStr(pkg_info.repo_path_real))
369 repoadd_set.add(self.repoadd)
372 def convert_myoldbest(self, pkg, pkg_info):
373 """converts and colorizes a version list to a string
375 @param pkg: _emerge.Package.Package instance
376 @param pkg_info: dictionary
379 myoldbest = pkg_info.oldbest_list
380 # Convert myoldbest from a list to a string.
384 for pos, old_pkg in enumerate(myoldbest):
385 key = old_pkg.version
386 if key[-3:] == "-r0":
388 if self.conf.verbosity == 3:
389 if pkg_info.attr_display.new_slot:
390 key += _slot_separator + old_pkg.slot
391 if old_pkg.slot != old_pkg.sub_slot:
392 key += "/" + old_pkg.sub_slot
393 elif any(x.slot + "/" + x.sub_slot != "0/0" for x in myoldbest + [pkg]):
394 key += _slot_separator + old_pkg.slot
395 if old_pkg.slot != old_pkg.sub_slot or \
396 old_pkg.slot == pkg.slot and old_pkg.sub_slot != pkg.sub_slot:
397 key += "/" + old_pkg.sub_slot
398 if not self.quiet_repo_display and (self.verbose_main_repo_display or
399 any(x.repo != self.portdb.repositories.mainRepo().name for x in myoldbest + [pkg])):
400 key += _repo_separator + old_pkg.repo
402 myoldbest_str = blue("["+", ".join(versions)+"]")
405 def _append_slot(self, pkg_str, pkg, pkg_info):
406 """Potentially appends slot and subslot to package string.
408 @param pkg_str: string
409 @param pkg: _emerge.Package.Package instance
410 @param pkg_info: dictionary
413 if pkg_info.attr_display.new_slot:
414 pkg_str += _slot_separator + pkg_info.slot
415 if pkg_info.slot != pkg_info.sub_slot:
416 pkg_str += "/" + pkg_info.sub_slot
417 elif any(x.slot + "/" + x.sub_slot != "0/0" for x in pkg_info.oldbest_list + [pkg]):
418 pkg_str += _slot_separator + pkg_info.slot
419 if pkg_info.slot != pkg_info.sub_slot or \
420 any(x.slot == pkg_info.slot and x.sub_slot != pkg_info.sub_slot for x in pkg_info.oldbest_list):
421 pkg_str += "/" + pkg_info.sub_slot
424 def _append_repository(self, pkg_str, pkg, pkg_info):
425 """Potentially appends repository to package string.
427 @param pkg_str: string
428 @param pkg: _emerge.Package.Package instance
429 @param pkg_info: dictionary
432 if not self.quiet_repo_display and (self.verbose_main_repo_display or
433 any(x.repo != self.portdb.repositories.mainRepo().name for x in pkg_info.oldbest_list + [pkg])):
434 pkg_str += _repo_separator + pkg.repo
437 def _set_non_root_columns(self, pkg, pkg_info):
438 """sets the indent level and formats the output
440 @param pkg: _emerge.Package.Package instance
441 @param pkg_info: dictionary
444 ver_str = pkg_info.ver
445 if self.conf.verbosity == 3:
446 ver_str = self._append_slot(ver_str, pkg, pkg_info)
447 ver_str = self._append_repository(ver_str, pkg, pkg_info)
449 myprint = str(pkg_info.attr_display) + " " + self.indent + \
450 self.pkgprint(pkg_info.cp, pkg_info)
451 myprint = myprint+darkblue(" "+ver_str)+" "
452 myprint = myprint+pkg_info.oldbest
453 myprint = myprint+darkgreen("to "+pkg.root)
454 self.verboseadd = None
456 if not pkg_info.merge:
457 myprint = "[%s] %s%s" % \
458 (self.pkgprint(pkg_info.operation.ljust(13), pkg_info),
459 self.indent, self.pkgprint(pkg.cp, pkg_info))
461 myprint = "[%s %s] %s%s" % \
462 (self.pkgprint(pkg.type_name, pkg_info),
463 pkg_info.attr_display,
464 self.indent, self.pkgprint(pkg.cp, pkg_info))
465 if (self.newlp-nc_len(myprint)) > 0:
466 myprint = myprint+(" "*(self.newlp-nc_len(myprint)))
467 myprint = myprint+" "+darkblue("["+ver_str+"]")+" "
468 if (self.oldlp-nc_len(myprint)) > 0:
469 myprint = myprint+" "*(self.oldlp-nc_len(myprint))
470 myprint = myprint+pkg_info.oldbest
471 myprint += darkgreen("to " + pkg.root)
475 def _set_root_columns(self, pkg, pkg_info):
476 """sets the indent level and formats the output
478 @param pkg: _emerge.Package.Package instance
479 @param pkg_info: dictionary
481 Modifies self.verboseadd
483 ver_str = pkg_info.ver
484 if self.conf.verbosity == 3:
485 ver_str = self._append_slot(ver_str, pkg, pkg_info)
486 ver_str = self._append_repository(ver_str, pkg, pkg_info)
488 myprint = str(pkg_info.attr_display) + " " + self.indent + \
489 self.pkgprint(pkg_info.cp, pkg_info)
490 myprint = myprint+" "+green(ver_str)+" "
491 myprint = myprint+pkg_info.oldbest
492 self.verboseadd = None
494 if not pkg_info.merge:
495 addl = self.empty_space_in_brackets()
496 myprint = "[%s%s] %s%s" % \
497 (self.pkgprint(pkg_info.operation.ljust(13), pkg_info),
498 addl, self.indent, self.pkgprint(pkg.cp, pkg_info))
500 myprint = "[%s %s] %s%s" % \
501 (self.pkgprint(pkg.type_name, pkg_info),
502 pkg_info.attr_display,
503 self.indent, self.pkgprint(pkg.cp, pkg_info))
504 if (self.newlp-nc_len(myprint)) > 0:
505 myprint = myprint+(" "*(self.newlp-nc_len(myprint)))
506 myprint = myprint+" "+green("["+ver_str+"]")+" "
507 if (self.oldlp-nc_len(myprint)) > 0:
508 myprint = myprint+(" "*(self.oldlp-nc_len(myprint)))
509 myprint += pkg_info.oldbest
513 def _set_no_columns(self, pkg, pkg_info):
514 """prints pkg info without column indentation.
516 @param pkg: _emerge.Package.Package instance
517 @param pkg_info: dictionary
518 @rtype the updated addl
521 if self.conf.verbosity == 3:
522 pkg_str = self._append_slot(pkg_str, pkg, pkg_info)
523 pkg_str = self._append_repository(pkg_str, pkg, pkg_info)
524 if not pkg_info.merge:
525 addl = self.empty_space_in_brackets()
526 myprint = "[%s%s] %s%s %s" % \
527 (self.pkgprint(pkg_info.operation.ljust(13),
529 self.indent, self.pkgprint(pkg_str, pkg_info),
532 myprint = "[%s %s] %s%s %s" % \
533 (self.pkgprint(pkg.type_name, pkg_info),
534 pkg_info.attr_display, self.indent,
535 self.pkgprint(pkg_str, pkg_info), pkg_info.oldbest)
538 def print_messages(self, show_repos):
539 """Performs the actual output printing of the pre-formatted
542 @param show_repos: bool.
544 for msg in self.print_msg:
545 if isinstance(msg, basestring):
546 writemsg_stdout("%s\n" % (msg,), noiselevel=-1)
548 myprint, self.verboseadd, repoadd = msg
550 myprint += " " + self.verboseadd
551 if show_repos and repoadd:
552 myprint += " " + teal("[%s]" % repoadd)
553 writemsg_stdout("%s\n" % (myprint,), noiselevel=-1)
557 def print_blockers(self):
558 """Performs the actual output printing of the pre-formatted
561 for pkg in self.blockers:
562 writemsg_stdout("%s\n" % (pkg,), noiselevel=-1)
566 def print_verbose(self, show_repos):
567 """Prints the verbose output to std_out
569 @param show_repos: bool.
571 writemsg_stdout('\n%s\n' % (self.counters,), noiselevel=-1)
573 # Use unicode_literals to force unicode format string so
574 # that RepoDisplay.__unicode__() is called in python2.
575 writemsg_stdout("%s" % (self.conf.repo_display,),
580 def print_changelog(self):
581 """Prints the changelog text to std_out
583 for chunk in self.changelogs:
584 writemsg_stdout(chunk,
588 def get_display_list(self, mylist):
589 """Determines the display list to process
593 Modifies self.counters.blocks, self.counters.blocks_satisfied,
596 unsatisfied_blockers = []
599 if isinstance(pkg, Blocker):
600 self.counters.blocks += 1
602 ordered_nodes.append(pkg)
603 self.counters.blocks_satisfied += 1
605 unsatisfied_blockers.append(pkg)
607 ordered_nodes.append(pkg)
608 if self.conf.tree_display:
609 display_list = _tree_display(self.conf, ordered_nodes)
611 display_list = [(pkg, 0, True) for pkg in ordered_nodes]
612 for pkg in unsatisfied_blockers:
613 display_list.append((pkg, 0, True))
617 def set_pkg_info(self, pkg, ordered):
618 """Sets various pkg_info dictionary variables
620 @param pkg: _emerge.Package.Package instance
622 @rtype pkg_info dictionary
623 Modifies self.counters.restrict_fetch,
624 self.counters.restrict_fetch_satisfied
628 pkg_info.ver = self.get_ver_str(pkg)
629 pkg_info.slot = pkg.slot
630 pkg_info.sub_slot = pkg.sub_slot
631 pkg_info.repo_name = pkg.repo
632 pkg_info.ordered = ordered
633 pkg_info.operation = pkg.operation
634 pkg_info.merge = ordered and pkg_info.operation == "merge"
635 if not pkg_info.merge and pkg_info.operation == "merge":
636 pkg_info.operation = "nomerge"
637 pkg_info.built = pkg.type_name != "ebuild"
638 pkg_info.ebuild_path = None
641 if pkg.type_name == "binary":
642 self.counters.binary += 1
643 elif pkg_info.operation == "uninstall":
644 self.counters.uninst += 1
645 if pkg.type_name == "ebuild":
646 pkg_info.ebuild_path = self.portdb.findname(
647 pkg.cpv, myrepo=pkg_info.repo_name)
648 if pkg_info.ebuild_path is None:
649 raise AssertionError(
650 "ebuild not found for '%s'" % pkg.cpv)
651 pkg_info.repo_path_real = os.path.dirname(os.path.dirname(
652 os.path.dirname(pkg_info.ebuild_path)))
654 pkg_info.repo_path_real = self.portdb.getRepositoryPath(pkg.repo)
655 pkg_info.use = list(self.conf.pkg_use_enabled(pkg))
656 if not pkg.built and pkg.operation == 'merge' and \
657 'fetch' in pkg.restrict:
659 self.counters.restrict_fetch += 1
660 pkg_info.attr_display.fetch_restrict = True
661 if not self.portdb.getfetchsizes(pkg.cpv,
662 useflags=pkg_info.use, myrepo=pkg.repo):
663 pkg_info.attr_display.fetch_restrict_satisfied = True
665 self.counters.restrict_fetch_satisfied += 1
667 if pkg_info.ebuild_path is not None:
668 self.restrict_fetch_list[pkg] = pkg_info
672 def do_changelog(self, pkg, pkg_info):
673 """Processes and adds the changelog text to the master text for output
675 @param pkg: _emerge.Package.Package instance
676 @param pkg_info: dictionay
677 Modifies self.changelogs
679 inst_matches = self.vardb.match(pkg.slot_atom)
681 ebuild_path_cl = pkg_info.ebuild_path
682 if ebuild_path_cl is None:
684 ebuild_path_cl = self.portdb.findname(pkg.cpv, myrepo=pkg.repo)
685 if ebuild_path_cl is not None:
686 self.changelogs.extend(_calc_changelog(
687 ebuild_path_cl, inst_matches[0], pkg.cpv))
691 def check_system_world(self, pkg):
692 """Checks for any occurances of the package in the system or world sets
694 @param pkg: _emerge.Package.Package instance
695 @rtype system and world booleans
697 root_config = self.conf.roots[pkg.root]
698 system_set = root_config.sets["system"]
699 world_set = root_config.sets["selected"]
703 system = system_set.findAtomForPackage(
704 pkg, modified_use=self.conf.pkg_use_enabled(pkg))
705 world = world_set.findAtomForPackage(
706 pkg, modified_use=self.conf.pkg_use_enabled(pkg))
707 if not (self.conf.oneshot or world) and \
708 pkg.root == self.conf.target_root and \
709 self.conf.favorites.findAtomForPackage(
710 pkg, modified_use=self.conf.pkg_use_enabled(pkg)
712 # Maybe it will be added to world now.
713 if create_world_atom(pkg, self.conf.favorites, root_config):
715 except InvalidDependString:
716 # This is reported elsewhere if relevant.
722 def get_ver_str(pkg):
723 """Obtains the version string
724 @param pkg: _emerge.Package.Package instance
727 ver_str = pkg.cpv.version
728 if ver_str.endswith("-r0"):
729 ver_str = ver_str[:-3]
733 def _get_installed_best(self, pkg, pkg_info):
734 """ we need to use "--emptrytree" testing here rather than
735 "empty" param testing because "empty"
736 param is used for -u, where you still *do* want to see when
737 something is being upgraded.
739 @param pkg: _emerge.Package.Package instance
740 @param pkg_info: dictionay
741 @rtype addl, myoldbest: list, myinslotlist: list
742 Modifies self.counters.reinst, self.counters.new
747 installed_versions = self.vardb.match_pkgs(pkg.cp)
748 if self.vardb.cpv_exists(pkg.cpv):
749 pkg_info.attr_display.replace = True
750 installed_version = self.vardb.match_pkgs(pkg.cpv)[0]
751 if installed_version.slot != pkg.slot or installed_version.sub_slot != pkg.sub_slot or \
752 not self.quiet_repo_display and installed_version.repo != pkg.repo:
753 myoldbest = [installed_version]
756 self.counters.reinst += 1
757 # filter out old-style virtual matches
758 elif installed_versions and \
759 installed_versions[0].cp == pkg.cp:
760 myinslotlist = self.vardb.match_pkgs(pkg.slot_atom)
761 # If this is the first install of a new-style virtual, we
762 # need to filter out old-style virtual matches.
763 if myinslotlist and \
764 myinslotlist[0].cp != pkg.cp:
767 myoldbest = myinslotlist[:]
768 if not cpvequal(pkg.cpv,
769 best([pkg.cpv] + [x.cpv for x in myinslotlist])):
771 pkg_info.attr_display.new_version = True
772 pkg_info.attr_display.downgrade = True
774 self.counters.downgrades += 1
777 pkg_info.attr_display.new_version = True
779 self.counters.upgrades += 1
781 myoldbest = installed_versions
782 pkg_info.attr_display.new = True
783 pkg_info.attr_display.new_slot = True
785 self.counters.newslot += 1
786 if self.conf.changelog:
787 self.do_changelog(pkg, pkg_info)
789 pkg_info.attr_display.new = True
791 self.counters.new += 1
792 return myoldbest, myinslotlist
795 def __call__(self, depgraph, mylist, favorites=None, verbosity=None):
796 """The main operation to format and display the resolver output.
798 @param depgraph: dependency grah
799 @param mylist: list of packages being processed
800 @param favorites: list, defaults to []
801 @param verbosity: verbose level, defaults to None
802 Modifies self.conf, self.myfetchlist, self.portdb, self.vardb,
803 self.pkgsettings, self.verboseadd, self.oldlp, self.newlp,
806 if favorites is None:
808 self.conf = _DisplayConfig(depgraph, mylist, favorites, verbosity)
809 mylist = self.get_display_list(self.conf.mylist)
810 # files to fetch list - avoids counting a same file twice
811 # in size display (verbose mode)
812 self.myfetchlist = set()
814 self.quiet_repo_display = "--quiet-repo-display" in depgraph._frozen_config.myopts
815 if self.quiet_repo_display:
816 # Use this set to detect when all the "repoadd" strings are "[0]"
817 # and disable the entire repo display in this case.
820 self.verbose_main_repo_display = "--verbose-main-repo-display" in depgraph._frozen_config.myopts
821 self.restrict_fetch_list = {}
823 for mylist_index in range(len(mylist)):
824 pkg, depth, ordered = mylist[mylist_index]
825 self.portdb = self.conf.trees[pkg.root]["porttree"].dbapi
826 self.vardb = self.conf.trees[pkg.root]["vartree"].dbapi
827 self.pkgsettings = self.conf.pkgsettings[pkg.root]
828 self.indent = " " * depth
830 if isinstance(pkg, Blocker):
833 pkg_info = self.set_pkg_info(pkg, ordered)
834 pkg_info.oldbest_list, myinslotlist = \
835 self._get_installed_best(pkg, pkg_info)
836 if ordered and pkg_info.merge and \
837 not pkg_info.attr_display.new:
838 for arg, atom in depgraph._iter_atoms_for_pkg(pkg):
839 if arg.force_reinstall:
840 pkg_info.attr_display.force_reinstall = True
844 if self.quiet_repo_display:
846 self._display_use(pkg, pkg_info.oldbest_list, myinslotlist)
847 self.recheck_hidden(pkg)
848 if self.conf.verbosity == 3:
849 if self.quiet_repo_display:
850 self.verbose_size(pkg, repoadd_set, pkg_info)
852 self.verbose_size(pkg, None, pkg_info)
854 self.oldlp = self.conf.columnwidth - 30
855 self.newlp = self.oldlp - 30
856 pkg_info.oldbest = self.convert_myoldbest(pkg, pkg_info)
857 pkg_info.system, pkg_info.world = \
858 self.check_system_world(pkg)
859 if 'interactive' in pkg.properties and \
860 pkg.operation == 'merge':
861 pkg_info.attr_display.interactive = True
863 self.counters.interactive += 1
865 if self.include_mask_str():
866 pkg_info.attr_display.mask = self.gen_mask_str(pkg)
868 if pkg.root_config.settings["ROOT"] != "/":
870 pkg_info.oldbest += " "
871 if self.conf.columns:
872 myprint = self._set_non_root_columns(pkg, pkg_info)
875 if self.conf.verbosity == 3:
876 pkg_str = self._append_slot(pkg_str, pkg, pkg_info)
877 pkg_str = self._append_repository(pkg_str, pkg, pkg_info)
878 if not pkg_info.merge:
879 addl = self.empty_space_in_brackets()
880 myprint = "[%s%s] " % (
881 self.pkgprint(pkg_info.operation.ljust(13),
885 myprint = "[%s %s] " % (
886 self.pkgprint(pkg.type_name, pkg_info),
887 pkg_info.attr_display)
888 myprint += self.indent + \
889 self.pkgprint(pkg_str, pkg_info) + " " + \
890 pkg_info.oldbest + darkgreen("to " + pkg.root)
892 if self.conf.columns:
893 myprint = self._set_root_columns(pkg, pkg_info)
895 myprint = self._set_no_columns(pkg, pkg_info)
897 if self.conf.columns and pkg.operation == "uninstall":
899 if self.quiet_repo_display:
900 self.print_msg.append((myprint, self.verboseadd, self.repoadd))
902 self.print_msg.append((myprint, self.verboseadd, None))
904 show_repos = self.quiet_repo_display and repoadd_set and repoadd_set != set(["0"])
906 # now finally print out the messages
907 self.print_messages(show_repos)
908 self.print_blockers()
909 if self.conf.verbosity == 3:
910 self.print_verbose(show_repos)
911 for pkg, pkg_info in self.restrict_fetch_list.items():
912 writemsg_stdout("\nFetch instructions for %s:\n" % (pkg.cpv,),
914 spawn_nofetch(self.conf.trees[pkg.root]["porttree"].dbapi,
915 pkg_info.ebuild_path)
916 if self.conf.changelog:
917 self.print_changelog()