summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pym/_emerge/depgraph.py11
-rw-r--r--pym/_emerge/resolver/output.py1822
-rw-r--r--pym/_emerge/resolver/output_helpers.py574
3 files changed, 1389 insertions, 1018 deletions
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index 45a450df1..76c1cb4ee 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -55,7 +55,7 @@ from _emerge.UnmergeDepPriority import UnmergeDepPriority
from _emerge.resolver.backtracking import Backtracker, BacktrackParameter
from _emerge.resolver.slot_collision import slot_conflict_handler
from _emerge.resolver.circular_dependency import circular_dependency_handler
-from _emerge.resolver.output import display, filter_iuse_defaults
+from _emerge.resolver.output import Display, filter_iuse_defaults
if sys.hexversion >= 0x3000000:
basestring = str
@@ -1024,10 +1024,10 @@ class depgraph(object):
self._add_parent_atom(pkg, parent_atom)
""" This section determines whether we go deeper into dependencies or not.
- We want to go deeper on a few occasions:
- Installing package A, we need to make sure package A's deps are met.
- emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
- If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
+ We want to go deeper on a few occasions:
+ Installing package A, we need to make sure package A's deps are met.
+ emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
+ If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
"""
if arg_atoms:
depth = 0
@@ -4718,6 +4718,7 @@ class depgraph(object):
# redundantly displaying this exact same merge list
# again via _show_merge_list().
self._dynamic_config._displayed_list = mylist
+ display = Display()
return display(self, mylist, favorites, verbosity)
diff --git a/pym/_emerge/resolver/output.py b/pym/_emerge/resolver/output.py
index b82d56bed..f2394e214 100644
--- a/pym/_emerge/resolver/output.py
+++ b/pym/_emerge/resolver/output.py
@@ -1,1069 +1,865 @@
# Copyright 2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
+"""Resolver output display operation.
+"""
+
__all__ = (
- "display", "filter_iuse_defaults",
+ "Display", "filter_iuse_defaults"
)
-import codecs
-import re
import sys
from portage import os
-from portage import _encodings, _unicode_decode, _unicode_encode
+from portage import _unicode_decode
from portage.dbapi.dep_expand import dep_expand
from portage.const import PORTAGE_PACKAGE_ATOM
from portage.dep import cpvequal, match_from_list
from portage.exception import InvalidDependString
-from portage._sets.base import InternalPackageSet
-from portage.output import blue, bold, colorize, create_color_func, darkblue, darkgreen, green, nc_len, red, \
- teal, turquoise, yellow
+from portage.output import ( blue, bold, colorize, create_color_func,
+ darkblue, darkgreen, green, nc_len, red, teal, turquoise, yellow )
bad = create_color_func("BAD")
-from portage.util import writemsg, writemsg_stdout
+from portage.util import writemsg_stdout
from portage.versions import best, catpkgsplit, cpv_getkey
from _emerge.Blocker import Blocker
from _emerge.create_world_atom import create_world_atom
-from _emerge.Package import Package
+from _emerge.resolver.output_helpers import ( _DisplayConfig, _tree_display,
+ _PackageCounters, _create_use_string, _format_size, _calc_changelog, PkgInfo)
if sys.hexversion >= 0x3000000:
basestring = str
+
def filter_iuse_defaults(iuse):
+ """Performs an absolute value action on an use flag list.
+
+ @param iuse: list of use flags
+ @rtype list
+ """
for flag in iuse:
if flag.startswith("+") or flag.startswith("-"):
yield flag[1:]
else:
yield flag
-class _RepoDisplay(object):
- def __init__(self, roots):
- self._shown_repos = {}
- self._unknown_repo = False
- repo_paths = set()
- for root_config in roots.values():
- portdir = root_config.settings.get("PORTDIR")
- if root_config.settings.repositories:
- repo_paths.update(root_config.settings.repositories.repoUserLocationList())
- repo_paths = list(repo_paths)
- self._repo_paths = repo_paths
- self._repo_paths_real = [ os.path.realpath(repo_path) \
- for repo_path in repo_paths ]
-
- # pre-allocate index for PORTDIR so that it always has index 0.
- for root_config in roots.values():
- portdb = root_config.trees["porttree"].dbapi
- portdir = portdb.porttree_root
- if portdir:
- self.repoStr(portdir)
-
- def repoStr(self, repo_path_real):
- real_index = -1
- if repo_path_real:
- real_index = self._repo_paths_real.index(repo_path_real)
- if real_index == -1:
- s = "?"
- self._unknown_repo = True
- else:
- shown_repos = self._shown_repos
- repo_paths = self._repo_paths
- repo_path = repo_paths[real_index]
- index = shown_repos.get(repo_path)
- if index is None:
- index = len(shown_repos)
- shown_repos[repo_path] = index
- s = str(index)
- return s
-
- def __str__(self):
- output = []
- shown_repos = self._shown_repos
- unknown_repo = self._unknown_repo
- if shown_repos or self._unknown_repo:
- output.append("Portage tree and overlays:\n")
- show_repo_paths = list(shown_repos)
- for repo_path, repo_index in shown_repos.items():
- show_repo_paths[repo_index] = repo_path
- if show_repo_paths:
- for index, repo_path in enumerate(show_repo_paths):
- output.append(" "+teal("["+str(index)+"]")+" %s\n" % repo_path)
- if unknown_repo:
- output.append(" "+teal("[?]") + \
- " indicates that the source repository could not be determined\n")
- return "".join(output)
-
- if sys.hexversion < 0x3000000:
-
- __unicode__ = __str__
-
- def __str__(self):
- return _unicode_encode(self.__unicode__(),
- encoding=_encodings['content'])
-
-class _PackageCounters(object):
+
+class Display(object):
+ """Formats and outputs the depgrah supplied it for merge/re-merge, etc.
+
+ __call__()
+ @param depgraph: list
+ @param favorites: defaults to []
+ @param verbosity: integer, defaults to None
+ """
def __init__(self):
- self.upgrades = 0
- self.downgrades = 0
- self.new = 0
- self.newslot = 0
- self.reinst = 0
- self.uninst = 0
- self.blocks = 0
- self.blocks_satisfied = 0
- self.totalsize = 0
- self.restrict_fetch = 0
- self.restrict_fetch_satisfied = 0
- self.interactive = 0
- self.binary = 0
-
- def __str__(self):
- total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
- myoutput = []
- details = []
- myoutput.append("Total: %s package" % total_installs)
- if total_installs != 1:
- myoutput.append("s")
- if total_installs != 0:
- myoutput.append(" (")
- if self.upgrades > 0:
- details.append("%s upgrade" % self.upgrades)
- if self.upgrades > 1:
- details[-1] += "s"
- if self.downgrades > 0:
- details.append("%s downgrade" % self.downgrades)
- if self.downgrades > 1:
- details[-1] += "s"
- if self.new > 0:
- details.append("%s new" % self.new)
- if self.newslot > 0:
- details.append("%s in new slot" % self.newslot)
- if self.newslot > 1:
- details[-1] += "s"
- if self.reinst > 0:
- details.append("%s reinstall" % self.reinst)
- if self.reinst > 1:
- details[-1] += "s"
- if self.binary > 0:
- details.append("%s binary" % self.binary)
- if self.binary > 1:
- details[-1] = details[-1][:-1] + "ies"
- if self.uninst > 0:
- details.append("%s uninstall" % self.uninst)
- if self.uninst > 1:
- details[-1] += "s"
- if self.interactive > 0:
- details.append("%s %s" % (self.interactive,
- colorize("WARN", "interactive")))
- myoutput.append(", ".join(details))
- if total_installs != 0:
- myoutput.append(")")
- myoutput.append(", Size of downloads: %s" % _format_size(self.totalsize))
- if self.restrict_fetch:
- myoutput.append("\nFetch Restriction: %s package" % \
- self.restrict_fetch)
- if self.restrict_fetch > 1:
- myoutput.append("s")
- if self.restrict_fetch_satisfied < self.restrict_fetch:
- myoutput.append(bad(" (%s unsatisfied)") % \
- (self.restrict_fetch - self.restrict_fetch_satisfied))
- if self.blocks > 0:
- myoutput.append("\nConflict: %s block" % \
- self.blocks)
- if self.blocks > 1:
- myoutput.append("s")
- if self.blocks_satisfied < self.blocks:
- myoutput.append(bad(" (%s unsatisfied)") % \
- (self.blocks - self.blocks_satisfied))
- return "".join(myoutput)
-
-class _DisplayConfig(object):
- def __init__(self, depgraph, mylist, favorites, verbosity):
- frozen_config = depgraph._frozen_config
- dynamic_config = depgraph._dynamic_config
-
- self.mylist = mylist
- self.favorites = InternalPackageSet(favorites, allow_repo=True)
- self.verbosity = verbosity
-
- if self.verbosity is None:
- self.verbosity = ("--quiet" in frozen_config.myopts and 1 or \
- "--verbose" in frozen_config.myopts and 3 or 2)
-
- self.oneshot = "--oneshot" in frozen_config.myopts or \
- "--onlydeps" in frozen_config.myopts
- self.columns = "--columns" in frozen_config.myopts
- self.tree_display = "--tree" in frozen_config.myopts
- self.alphabetical = "--alphabetical" in frozen_config.myopts
- self.quiet = "--quiet" in frozen_config.myopts
- self.all_flags = self.verbosity == 3 or self.quiet
- self.print_use_string = self.verbosity != 1 or "--verbose" in frozen_config.myopts
- self.changelog = "--changelog" in frozen_config.myopts
- self.edebug = frozen_config.edebug
- self.no_restart = frozen_config._opts_no_restart.intersection(frozen_config.myopts)
- self.unordered_display = "--unordered-display" in frozen_config.myopts
-
- mywidth = 130
- if "COLUMNWIDTH" in frozen_config.settings:
- try:
- mywidth = int(frozen_config.settings["COLUMNWIDTH"])
- except ValueError as e:
- writemsg("!!! %s\n" % str(e), noiselevel=-1)
- writemsg("!!! Unable to parse COLUMNWIDTH='%s'\n" % \
- frozen_config.settings["COLUMNWIDTH"], noiselevel=-1)
- del e
- self.columnwidth = mywidth
-
- self.repo_display = _RepoDisplay(frozen_config.roots)
- self.trees = frozen_config.trees
- self.pkgsettings = frozen_config.pkgsettings
- self.target_root = frozen_config.target_root
- self.running_root = frozen_config._running_root
- self.roots = frozen_config.roots
-
- self.blocker_parents = dynamic_config._blocker_parents
- self.reinstall_nodes = dynamic_config._reinstall_nodes
- self.digraph = dynamic_config.digraph
- self.blocker_uninstalls = dynamic_config._blocker_uninstalls
- self.slot_pkg_map = dynamic_config._slot_pkg_map
- self.set_nodes = dynamic_config._set_nodes
-
- self.pkg_use_enabled = depgraph._pkg_use_enabled
- self.pkg = depgraph._pkg
-
-# formats a size given in bytes nicely
-def _format_size(mysize):
- if isinstance(mysize, basestring):
- return mysize
- if 0 != mysize % 1024:
- # Always round up to the next kB so that it doesn't show 0 kB when
- # some small file still needs to be fetched.
- mysize += 1024 - mysize % 1024
- mystr=str(mysize//1024)
- mycount=len(mystr)
- while (mycount > 3):
- mycount-=3
- mystr=mystr[:mycount]+","+mystr[mycount:]
- return mystr+" kB"
-
-def display(depgraph, mylist, favorites=[], verbosity=None):
-
- conf = _DisplayConfig(depgraph, mylist, favorites, verbosity)
-
- changelogs=[]
- p=[]
- blockers = []
- counters = _PackageCounters()
- repo_display = conf.repo_display
- unsatisfied_blockers = []
- ordered_nodes = []
- for x in conf.mylist:
- if isinstance(x, Blocker):
- counters.blocks += 1
- if x.satisfied:
- ordered_nodes.append(x)
- counters.blocks_satisfied += 1
- else:
- unsatisfied_blockers.append(x)
+ self.changelogs = []
+ self.print_msg = []
+ self.blockers = []
+ self.counters = _PackageCounters()
+ self.resolver = None
+ self.resolved = None
+ self.vardb = None
+ self.portdb = None
+ self.verboseadd = ''
+ self.oldlp = None
+ self.myfetchlist = None
+ self.indent = ''
+ self.is_new = True
+ self.cur_use = None
+ self.cur_iuse = None
+ self.old_use = ''
+ self.old_iuse = ''
+ self.use_expand = None
+ self.use_expand_hidden = None
+ self.pkgsettings = None
+ self.forced_flags = None
+ self.newlp = None
+ self.conf = None
+ self.blocker_style = None
+
+
+ def _blockers(self, pkg, fetch_symbol):
+ """Processes pkg for blockers and adds colorized strings to
+ self.print_msg and self.blockers
+
+ @param pkg: _emerge.Package instance
+ @param fetch_symbol: string
+ @rtype: bool
+ Modifies class globals: self.blocker_style, self.resolved,
+ self.print_msg
+ """
+ if pkg.satisfied:
+ self.blocker_style = "PKG_BLOCKER_SATISFIED"
+ addl = "%s %s " % (colorize(self.blocker_style, "b"),
+ fetch_symbol)
else:
- ordered_nodes.append(x)
-
- if conf.tree_display:
- display_list = _tree_display(conf, ordered_nodes)
- else:
- display_list = [(x, 0, True) for x in ordered_nodes]
-
- mylist = display_list
- for x in unsatisfied_blockers:
- mylist.append((x, 0, True))
-
- # files to fetch list - avoids counting a same file twice
- # in size display (verbose mode)
- myfetchlist=[]
-
- # Use this set to detect when all the "repoadd" strings are "[0]"
- # and disable the entire repo display in this case.
- repoadd_set = set()
-
- for mylist_index in range(len(mylist)):
- x, depth, ordered = mylist[mylist_index]
- pkg_type = x[0]
- myroot = x[1]
- pkg_key = x[2]
- portdb = conf.trees[myroot]["porttree"].dbapi
- vardb = conf.trees[myroot]["vartree"].dbapi
- pkgsettings = conf.pkgsettings[myroot]
-
- fetch=" "
- indent = " " * depth
-
- if isinstance(x, Blocker):
- if x.satisfied:
- blocker_style = "PKG_BLOCKER_SATISFIED"
- addl = "%s %s " % (colorize(blocker_style, "b"), fetch)
- else:
- blocker_style = "PKG_BLOCKER"
- addl = "%s %s " % (colorize(blocker_style, "B"), fetch)
- resolved = dep_expand(
- str(x.atom).lstrip("!"), mydb=vardb, settings=pkgsettings)
- if conf.columns and conf.quiet:
- addl += " " + colorize(blocker_style, str(resolved))
- else:
- addl = "[%s %s] %s%s" % \
- (colorize(blocker_style, "blocks"),
- addl, indent, colorize(blocker_style, str(resolved)))
- block_parents = conf.blocker_parents.parent_nodes(x)
- block_parents = set([pnode[2] for pnode in block_parents])
- block_parents = ", ".join(block_parents)
- if resolved!=x[2]:
- addl += colorize(blocker_style,
- " (\"%s\" is blocking %s)") % \
- (str(x.atom).lstrip("!"), block_parents)
- else:
- addl += colorize(blocker_style,
- " (is blocking %s)") % block_parents
- if isinstance(x, Blocker) and x.satisfied:
- if conf.columns:
- continue
- p.append(addl)
- else:
- blockers.append(addl)
+ self.blocker_style = "PKG_BLOCKER"
+ addl = "%s %s " % (colorize(self.blocker_style, "B"),
+ fetch_symbol)
+ self.resolved = dep_expand(
+ str(pkg.atom).lstrip("!"), mydb=self.vardb,
+ settings=self.pkgsettings
+ )
+ if self.conf.columns and self.conf.quiet:
+ addl += " " + colorize(self.blocker_style, str(self.resolved))
else:
- pkg_status = x[3]
- pkg_merge = ordered and pkg_status == "merge"
- if not pkg_merge and pkg_status == "merge":
- pkg_status = "nomerge"
- built = pkg_type != "ebuild"
- pkg = x
- metadata = pkg.metadata
- ebuild_path = None
- repo_name = pkg.repo
- if pkg.type_name == "ebuild":
- ebuild_path = portdb.findname(pkg.cpv, myrepo=repo_name)
- if ebuild_path is None:
- raise AssertionError(
- "ebuild not found for '%s'" % pkg.cpv)
- repo_path_real = os.path.dirname(os.path.dirname(
- os.path.dirname(ebuild_path)))
- else:
- repo_path_real = portdb.getRepositoryPath(repo_name)
- pkg_use = list(conf.pkg_use_enabled(pkg))
- if not pkg.built and pkg.operation == 'merge' and \
- 'fetch' in pkg.metadata.restrict:
- fetch = red("F")
- if ordered:
- counters.restrict_fetch += 1
- if portdb.fetch_check(pkg_key, pkg_use, myrepo=pkg.repo):
- fetch = green("f")
- if ordered:
- counters.restrict_fetch_satisfied += 1
-
- #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
- #param is used for -u, where you still *do* want to see when something is being upgraded.
- myoldbest = []
- myinslotlist = None
- installed_versions = vardb.match(cpv_getkey(pkg_key))
- if vardb.cpv_exists(pkg_key):
- addl=" "+yellow("R")+fetch+" "
- if ordered:
- if pkg_merge:
- counters.reinst += 1
- if pkg_type == "binary":
- counters.binary += 1
- elif pkg_status == "uninstall":
- counters.uninst += 1
- # filter out old-style virtual matches
- elif installed_versions and \
- cpv_getkey(installed_versions[0]) == \
- cpv_getkey(pkg_key):
- myinslotlist = vardb.match(pkg.slot_atom)
- # If this is the first install of a new-style virtual, we
- # need to filter out old-style virtual matches.
- if myinslotlist and \
- cpv_getkey(myinslotlist[0]) != \
- cpv_getkey(pkg_key):
- myinslotlist = None
- if myinslotlist:
- myoldbest = myinslotlist[:]
- addl = " " + fetch
- if not cpvequal(pkg_key,
- best([pkg_key] + myoldbest)):
- # Downgrade in slot
- addl += turquoise("U")+blue("D")
- if ordered:
- counters.downgrades += 1
- if pkg_type == "binary":
- counters.binary += 1
- else:
- # Update in slot
- addl += turquoise("U") + " "
- if ordered:
- counters.upgrades += 1
- if pkg_type == "binary":
- counters.binary += 1
+ addl = "[%s %s] %s%s" % \
+ (colorize(self.blocker_style, "blocks"),
+ addl, self.indent,
+ colorize(self.blocker_style, str(self.resolved))
+ )
+ block_parents = self.conf.blocker_parents.parent_nodes(pkg)
+ block_parents = set([pnode[2] for pnode in block_parents])
+ block_parents = ", ".join(block_parents)
+ if self.resolved != pkg[2]:
+ addl += colorize(self.blocker_style,
+ " (\"%s\" is blocking %s)") % \
+ (str(pkg.atom).lstrip("!"), block_parents)
+ else:
+ addl += colorize(self.blocker_style,
+ " (is blocking %s)") % block_parents
+ if isinstance(pkg, Blocker) and pkg.satisfied:
+ if self.conf.columns:
+ return True
+ self.print_msg.append(addl)
+ else:
+ self.blockers.append(addl)
+ return False
+
+
+ def _display_use(self, pkg, myoldbest, myinslotlist):
+ """ USE flag display
+
+ @param pkg: _emerge.Package instance
+ @param myoldbest: list of installed versions
+ @param myinslotlist: list of installed slots
+ Modifies class globals: self.forced_flags, self.cur_iuse,
+ self.old_iuse, self.old_use, self.use_expand
+ """
+
+ self.forced_flags = set()
+ self.pkgsettings.setcpv(pkg) # for package.use.{mask,force}
+ self.forced_flags.update(self.pkgsettings.useforce)
+ self.forced_flags.update(self.pkgsettings.usemask)
+
+ self.cur_use = [flag for flag in self.conf.pkg_use_enabled(pkg) \
+ if flag in pkg.iuse.all]
+ self.cur_iuse = sorted(pkg.iuse.all)
+
+ if myoldbest and myinslotlist:
+ previous_cpv = myoldbest[0]
+ else:
+ previous_cpv = pkg.cpv
+ if self.vardb.cpv_exists(previous_cpv):
+ self.old_iuse, self.old_use = self.vardb.aux_get(
+ previous_cpv, ["IUSE", "USE"])
+ self.old_iuse = list(set(
+ filter_iuse_defaults(self.old_iuse.split())))
+ self.old_iuse.sort()
+ self.old_use = self.old_use.split()
+ self.is_new = False
+ else:
+ self.old_iuse = []
+ self.old_use = []
+ self.is_new = True
+
+ self.old_use = [flag for flag in self.old_use if flag in self.old_iuse]
+
+ self.use_expand = self.pkgsettings["USE_EXPAND"].lower().split()
+ self.use_expand.sort()
+ self.use_expand.reverse()
+ self.use_expand_hidden = \
+ self.pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
+ return
+
+
+ def map_to_use_expand(self, myvals, forced_flags=False,
+ remove_hidden=True):
+ """Map use expand variables
+
+ @param myvals: list
+ @param forced_flags: bool
+ @param remove_hidden: bool
+ @rtype ret dictionary
+ or ret dict, forced dict.
+ """
+ ret = {}
+ forced = {}
+ for exp in self.use_expand:
+ ret[exp] = []
+ forced[exp] = set()
+ for val in myvals[:]:
+ if val.startswith(exp.lower()+"_"):
+ if val in self.forced_flags:
+ forced[exp].add(val[len(exp)+1:])
+ ret[exp].append(val[len(exp)+1:])
+ myvals.remove(val)
+ ret["USE"] = myvals
+ forced["USE"] = [val for val in myvals \
+ if val in self.forced_flags]
+ if remove_hidden:
+ for exp in self.use_expand_hidden:
+ ret.pop(exp, None)
+ if forced_flags:
+ return ret, forced
+ return ret
+
+
+ def recheck_hidden(self, pkg):
+ """ Prevent USE_EXPAND_HIDDEN flags from being hidden if they
+ are the only thing that triggered reinstallation.
+
+ @param pkg: _emerge.Package instance
+ Modifies self.use_expand_hidden, self.use_expand, self.verboseadd
+ """
+ reinst_flags_map = {}
+ reinstall_for_flags = self.conf.reinstall_nodes.get(pkg)
+ reinst_expand_map = None
+ if reinstall_for_flags:
+ reinst_flags_map = self.map_to_use_expand(
+ list(reinstall_for_flags), remove_hidden=False)
+ for k in list(reinst_flags_map):
+ if not reinst_flags_map[k]:
+ del reinst_flags_map[k]
+ if not reinst_flags_map.get("USE"):
+ reinst_expand_map = reinst_flags_map.copy()
+ reinst_expand_map.pop("USE", None)
+ if reinst_expand_map and \
+ not set(reinst_expand_map).difference(
+ self.use_expand_hidden):
+ self.use_expand_hidden = \
+ set(self.use_expand_hidden).difference(
+ reinst_expand_map)
+
+ cur_iuse_map, iuse_forced = \
+ self.map_to_use_expand(self.cur_iuse, forced_flags=True)
+ cur_use_map = self.map_to_use_expand(self.cur_use)
+ old_iuse_map = self.map_to_use_expand(self.old_iuse)
+ old_use_map = self.map_to_use_expand(self.old_use)
+
+ self.use_expand.sort()
+ self.use_expand.insert(0, "USE")
+
+ for key in self.use_expand:
+ if key in self.use_expand_hidden:
+ continue
+ self.verboseadd += _create_use_string(self.conf, key.upper(),
+ cur_iuse_map[key], iuse_forced[key],
+ cur_use_map[key], old_iuse_map[key],
+ old_use_map[key], self.is_new,
+ reinst_flags_map.get(key))
+ return
+
+
+ @staticmethod
+ def pkgprint(pkg_str, pkg_info):
+ """Colorizes a string acording to pkg_info settings
+
+ @param pkg_str: string
+ @param pkg_info: dictionary
+ @rtype colorized string
+ """
+ if pkg_info.merge:
+ if pkg_info.built:
+ if pkg_info.system:
+ return colorize("PKG_BINARY_MERGE_SYSTEM", pkg_str)
+ elif pkg_info.world:
+ return colorize("PKG_BINARY_MERGE_WORLD", pkg_str)
else:
- # New slot, mark it new.
- addl = " " + green("NS") + fetch + " "
- myoldbest = vardb.match(cpv_getkey(pkg_key))
- if ordered:
- counters.newslot += 1
- if pkg_type == "binary":
- counters.binary += 1
-
- if conf.changelog:
- inst_matches = vardb.match(pkg.slot_atom)
- if inst_matches:
- ebuild_path_cl = ebuild_path
- if ebuild_path_cl is None:
- # binary package
- ebuild_path_cl = portdb.findname(pkg.cpv, myrepo=pkg.repo)
-
- if ebuild_path_cl is not None:
- changelogs.extend(_calc_changelog(
- ebuild_path_cl, inst_matches[0], pkg.cpv))
+ return colorize("PKG_BINARY_MERGE", pkg_str)
else:
- addl = " " + green("N") + " " + fetch + " "
- if ordered:
- counters.new += 1
- if pkg_type == "binary":
- counters.binary += 1
-
- verboseadd = ""
- repoadd = None
-
- if True:
- # USE flag display
- forced_flags = set()
- pkgsettings.setcpv(pkg) # for package.use.{mask,force}
- forced_flags.update(pkgsettings.useforce)
- forced_flags.update(pkgsettings.usemask)
-
- cur_use = [flag for flag in conf.pkg_use_enabled(pkg) \
- if flag in pkg.iuse.all]
- cur_iuse = sorted(pkg.iuse.all)
-
- if myoldbest and myinslotlist:
- previous_cpv = myoldbest[0]
- else:
- previous_cpv = pkg.cpv
- if vardb.cpv_exists(previous_cpv):
- old_iuse, old_use = vardb.aux_get(
- previous_cpv, ["IUSE", "USE"])
- old_iuse = list(set(
- filter_iuse_defaults(old_iuse.split())))
- old_iuse.sort()
- old_use = old_use.split()
- is_new = False
- else:
- old_iuse = []
- old_use = []
- is_new = True
-
- old_use = [flag for flag in old_use if flag in old_iuse]
-
- use_expand = pkgsettings["USE_EXPAND"].lower().split()
- use_expand.sort()
- use_expand.reverse()
- use_expand_hidden = \
- pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
-
- def map_to_use_expand(myvals, forcedFlags=False,
- removeHidden=True):
- ret = {}
- forced = {}
- for exp in use_expand:
- ret[exp] = []
- forced[exp] = set()
- for val in myvals[:]:
- if val.startswith(exp.lower()+"_"):
- if val in forced_flags:
- forced[exp].add(val[len(exp)+1:])
- ret[exp].append(val[len(exp)+1:])
- myvals.remove(val)
- ret["USE"] = myvals
- forced["USE"] = [val for val in myvals \
- if val in forced_flags]
- if removeHidden:
- for exp in use_expand_hidden:
- ret.pop(exp, None)
- if forcedFlags:
- return ret, forced
- return ret
-
- # Prevent USE_EXPAND_HIDDEN flags from being hidden if they
- # are the only thing that triggered reinstallation.
- reinst_flags_map = {}
- reinstall_for_flags = conf.reinstall_nodes.get(pkg)
- reinst_expand_map = None
- if reinstall_for_flags:
- reinst_flags_map = map_to_use_expand(
- list(reinstall_for_flags), removeHidden=False)
- for k in list(reinst_flags_map):
- if not reinst_flags_map[k]:
- del reinst_flags_map[k]
- if not reinst_flags_map.get("USE"):
- reinst_expand_map = reinst_flags_map.copy()
- reinst_expand_map.pop("USE", None)
- if reinst_expand_map and \
- not set(reinst_expand_map).difference(
- use_expand_hidden):
- use_expand_hidden = \
- set(use_expand_hidden).difference(
- reinst_expand_map)
-
- cur_iuse_map, iuse_forced = \
- map_to_use_expand(cur_iuse, forcedFlags=True)
- cur_use_map = map_to_use_expand(cur_use)
- old_iuse_map = map_to_use_expand(old_iuse)
- old_use_map = map_to_use_expand(old_use)
-
- use_expand.sort()
- use_expand.insert(0, "USE")
-
- for key in use_expand:
- if key in use_expand_hidden:
- continue
- verboseadd += _create_use_string(conf, key.upper(),
- cur_iuse_map[key], iuse_forced[key],
- cur_use_map[key], old_iuse_map[key],
- old_use_map[key], is_new,
- reinst_flags_map.get(key))
-
- if conf.verbosity == 3:
- # size verbose
- mysize=0
- if pkg_type == "ebuild" and pkg_merge:
- try:
- myfilesdict = portdb.getfetchsizes(pkg_key,
- useflags=pkg_use, myrepo=pkg.repo)
- except InvalidDependString:
- # should have been masked before it was selected
- raise
- if myfilesdict is None:
- myfilesdict="[empty/missing/bad digest]"
- else:
- for myfetchfile in myfilesdict:
- if myfetchfile not in myfetchlist:
- mysize+=myfilesdict[myfetchfile]
- myfetchlist.append(myfetchfile)
- if ordered:
- counters.totalsize += mysize
- verboseadd += _format_size(mysize)
-
- # overlay verbose
- # assign index for a previous version in the same slot
- has_previous = False
- repo_name_prev = None
- slot_matches = vardb.match(pkg.slot_atom)
- if slot_matches:
- has_previous = True
- repo_name_prev = vardb.aux_get(slot_matches[0],
- ["repository"])[0]
-
- # now use the data to generate output
- if pkg.installed or not has_previous:
- repoadd = repo_display.repoStr(repo_path_real)
+ if pkg_info.system:
+ return colorize("PKG_MERGE_SYSTEM", pkg_str)
+ elif pkg_info.world:
+ return colorize("PKG_MERGE_WORLD", pkg_str)
else:
- repo_path_prev = None
- if repo_name_prev:
- repo_path_prev = portdb.getRepositoryPath(
- repo_name_prev)
- if repo_path_prev == repo_path_real:
- repoadd = repo_display.repoStr(repo_path_real)
- else:
- repoadd = "%s=>%s" % (
- repo_display.repoStr(repo_path_prev),
- repo_display.repoStr(repo_path_real))
- if repoadd:
- repoadd_set.add(repoadd)
-
- xs = [cpv_getkey(pkg_key)] + \
- list(catpkgsplit(pkg_key)[2:])
- if xs[2] == "r0":
- xs[2] = ""
- else:
- xs[2] = "-" + xs[2]
-
- oldlp = conf.columnwidth - 30
- newlp = oldlp - 30
-
- # Convert myoldbest from a list to a string.
- if not myoldbest:
- myoldbest = ""
+ return colorize("PKG_MERGE", pkg_str)
+ elif pkg_info.operation == "uninstall":
+ return colorize("PKG_UNINSTALL", pkg_str)
+ else:
+ if pkg_info.system:
+ return colorize("PKG_NOMERGE_SYSTEM", pkg_str)
+ elif pkg_info.world:
+ return colorize("PKG_NOMERGE_WORLD", pkg_str)
else:
- for pos, key in enumerate(myoldbest):
- key = catpkgsplit(key)[2] + \
- "-" + catpkgsplit(key)[3]
- if key[-3:] == "-r0":
- key = key[:-3]
- myoldbest[pos] = key
- myoldbest = blue("["+", ".join(myoldbest)+"]")
-
- pkg_cp = xs[0]
- root_config = conf.roots[myroot]
- system_set = root_config.sets["system"]
- world_set = root_config.sets["selected"]
-
- pkg_system = False
- pkg_world = False
+ return colorize("PKG_NOMERGE", pkg_str)
+
+
+ def verbose_size(self, pkg, repoadd_set, pkg_info):
+ """Determines teh size of the downloads reqired
+
+ @param pkg: _emerge.Package instance
+ @param repoadd_set: set of repos to add
+ @param pkg_info: dictionary
+ Modifies class globals: self.myfetchlist, self.counters.totalsize,
+ self.verboseadd, repoadd_set.
+ """
+ mysize = 0
+ if pkg.type_name == "ebuild" and pkg_info.merge:
try:
- pkg_system = system_set.findAtomForPackage(pkg, modified_use=conf.pkg_use_enabled(pkg))
- pkg_world = world_set.findAtomForPackage(pkg, modified_use=conf.pkg_use_enabled(pkg))
- if not (conf.oneshot or pkg_world) and \
- myroot == conf.target_root and \
- conf.favorites.findAtomForPackage(pkg, modified_use=conf.pkg_use_enabled(pkg)):
- # Maybe it will be added to world now.
- if create_world_atom(pkg, conf.favorites, root_config):
- pkg_world = True
+ myfilesdict = self.portdb.getfetchsizes(pkg.cpv,
+ useflags=pkg_info.use, myrepo=pkg.repo)
except InvalidDependString:
- # This is reported elsewhere if relevant.
- pass
-
- def pkgprint(pkg_str):
- if pkg_merge:
- if built:
- if pkg_system:
- return colorize("PKG_BINARY_MERGE_SYSTEM", pkg_str)
- elif pkg_world:
- return colorize("PKG_BINARY_MERGE_WORLD", pkg_str)
- else:
- return colorize("PKG_BINARY_MERGE", pkg_str)
- else:
- if pkg_system:
- return colorize("PKG_MERGE_SYSTEM", pkg_str)
- elif pkg_world:
- return colorize("PKG_MERGE_WORLD", pkg_str)
- else:
- return colorize("PKG_MERGE", pkg_str)
- elif pkg_status == "uninstall":
- return colorize("PKG_UNINSTALL", pkg_str)
- else:
- if pkg_system:
- return colorize("PKG_NOMERGE_SYSTEM", pkg_str)
- elif pkg_world:
- return colorize("PKG_NOMERGE_WORLD", pkg_str)
- else:
- return colorize("PKG_NOMERGE", pkg_str)
-
- if 'interactive' in pkg.metadata.properties and \
- pkg.operation == 'merge':
- addl = colorize("WARN", "I") + addl[1:]
- if ordered:
- counters.interactive += 1
-
- if x[1]!="/":
- if myoldbest:
- myoldbest +=" "
- if conf.columns:
- if conf.quiet:
- myprint=addl+" "+indent+pkgprint(pkg_cp)
- myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
- myprint=myprint+myoldbest
- myprint=myprint+darkgreen("to "+x[1])
- verboseadd = None
- else:
- if not pkg_merge:
- myprint = "[%s] %s%s" % \
- (pkgprint(pkg_status.ljust(13)),
- indent, pkgprint(pkg.cp))
- else:
- myprint = "[%s %s] %s%s" % \
- (pkgprint(pkg.type_name), addl,
- indent, pkgprint(pkg.cp))
- if (newlp-nc_len(myprint)) > 0:
- myprint=myprint+(" "*(newlp-nc_len(myprint)))
- myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
- if (oldlp-nc_len(myprint)) > 0:
- myprint=myprint+" "*(oldlp-nc_len(myprint))
- myprint=myprint+myoldbest
- myprint += darkgreen("to " + pkg.root)
- else:
- if not pkg_merge:
- myprint = "[%s] " % pkgprint(pkg_status.ljust(13))
- else:
- myprint = "[%s %s] " % (pkgprint(pkg_type), addl)
- myprint += indent + pkgprint(pkg_key) + " " + \
- myoldbest + darkgreen("to " + myroot)
+ # should have been masked before it was selected
+ raise
+ if myfilesdict is None:
+ myfilesdict = "[empty/missing/bad digest]"
else:
- if conf.columns:
- if conf.quiet:
- myprint=addl+" "+indent+pkgprint(pkg_cp)
- myprint=myprint+" "+green(xs[1]+xs[2])+" "
- myprint=myprint+myoldbest
- verboseadd = None
- else:
- if not pkg_merge:
- myprint = "[%s] %s%s" % \
- (pkgprint(pkg_status.ljust(13)),
- indent, pkgprint(pkg.cp))
- else:
- myprint = "[%s %s] %s%s" % \
- (pkgprint(pkg.type_name), addl,
- indent, pkgprint(pkg.cp))
- if (newlp-nc_len(myprint)) > 0:
- myprint=myprint+(" "*(newlp-nc_len(myprint)))
- myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
- if (oldlp-nc_len(myprint)) > 0:
- myprint=myprint+(" "*(oldlp-nc_len(myprint)))
- myprint += myoldbest
- else:
- if not pkg_merge:
- myprint = "[%s] %s%s %s" % \
- (pkgprint(pkg_status.ljust(13)),
- indent, pkgprint(pkg.cpv),
- myoldbest)
- else:
- myprint = "[%s %s] %s%s %s" % \
- (pkgprint(pkg_type), addl, indent,
- pkgprint(pkg.cpv), myoldbest)
+ for myfetchfile in myfilesdict:
+ if myfetchfile not in self.myfetchlist:
+ mysize += myfilesdict[myfetchfile]
+ self.myfetchlist.append(myfetchfile)
+ if pkg_info.ordered:
+ self.counters.totalsize += mysize
+ self.verboseadd += _format_size(mysize)
+
+ # overlay verbose
+ # assign index for a previous version in the same slot
+ slot_matches = self.vardb.match(pkg.slot_atom)
+ if slot_matches:
+ repo_name_prev = self.vardb.aux_get(slot_matches[0],
+ ["repository"])[0]
+ else:
+ repo_name_prev = None
- if conf.columns and pkg.operation == "uninstall":
+ # now use the data to generate output
+ if pkg.installed or not slot_matches:
+ repoadd = self.conf.repo_display.repoStr(
+ pkg_info.repo_path_real)
+ else:
+ repo_path_prev = None
+ if repo_name_prev:
+ repo_path_prev = self.portdb.getRepositoryPath(
+ repo_name_prev)
+ if repo_path_prev == pkg_info.repo_path_real:
+ repoadd = self.conf.repo_display.repoStr(
+ pkg_info.repo_path_real)
+ else:
+ repoadd = "%s=>%s" % (
+ self.conf.repo_display.repoStr(repo_path_prev),
+ self.conf.repo_display.repoStr(pkg_info.repo_path_real))
+ if repoadd:
+ repoadd_set.add(repoadd)
+
+
+ @staticmethod
+ def convert_myoldbest(myoldbest):
+ """converts and colorizes a version list to a string
+
+ @param myoldbest: list
+ @rtype string.
+ """
+ # Convert myoldbest from a list to a string.
+ myoldbest_str = ""
+ if myoldbest:
+ for pos, key in enumerate(myoldbest):
+ key = catpkgsplit(key)[2] + \
+ "-" + catpkgsplit(key)[3]
+ if key[-3:] == "-r0":
+ key = key[:-3]
+ myoldbest[pos] = key
+ myoldbest_str = blue("["+", ".join(myoldbest)+"]")
+ return myoldbest_str
+
+
+ def set_interactive(self, pkg, ordered, addl):
+ """Increments counters.interactive if the pkg is to
+ be merged and it's metadata has interactive set True
+
+ @param pkg: _emerge.Package instance
+ @param ordered: boolean
+ @param addl: already defined string to add to
+ """
+ if 'interactive' in pkg.metadata.properties and \
+ pkg.operation == 'merge':
+ addl = colorize("WARN", "I") + addl[1:]
+ if ordered:
+ self.counters.interactive += 1
+ return addl
+
+ def _set_non_root_columns(self, addl, pkg_info, pkg):
+ """sets the indent level and formats the output
+
+ @param addl: already defined string to add to
+ @param pkg_info: dictionary
+ @param pkg: _emerge.Package instance
+ @rtype string
+ """
+ if self.conf.quiet:
+ myprint = addl + " " + self.indent + \
+ self.pkgprint(pkg_info.cp, pkg_info)
+ myprint = myprint+darkblue(" "+pkg_info.ver)+" "
+ myprint = myprint+pkg_info.oldbest
+ myprint = myprint+darkgreen("to "+pkg.root)
+ self.verboseadd = None
+ else:
+ if not pkg_info.merge:
+ myprint = "[%s] %s%s" % \
+ (self.pkgprint(pkg_info.operation.ljust(13), pkg_info),
+ self.indent, self.pkgprint(pkg.cp, pkg_info))
+ else:
+ myprint = "[%s %s] %s%s" % \
+ (self.pkgprint(pkg.type_name, pkg_info), addl,
+ self.indent, self.pkgprint(pkg.cp, pkg_info))
+ if (self.newlp-nc_len(myprint)) > 0:
+ myprint = myprint+(" "*(self.newlp-nc_len(myprint)))
+ myprint = myprint+"["+darkblue(pkg_info.ver)+"] "
+ if (self.oldlp-nc_len(myprint)) > 0:
+ myprint = myprint+" "*(self.oldlp-nc_len(myprint))
+ myprint = myprint+pkg_info.oldbest
+ myprint += darkgreen("to " + pkg.root)
+ return myprint
+
+
+ def _set_root_columns(self, addl, pkg_info, pkg):
+ """sets the indent level and formats the output
+
+ @param addl: already defined string to add to
+ @param pkg_info: dictionary
+ @param pkg: _emerge.Package instance
+ @rtype string
+ Modifies self.verboseadd
+ """
+ if self.conf.quiet:
+ myprint = addl + " " + self.indent + \
+ self.pkgprint(pkg_info.cp, pkg_info)
+ myprint = myprint+" "+green(pkg_info.ver)+" "
+ myprint = myprint+pkg_info.oldbest
+ self.verboseadd = None
+ else:
+ if not pkg_info.merge:
+ myprint = "[%s] %s%s" % \
+ (self.pkgprint(pkg_info.operation.ljust(13), pkg_info),
+ self.indent, self.pkgprint(pkg.cp, pkg_info))
+ else:
+ myprint = "[%s %s] %s%s" % \
+ (self.pkgprint(pkg.type_name, pkg_info), addl,
+ self.indent, self.pkgprint(pkg.cp, pkg_info))
+ if (self.newlp-nc_len(myprint)) > 0:
+ myprint = myprint+(" "*(self.newlp-nc_len(myprint)))
+ myprint = myprint+green(" ["+pkg_info.ver+"] ")
+ if (self.oldlp-nc_len(myprint)) > 0:
+ myprint = myprint+(" "*(self.oldlp-nc_len(myprint)))
+ myprint += pkg_info.oldbest
+ return myprint
+
+
+ def _set_no_columns(self, pkg, pkg_info, addl):
+ """prints pkg info without column indentation.
+
+ @param pkg: _emerge.Package instance
+ @param pkg_info: dictionary
+ @param addl: the current text to add for the next line to output
+ @rtype the updated addl
+ """
+ if not pkg_info.merge:
+ myprint = "[%s] %s%s %s" % \
+ (self.pkgprint(pkg_info.operation.ljust(13),
+ pkg_info),
+ self.indent, self.pkgprint(pkg.cpv, pkg_info),
+ pkg_info.oldbest)
+ else:
+ myprint = "[%s %s] %s%s %s" % \
+ (self.pkgprint(pkg.type_name, pkg_info),
+ addl, self.indent,
+ self.pkgprint(pkg.cpv, pkg_info), pkg_info.oldbest)
+ return myprint
+
+
+ def _insert_slot(self, pkg, pkg_info, myinslotlist):
+ """Adds slot info to the message
+
+ @returns addl: formatted slot info
+ @returns myoldbest: installed version list
+ Modifies self.counters.downgrades, self.counters.upgrades,
+ self.counters.binary
+ """
+ myoldbest = myinslotlist[:]
+ addl = " " + pkg_info.fetch_symbol
+ if not cpvequal(pkg.cpv,
+ best([pkg.cpv] + myoldbest)):
+ # Downgrade in slot
+ addl += turquoise("U")+blue("D")
+ if pkg_info.ordered:
+ self.counters.downgrades += 1
+ if pkg.type_name == "binary":
+ self.counters.binary += 1
+ else:
+ # Update in slot
+ addl += turquoise("U") + " "
+ if pkg_info.ordered:
+ self.counters.upgrades += 1
+ if pkg.type_name == "binary":
+ self.counters.binary += 1
+ return addl, myoldbest
+
+
+ def _new_slot(self, pkg, pkg_info):
+ """New slot, mark it new.
+
+ @returns addl: formatted slot info
+ @returns myoldbest: installed version list
+ Modifies self.counters.newslot, self.counters.binary
+ """
+ addl = " " + green("NS") + pkg_info.fetch_symbol + " "
+ myoldbest = self.vardb.match(cpv_getkey(pkg.cpv))
+ if pkg_info.ordered:
+ self.counters.newslot += 1
+ if pkg.type_name == "binary":
+ self.counters.binary += 1
+ return addl, myoldbest
+
+
+ def print_messages(self, show_repos):
+ """Performs the actual output printing of the pre-formatted
+ messages
+
+ @param show_repos: bool.
+ """
+ for msg in self.print_msg:
+ if isinstance(msg, basestring):
+ writemsg_stdout("%s\n" % (msg,), noiselevel=-1)
continue
- p.append((myprint, verboseadd, repoadd))
-
- if not conf.tree_display and \
- conf.quiet and \
- not conf.no_restart and \
- pkg.root == conf.running_root.root and \
- match_from_list(
- PORTAGE_PACKAGE_ATOM, [pkg]) and \
- not conf.quiet:
- if not vardb.cpv_exists(pkg.cpv) or \
- '9999' in pkg.cpv or \
- 'git' in pkg.inherited:
- if mylist_index < len(mylist) - 1:
- p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
- p.append(colorize("WARN", " then resume the merge."))
-
- show_repos = repoadd_set and repoadd_set != set(["0"])
-
- for x in p:
- if isinstance(x, basestring):
- writemsg_stdout("%s\n" % (x,), noiselevel=-1)
- continue
-
- myprint, verboseadd, repoadd = x
-
- if verboseadd:
- myprint += " " + verboseadd
-
- if show_repos and repoadd:
- myprint += " " + teal("[%s]" % repoadd)
-
- writemsg_stdout("%s\n" % (myprint,), noiselevel=-1)
-
- for x in blockers:
- writemsg_stdout("%s\n" % (x,), noiselevel=-1)
-
- if conf.verbosity == 3:
- writemsg_stdout('\n%s\n' % (counters,), noiselevel=-1)
+ myprint, self.verboseadd, repoadd = msg
+ if self.verboseadd:
+ myprint += " " + self.verboseadd
+ if show_repos and repoadd:
+ myprint += " " + teal("[%s]" % repoadd)
+ writemsg_stdout("%s\n" % (myprint,), noiselevel=-1)
+ return
+
+
+ def print_blockers(self):
+ """Performs the actual output printing of the pre-formatted
+ blocker messages
+ """
+ for pkg in self.blockers:
+ writemsg_stdout("%s\n" % (pkg,), noiselevel=-1)
+ return
+
+
+ def print_verbose(self, show_repos):
+ """Prints the verbose output to std_out
+
+ @param show_repos: bool.
+ """
+ writemsg_stdout('\n%s\n' % (self.counters,), noiselevel=-1)
if show_repos:
# Use _unicode_decode() to force unicode format string so
# that RepoDisplay.__unicode__() is called in python2.
- writemsg_stdout(_unicode_decode("%s") % (repo_display,),
+ writemsg_stdout(_unicode_decode("%s") % (self.conf.repo_display,),
noiselevel=-1)
+ return
+
- if conf.changelog:
+ def print_changelog(self):
+ """Prints the changelog text to std_out
+ """
writemsg_stdout('\n', noiselevel=-1)
- for revision,text in changelogs:
+ for revision, text in self.changelogs:
writemsg_stdout(bold('*'+revision) + '\n' + text,
noiselevel=-1)
-
- return os.EX_OK
-
-
-def _create_use_string(conf, name, cur_iuse, iuse_forced, cur_use,
- old_iuse, old_use,
- is_new, reinst_flags):
-
- if not conf.print_use_string:
- return ""
-
- enabled = []
- if conf.alphabetical:
- disabled = enabled
- removed = enabled
- else:
- disabled = []
- removed = []
- cur_iuse = set(cur_iuse)
- enabled_flags = cur_iuse.intersection(cur_use)
- removed_iuse = set(old_iuse).difference(cur_iuse)
- any_iuse = cur_iuse.union(old_iuse)
- any_iuse = list(any_iuse)
- any_iuse.sort()
- for flag in any_iuse:
- flag_str = None
- isEnabled = False
- reinst_flag = reinst_flags and flag in reinst_flags
- if flag in enabled_flags:
- isEnabled = True
- if is_new or flag in old_use and \
- (conf.all_flags or reinst_flag):
- flag_str = red(flag)
- elif flag not in old_iuse:
- flag_str = yellow(flag) + "%*"
- elif flag not in old_use:
- flag_str = green(flag) + "*"
- elif flag in removed_iuse:
- if conf.all_flags or reinst_flag:
- flag_str = yellow("-" + flag) + "%"
- if flag in old_use:
- flag_str += "*"
- flag_str = "(" + flag_str + ")"
- removed.append(flag_str)
- continue
- else:
- if is_new or flag in old_iuse and \
- flag not in old_use and \
- (conf.all_flags or reinst_flag):
- flag_str = blue("-" + flag)
- elif flag not in old_iuse:
- flag_str = yellow("-" + flag)
- if flag not in iuse_forced:
- flag_str += "%"
- elif flag in old_use:
- flag_str = green("-" + flag) + "*"
- if flag_str:
- if flag in iuse_forced:
- flag_str = "(" + flag_str + ")"
- if isEnabled:
- enabled.append(flag_str)
+ return
+
+
+ def get_display_list(self, mylist):
+ """Determines the display list to process
+
+ @param mylist
+ @rtype list
+ Modifies self.counters.blocks, self.counters.blocks_satisfied,
+
+ """
+ unsatisfied_blockers = []
+ ordered_nodes = []
+ for pkg in mylist:
+ if isinstance(pkg, Blocker):
+ self.counters.blocks += 1
+ if pkg.satisfied:
+ ordered_nodes.append(pkg)
+ self.counters.blocks_satisfied += 1
+ else:
+ unsatisfied_blockers.append(pkg)
else:
- disabled.append(flag_str)
-
- if conf.alphabetical:
- ret = " ".join(enabled)
- else:
- ret = " ".join(enabled + disabled + removed)
- if ret:
- ret = '%s="%s" ' % (name, ret)
- return ret
-
-
-def _tree_display(conf, mylist):
-
- # If there are any Uninstall instances, add the
- # corresponding blockers to the digraph.
- mygraph = conf.digraph.copy()
-
- executed_uninstalls = set(node for node in mylist \
- if isinstance(node, Package) and node.operation == "unmerge")
-
- for uninstall in conf.blocker_uninstalls.leaf_nodes():
- uninstall_parents = \
- conf.blocker_uninstalls.parent_nodes(uninstall)
- if not uninstall_parents:
- continue
-
- # Remove the corresponding "nomerge" node and substitute
- # the Uninstall node.
- inst_pkg = conf.pkg(uninstall.cpv, "installed",
- uninstall.root_config, installed=True)
-
- try:
- mygraph.remove(inst_pkg)
- except KeyError:
- pass
-
+ ordered_nodes.append(pkg)
+ if self.conf.tree_display:
+ display_list = _tree_display(self.conf, ordered_nodes)
+ else:
+ display_list = [(pkg, 0, True) for pkg in ordered_nodes]
+ for pkg in unsatisfied_blockers:
+ display_list.append((pkg, 0, True))
+ return display_list
+
+
+ def set_pkg_info(self, pkg, ordered):
+ """Sets various pkg_info dictionary variables
+
+ @param pkg: _emerge.Package instance
+ @param ordered: bool
+ @rtype pkg_info dictionary
+ Modifies self.counters.restrict_fetch,
+ self.counters.restrict_fetch_satisfied
+ """
+ pkg_info = PkgInfo()
+ pkg_info.ordered = ordered
+ pkg_info.fetch_symbol = " "
+ pkg_info.operation = pkg.operation
+ pkg_info.merge = ordered and pkg_info.operation == "merge"
+ if not pkg_info.merge and pkg_info.operation == "merge":
+ pkg_info.operation = "nomerge"
+ pkg_info.built = pkg.type_name != "ebuild"
+ pkg_info.ebuild_path = None
+ pkg_info.repo_name = pkg.repo
+ if pkg.type_name == "ebuild":
+ pkg_info.ebuild_path = self.portdb.findname(
+ pkg.cpv, myrepo=pkg_info.repo_name)
+ if pkg_info.ebuild_path is None:
+ raise AssertionError(
+ "ebuild not found for '%s'" % pkg.cpv)
+ pkg_info.repo_path_real = os.path.dirname(os.path.dirname(
+ os.path.dirname(pkg_info.ebuild_path)))
+ else:
+ pkg_info.repo_path_real = \
+ self.portdb.getRepositoryPath(pkg.metadata["repository"])
+ pkg_info.use = list(self.conf.pkg_use_enabled(pkg))
+ if not pkg.built and pkg.operation == 'merge' and \
+ 'fetch' in pkg.metadata.restrict:
+ pkg_info.fetch_symbol = red("F")
+ if pkg_info.ordered:
+ self.counters.restrict_fetch += 1
+ if self.portdb.fetch_check(pkg.cpv, pkg_info.use,
+ myrepo=pkg.repo):
+ pkg_info.fetch_symbol = green("f")
+ if pkg_info.ordered:
+ self.counters.restrict_fetch_satisfied += 1
+ return pkg_info
+
+
+ def do_changelog(self, pkg, pkg_info):
+ """Processes and adds the changelog text to the master text for output
+
+ @param pkg: _emerge.Package instance
+ @param pkg_info: dictionay
+ Modifies self.changelogs
+ """
+ inst_matches = self.vardb.match(pkg.slot_atom)
+ if inst_matches:
+ ebuild_path_cl = pkg_info.ebuild_path
+ if ebuild_path_cl is None:
+ # binary package
+ ebuild_path_cl = self.portdb.findname(pkg.cpv, myrepo=pkg.repo)
+ if ebuild_path_cl is not None:
+ self.changelogs.extend(_calc_changelog(
+ ebuild_path_cl, inst_matches[0], pkg.cpv))
+ return
+
+
+ def check_system_world(self, pkg):
+ """Checks for any occurances of the package in the system or world sets
+
+ @param pkg: _emerge.Package instance
+ @rtype system and world booleans
+ """
+ root_config = self.conf.roots[pkg.root]
+ system_set = root_config.sets["system"]
+ world_set = root_config.sets["selected"]
+ system = False
+ world = False
try:
- inst_pkg_blockers = conf.blocker_parents.child_nodes(inst_pkg)
- except KeyError:
- inst_pkg_blockers = []
-
- # Break the Package -> Uninstall edges.
- mygraph.remove(uninstall)
-
- # Resolution of a package's blockers
- # depend on it's own uninstallation.
- for blocker in inst_pkg_blockers:
- mygraph.add(uninstall, blocker)
-
- # Expand Package -> Uninstall edges into
- # Package -> Blocker -> Uninstall edges.
- for blocker in uninstall_parents:
- mygraph.add(uninstall, blocker)
- for parent in conf.blocker_parents.parent_nodes(blocker):
- if parent != inst_pkg:
- mygraph.add(blocker, parent)
-
- # If the uninstall task did not need to be executed because
- # of an upgrade, display Blocker -> Upgrade edges since the
- # corresponding Blocker -> Uninstall edges will not be shown.
- upgrade_node = \
- conf.slot_pkg_map[uninstall.root].get(uninstall.slot_atom)
- if upgrade_node is not None and \
- uninstall not in executed_uninstalls:
- for blocker in uninstall_parents:
- mygraph.add(upgrade_node, blocker)
-
- if conf.unordered_display:
- display_list = _unordered_tree_display(mygraph, mylist)
- else:
- display_list = _ordered_tree_display(conf, mygraph, mylist)
-
- _prune_tree_display(display_list)
-
- return display_list
-
-def _unordered_tree_display(mygraph, mylist):
- display_list = []
- seen_nodes = set()
-
- def print_node(node, depth):
-
- if node in seen_nodes:
+ system = system_set.findAtomForPackage(
+ pkg, modified_use=self.conf.pkg_use_enabled(pkg))
+ world = world_set.findAtomForPackage(
+ pkg, modified_use=self.conf.pkg_use_enabled(pkg))
+ if not (self.conf.oneshot or world) and \
+ pkg.root == self.conf.target_root and \
+ self.conf.favorites.findAtomForPackage(
+ pkg, modified_use=self.conf.pkg_use_enabled(pkg)
+ ):
+ # Maybe it will be added to world now.
+ if create_world_atom(pkg, self.conf.favorites, root_config):
+ world = True
+ except InvalidDependString:
+ # This is reported elsewhere if relevant.
pass
+ return system, world
+
+
+ @staticmethod
+ def get_ver_str(pkg):
+ """Obtains the version string
+ @param pkg: _emerge.Package instance
+ @rtype string
+ """
+ ver_str = list(catpkgsplit(pkg.cpv)[2:])
+ if ver_str[1] == "r0":
+ ver_str[1] = ""
else:
- seen_nodes.add(node)
-
- if isinstance(node, (Blocker, Package)):
- display_list.append((node, depth, True))
+ ver_str[1] = "-" + ver_str[1]
+ return ver_str[0]+ver_str[1]
+
+
+ def _get_installed_best(self, pkg, pkg_info):
+ """ we need to use "--emptrytree" testing here rather than
+ "empty" param testing because "empty"
+ param is used for -u, where you still *do* want to see when
+ something is being upgraded.
+
+ @param pkg: _emerge.Package instance
+ @param pkg_info: dictionay
+ @rtype addl, myoldbest: list, myinslotlist: list
+ Modifies self.counters.reinst, self.counters.binary, self.counters.new
+
+ """
+ myoldbest = []
+ myinslotlist = None
+ installed_versions = self.vardb.match(cpv_getkey(pkg.cpv))
+ if self.vardb.cpv_exists(pkg.cpv):
+ addl = " "+yellow("R")+pkg_info.fetch_symbol+" "
+ if pkg_info.ordered:
+ if pkg_info.merge:
+ self.counters.reinst += 1
+ if pkg.type_name == "binary":
+ self.counters.binary += 1
+ elif pkg_info.operation == "uninstall":
+ self.counters.uninst += 1
+ # filter out old-style virtual matches
+ elif installed_versions and \
+ cpv_getkey(installed_versions[0]) == cpv_getkey(pkg.cpv):
+ myinslotlist = self.vardb.match(pkg.slot_atom)
+ # If this is the first install of a new-style virtual, we
+ # need to filter out old-style virtual matches.
+ if myinslotlist and \
+ cpv_getkey(myinslotlist[0]) != cpv_getkey(pkg.cpv):
+ myinslotlist = None
+ if myinslotlist:
+ addl, myoldbest = self._insert_slot(pkg, pkg_info, myinslotlist)
else:
- depth = -1
-
- for child_node in mygraph.child_nodes(node):
- print_node(child_node, depth + 1)
-
- for root_node in mygraph.root_nodes():
- print_node(root_node, 0)
-
- return display_list
-
-def _ordered_tree_display(conf, mygraph, mylist):
- depth = 0
- shown_edges = set()
- tree_nodes = []
- display_list = []
-
- for x in mylist:
- depth = len(tree_nodes)
- while depth and x not in \
- mygraph.child_nodes(tree_nodes[depth-1]):
- depth -= 1
- if depth:
- tree_nodes = tree_nodes[:depth]
- tree_nodes.append(x)
- display_list.append((x, depth, True))
- shown_edges.add((x, tree_nodes[depth-1]))
+ addl, myoldbest = self._new_slot(pkg, pkg_info)
+ if self.conf.changelog:
+ self.do_changelog(pkg, pkg_info)
else:
- traversed_nodes = set() # prevent endless circles
- traversed_nodes.add(x)
- def add_parents(current_node, ordered):
- parent_nodes = None
- # Do not traverse to parents if this node is an
- # an argument or a direct member of a set that has
- # been specified as an argument (system or world).
- if current_node not in conf.set_nodes:
- parent_nodes = mygraph.parent_nodes(current_node)
- if parent_nodes:
- child_nodes = set(mygraph.child_nodes(current_node))
- selected_parent = None
- # First, try to avoid a direct cycle.
- for node in parent_nodes:
- if not isinstance(node, (Blocker, Package)):
- continue
- if node not in traversed_nodes and \
- node not in child_nodes:
- edge = (current_node, node)
- if edge in shown_edges:
- continue
- selected_parent = node
- break
- if not selected_parent:
- # A direct cycle is unavoidable.
- for node in parent_nodes:
- if not isinstance(node, (Blocker, Package)):
- continue
- if node not in traversed_nodes:
- edge = (current_node, node)
- if edge in shown_edges:
- continue
- selected_parent = node
- break
- if selected_parent:
- shown_edges.add((current_node, selected_parent))
- traversed_nodes.add(selected_parent)
- add_parents(selected_parent, False)
- display_list.append((current_node,
- len(tree_nodes), ordered))
- tree_nodes.append(current_node)
- tree_nodes = []
- add_parents(x, True)
-
- return display_list
-
-def _prune_tree_display(display_list):
- last_merge_depth = 0
- for i in range(len(display_list) - 1, -1, -1):
- node, depth, ordered = display_list[i]
- if not ordered and depth == 0 and i > 0 \
- and node == display_list[i-1][0] and \
- display_list[i-1][1] == 0:
- # An ordered node got a consecutive duplicate
- # when the tree was being filled in.
- del display_list[i]
- continue
- if ordered and isinstance(node, Package) \
- and node.operation in ('merge', 'uninstall'):
- last_merge_depth = depth
- continue
- if depth >= last_merge_depth or \
- i < len(display_list) - 1 and \
- depth >= display_list[i+1][1]:
- del display_list[i]
-
-def _calc_changelog(ebuildpath,current,next):
- if ebuildpath == None or not os.path.exists(ebuildpath):
- return []
- current = '-'.join(catpkgsplit(current)[1:])
- if current.endswith('-r0'):
- current = current[:-3]
- next = '-'.join(catpkgsplit(next)[1:])
- if next.endswith('-r0'):
- next = next[:-3]
- changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
- try:
- changelog = codecs.open(_unicode_encode(changelogpath,
- encoding=_encodings['fs'], errors='strict'),
- mode='r', encoding=_encodings['repo.content'], errors='replace'
- ).read()
- except SystemExit:
- raise # Needed else can't exit
- except:
- return []
- divisions = _find_changelog_tags(changelog)
- #print 'XX from',current,'to',next
- #for div,text in divisions: print 'XX',div
- # skip entries for all revisions above the one we are about to emerge
- for i in range(len(divisions)):
- if divisions[i][0]==next:
- divisions = divisions[i:]
- break
- # find out how many entries we are going to display
- for i in range(len(divisions)):
- if divisions[i][0]==current:
- divisions = divisions[:i]
- break
- else:
- # couldnt find the current revision in the list. display nothing
- return []
- return divisions
-
-def _find_changelog_tags(changelog):
- divs = []
- release = None
- while 1:
- match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
- if match is None:
- if release is not None:
- divs.append((release,changelog))
- return divs
- if release is not None:
- divs.append((release,changelog[:match.start()]))
- changelog = changelog[match.end():]
- release = match.group(1)
- if release.endswith('.ebuild'):
- release = release[:-7]
- if release.endswith('-r0'):
- release = release[:-3]
+ addl = " " + green("N") + " " + pkg_info.fetch_symbol + " "
+ if pkg_info.ordered:
+ self.counters.new += 1
+ if pkg.type_name == "binary":
+ self.counters.binary += 1
+ return addl, myoldbest, myinslotlist
+
+
+ def __call__(self, depgraph, mylist, favorites=None, verbosity=None):
+ """The main operation to format and display the resolver output.
+
+ @param depgraph: dependency grah
+ @param mylist: list of packages being processed
+ @param favorites: list, defaults to []
+ @param verbosity: verbose level, defaults to None
+ Modifies self.conf, self.myfetchlist, self.portdb, self.vardb,
+ self.pkgsettings, self.verboseadd, self.oldlp, self.newlp,
+ self.print_msg,
+ """
+ if favorites is None:
+ favorites = []
+ self.conf = _DisplayConfig(depgraph, mylist, favorites, verbosity)
+ mylist = self.get_display_list(self.conf.mylist)
+ # files to fetch list - avoids counting a same file twice
+ # in size display (verbose mode)
+ self.myfetchlist = []
+ # Use this set to detect when all the "repoadd" strings are "[0]"
+ # and disable the entire repo display in this case.
+ repoadd_set = set()
+
+ for mylist_index in range(len(mylist)):
+ pkg, depth, ordered = mylist[mylist_index]
+ self.portdb = self.conf.trees[pkg.root]["porttree"].dbapi
+ self.vardb = self.conf.trees[pkg.root]["vartree"].dbapi
+ self.pkgsettings = self.conf.pkgsettings[pkg.root]
+ self.indent = " " * depth
+
+ if isinstance(pkg, Blocker):
+ if self._blockers(pkg, fetch_symbol=" "):
+ continue
+ else:
+ pkg_info = self.set_pkg_info(pkg, ordered)
+ addl, pkg_info.oldbest, myinslotlist = \
+ self._get_installed_best(pkg, pkg_info)
+ self.verboseadd = ""
+ repoadd = None
+ self._display_use(pkg, pkg_info.oldbest, myinslotlist)
+ self.recheck_hidden(pkg)
+ if self.conf.verbosity == 3:
+ self.verbose_size(pkg, repoadd_set, pkg_info)
+
+ pkg_info.cp = cpv_getkey(pkg.cpv)
+ pkg_info.ver = self.get_ver_str(pkg)
+
+ self.oldlp = self.conf.columnwidth - 30
+ self.newlp = self.oldlp - 30
+ pkg_info.oldbest = self.convert_myoldbest(pkg_info.oldbest)
+ pkg_info.system, pkg_info.world = \
+ self.check_system_world(pkg)
+ addl = self.set_interactive(pkg, pkg_info.ordered, addl)
+
+ if pkg.root != "/":
+ if pkg_info.oldbest:
+ pkg_info.oldbest += " "
+ if self.conf.columns:
+ myprint = self._set_non_root_columns(
+ addl, pkg_info, pkg)
+ else:
+ if not pkg_info.merge:
+ myprint = "[%s] " % (
+ self.pkgprint(pkg_info.operation.ljust(13),
+ pkg_info)
+ )
+ else:
+ myprint = "[%s %s] " % (
+ self.pkgprint(pkg.type_name, pkg_info), addl)
+ myprint += self.indent + \
+ self.pkgprint(pkg.cpv, pkg_info) + " " + \
+ pkg_info.oldbest + darkgreen("to " + pkg.root)
+ else:
+ if self.conf.columns:
+ myprint = self._set_root_columns(
+ addl, pkg_info, pkg)
+ else:
+ myprint = self._set_no_columns(
+ pkg, pkg_info, addl)
+
+ if self.conf.columns and pkg.operation == "uninstall":
+ continue
+ self.print_msg.append((myprint, self.verboseadd, repoadd))
+
+ if not self.conf.tree_display \
+ and self.conf.quiet \
+ and not self.conf.no_restart \
+ and pkg.root == self.conf.running_root.root \
+ and match_from_list(PORTAGE_PACKAGE_ATOM, [pkg]) \
+ and not self.conf.quiet:
+
+ if not self.vardb.cpv_exists(pkg.cpv) or \
+ '9999' in pkg.cpv or \
+ 'git' in pkg.inherited:
+ if mylist_index < len(mylist) - 1:
+ self.print_msg.append(
+ colorize(
+ "WARN", "*** Portage will stop merging "
+ "at this point and reload itself,"
+ )
+ )
+ self.print_msg.append(
+ colorize("WARN", " then resume the merge.")
+ )
+
+ show_repos = repoadd_set and repoadd_set != set(["0"])
+
+ # now finally print out the messages
+ self.print_messages(show_repos)
+ self.print_blockers()
+ if self.conf.verbosity == 3:
+ self.print_verbose(show_repos)
+ if self.conf.changelog:
+ self.print_changelog()
+
+ return os.EX_OK
diff --git a/pym/_emerge/resolver/output_helpers.py b/pym/_emerge/resolver/output_helpers.py
new file mode 100644
index 000000000..e5d9a2604
--- /dev/null
+++ b/pym/_emerge/resolver/output_helpers.py
@@ -0,0 +1,574 @@
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+"""Contains private suport functions for the Display class
+in output.py
+"""
+__all__ = (
+ )
+
+import codecs
+import re
+import sys
+
+from portage import os
+from portage import _encodings, _unicode_encode
+from portage._sets.base import InternalPackageSet
+from portage.output import blue, colorize, create_color_func, green, red, \
+ teal, yellow
+bad = create_color_func("BAD")
+from portage.util import writemsg
+from portage.versions import catpkgsplit
+
+from _emerge.Blocker import Blocker
+from _emerge.Package import Package
+
+
+if sys.hexversion >= 0x3000000:
+ basestring = str
+
+
+class _RepoDisplay(object):
+ def __init__(self, roots):
+ self._shown_repos = {}
+ self._unknown_repo = False
+ repo_paths = set()
+ for root_config in roots.values():
+ portdir = root_config.settings.get("PORTDIR")
+ if root_config.settings.repositories:
+ repo_paths.update(root_config.settings.repositories.repoLocationList())
+ repo_paths = list(repo_paths)
+ self._repo_paths = repo_paths
+ self._repo_paths_real = [ os.path.realpath(repo_path) \
+ for repo_path in repo_paths ]
+
+ # pre-allocate index for PORTDIR so that it always has index 0.
+ for root_config in roots.values():
+ portdb = root_config.trees["porttree"].dbapi
+ portdir = portdb.porttree_root
+ if portdir:
+ self.repoStr(portdir)
+
+ def repoStr(self, repo_path_real):
+ real_index = -1
+ if repo_path_real:
+ repo_path_real = os.path.realpath(repo_path_real)
+ real_index = self._repo_paths_real.index(repo_path_real)
+ if real_index == -1:
+ s = "?"
+ self._unknown_repo = True
+ else:
+ shown_repos = self._shown_repos
+ repo_paths = self._repo_paths
+ repo_path = repo_paths[real_index]
+ index = shown_repos.get(repo_path)
+ if index is None:
+ index = len(shown_repos)
+ shown_repos[repo_path] = index
+ s = str(index)
+ return s
+
+ def __str__(self):
+ output = []
+ shown_repos = self._shown_repos
+ unknown_repo = self._unknown_repo
+ if shown_repos or self._unknown_repo:
+ output.append("Portage tree and overlays:\n")
+ show_repo_paths = list(shown_repos)
+ for repo_path, repo_index in shown_repos.items():
+ show_repo_paths[repo_index] = repo_path
+ if show_repo_paths:
+ for index, repo_path in enumerate(show_repo_paths):
+ output.append(" "+teal("["+str(index)+"]")+" %s\n" % repo_path)
+ if unknown_repo:
+ output.append(" "+teal("[?]") + \
+ " indicates that the source repository could not be determined\n")
+ return "".join(output)
+
+ if sys.hexversion < 0x3000000:
+
+ __unicode__ = __str__
+
+ def __str__(self):
+ return _unicode_encode(self.__unicode__(),
+ encoding=_encodings['content'])
+
+
+class _PackageCounters(object):
+
+ def __init__(self):
+ self.upgrades = 0
+ self.downgrades = 0
+ self.new = 0
+ self.newslot = 0
+ self.reinst = 0
+ self.uninst = 0
+ self.blocks = 0
+ self.blocks_satisfied = 0
+ self.totalsize = 0
+ self.restrict_fetch = 0
+ self.restrict_fetch_satisfied = 0
+ self.interactive = 0
+ self.binary = 0
+
+ def __str__(self):
+ total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
+ myoutput = []
+ details = []
+ myoutput.append("Total: %s package" % total_installs)
+ if total_installs != 1:
+ myoutput.append("s")
+ if total_installs != 0:
+ myoutput.append(" (")
+ if self.upgrades > 0:
+ details.append("%s upgrade" % self.upgrades)
+ if self.upgrades > 1:
+ details[-1] += "s"
+ if self.downgrades > 0:
+ details.append("%s downgrade" % self.downgrades)
+ if self.downgrades > 1:
+ details[-1] += "s"
+ if self.new > 0:
+ details.append("%s new" % self.new)
+ if self.newslot > 0:
+ details.append("%s in new slot" % self.newslot)
+ if self.newslot > 1:
+ details[-1] += "s"
+ if self.reinst > 0:
+ details.append("%s reinstall" % self.reinst)
+ if self.reinst > 1:
+ details[-1] += "s"
+ if self.binary > 0:
+ details.append("%s binary" % self.binary)
+ if self.binary > 1:
+ details[-1] = details[-1][:-1] + "ies"
+ if self.uninst > 0:
+ details.append("%s uninstall" % self.uninst)
+ if self.uninst > 1:
+ details[-1] += "s"
+ if self.interactive > 0:
+ details.append("%s %s" % (self.interactive,
+ colorize("WARN", "interactive")))
+ myoutput.append(", ".join(details))
+ if total_installs != 0:
+ myoutput.append(")")
+ myoutput.append(", Size of downloads: %s" % _format_size(self.totalsize))
+ if self.restrict_fetch:
+ myoutput.append("\nFetch Restriction: %s package" % \
+ self.restrict_fetch)
+ if self.restrict_fetch > 1:
+ myoutput.append("s")
+ if self.restrict_fetch_satisfied < self.restrict_fetch:
+ myoutput.append(bad(" (%s unsatisfied)") % \
+ (self.restrict_fetch - self.restrict_fetch_satisfied))
+ if self.blocks > 0:
+ myoutput.append("\nConflict: %s block" % \
+ self.blocks)
+ if self.blocks > 1:
+ myoutput.append("s")
+ if self.blocks_satisfied < self.blocks:
+ myoutput.append(bad(" (%s unsatisfied)") % \
+ (self.blocks - self.blocks_satisfied))
+ return "".join(myoutput)
+
+
+class _DisplayConfig(object):
+
+ def __init__(self, depgraph, mylist, favorites, verbosity):
+ frozen_config = depgraph._frozen_config
+ dynamic_config = depgraph._dynamic_config
+
+ self.mylist = mylist
+ self.favorites = InternalPackageSet(favorites, allow_repo=True)
+ self.verbosity = verbosity
+
+ if self.verbosity is None:
+ self.verbosity = ("--quiet" in frozen_config.myopts and 1 or \
+ "--verbose" in frozen_config.myopts and 3 or 2)
+
+ self.oneshot = "--oneshot" in frozen_config.myopts or \
+ "--onlydeps" in frozen_config.myopts
+ self.columns = "--columns" in frozen_config.myopts
+ self.tree_display = "--tree" in frozen_config.myopts
+ self.alphabetical = "--alphabetical" in frozen_config.myopts
+ self.quiet = "--quiet" in frozen_config.myopts
+ self.all_flags = self.verbosity == 3 or self.quiet
+ self.print_use_string = self.verbosity != 1 or "--verbose" in frozen_config.myopts
+ self.changelog = "--changelog" in frozen_config.myopts
+ self.edebug = frozen_config.edebug
+ self.no_restart = frozen_config._opts_no_restart.intersection(frozen_config.myopts)
+ self.unordered_display = "--unordered-display" in frozen_config.myopts
+
+ mywidth = 130
+ if "COLUMNWIDTH" in frozen_config.settings:
+ try:
+ mywidth = int(frozen_config.settings["COLUMNWIDTH"])
+ except ValueError as e:
+ writemsg("!!! %s\n" % str(e), noiselevel=-1)
+ writemsg("!!! Unable to parse COLUMNWIDTH='%s'\n" % \
+ frozen_config.settings["COLUMNWIDTH"], noiselevel=-1)
+ del e
+ self.columnwidth = mywidth
+
+ self.repo_display = _RepoDisplay(frozen_config.roots)
+ self.trees = frozen_config.trees
+ self.pkgsettings = frozen_config.pkgsettings
+ self.target_root = frozen_config.target_root
+ self.running_root = frozen_config._running_root
+ self.roots = frozen_config.roots
+
+ self.blocker_parents = dynamic_config._blocker_parents
+ self.reinstall_nodes = dynamic_config._reinstall_nodes
+ self.digraph = dynamic_config.digraph
+ self.blocker_uninstalls = dynamic_config._blocker_uninstalls
+ self.slot_pkg_map = dynamic_config._slot_pkg_map
+ self.set_nodes = dynamic_config._set_nodes
+
+ self.pkg_use_enabled = depgraph._pkg_use_enabled
+ self.pkg = depgraph._pkg
+
+
+# formats a size given in bytes nicely
+def _format_size(mysize):
+ if isinstance(mysize, basestring):
+ return mysize
+ if 0 != mysize % 1024:
+ # Always round up to the next kB so that it doesn't show 0 kB when
+ # some small file still needs to be fetched.
+ mysize += 1024 - mysize % 1024
+ mystr=str(mysize//1024)
+ mycount=len(mystr)
+ while (mycount > 3):
+ mycount-=3
+ mystr=mystr[:mycount]+","+mystr[mycount:]
+ return mystr+" kB"
+
+
+def _create_use_string(conf, name, cur_iuse, iuse_forced, cur_use,
+ old_iuse, old_use,
+ is_new, reinst_flags):
+
+ if not conf.print_use_string:
+ return ""
+
+ enabled = []
+ if conf.alphabetical:
+ disabled = enabled
+ removed = enabled
+ else:
+ disabled = []
+ removed = []
+ cur_iuse = set(cur_iuse)
+ enabled_flags = cur_iuse.intersection(cur_use)
+ removed_iuse = set(old_iuse).difference(cur_iuse)
+ any_iuse = cur_iuse.union(old_iuse)
+ any_iuse = list(any_iuse)
+ any_iuse.sort()
+ for flag in any_iuse:
+ flag_str = None
+ isEnabled = False
+ reinst_flag = reinst_flags and flag in reinst_flags
+ if flag in enabled_flags:
+ isEnabled = True
+ if is_new or flag in old_use and \
+ (conf.all_flags or reinst_flag):
+ flag_str = red(flag)
+ elif flag not in old_iuse:
+ flag_str = yellow(flag) + "%*"
+ elif flag not in old_use:
+ flag_str = green(flag) + "*"
+ elif flag in removed_iuse:
+ if conf.all_flags or reinst_flag:
+ flag_str = yellow("-" + flag) + "%"
+ if flag in old_use:
+ flag_str += "*"
+ flag_str = "(" + flag_str + ")"
+ removed.append(flag_str)
+ continue
+ else:
+ if is_new or flag in old_iuse and \
+ flag not in old_use and \
+ (conf.all_flags or reinst_flag):
+ flag_str = blue("-" + flag)
+ elif flag not in old_iuse:
+ flag_str = yellow("-" + flag)
+ if flag not in iuse_forced:
+ flag_str += "%"
+ elif flag in old_use:
+ flag_str = green("-" + flag) + "*"
+ if flag_str:
+ if flag in iuse_forced:
+ flag_str = "(" + flag_str + ")"
+ if isEnabled:
+ enabled.append(flag_str)
+ else:
+ disabled.append(flag_str)
+
+ if conf.alphabetical:
+ ret = " ".join(enabled)
+ else:
+ ret = " ".join(enabled + disabled + removed)
+ if ret:
+ ret = '%s="%s" ' % (name, ret)
+ return ret
+
+
+def _tree_display(conf, mylist):
+
+ # If there are any Uninstall instances, add the
+ # corresponding blockers to the digraph.
+ mygraph = conf.digraph.copy()
+
+ executed_uninstalls = set(node for node in mylist \
+ if isinstance(node, Package) and node.operation == "unmerge")
+
+ for uninstall in conf.blocker_uninstalls.leaf_nodes():
+ uninstall_parents = \
+ conf.blocker_uninstalls.parent_nodes(uninstall)
+ if not uninstall_parents:
+ continue
+
+ # Remove the corresponding "nomerge" node and substitute
+ # the Uninstall node.
+ inst_pkg = conf.pkg(uninstall.cpv, "installed",
+ uninstall.root_config, installed=True)
+
+ try:
+ mygraph.remove(inst_pkg)
+ except KeyError:
+ pass
+
+ try:
+ inst_pkg_blockers = conf.blocker_parents.child_nodes(inst_pkg)
+ except KeyError:
+ inst_pkg_blockers = []
+
+ # Break the Package -> Uninstall edges.
+ mygraph.remove(uninstall)
+
+ # Resolution of a package's blockers
+ # depend on it's own uninstallation.
+ for blocker in inst_pkg_blockers:
+ mygraph.add(uninstall, blocker)
+
+ # Expand Package -> Uninstall edges into
+ # Package -> Blocker -> Uninstall edges.
+ for blocker in uninstall_parents:
+ mygraph.add(uninstall, blocker)
+ for parent in conf.blocker_parents.parent_nodes(blocker):
+ if parent != inst_pkg:
+ mygraph.add(blocker, parent)
+
+ # If the uninstall task did not need to be executed because
+ # of an upgrade, display Blocker -> Upgrade edges since the
+ # corresponding Blocker -> Uninstall edges will not be shown.
+ upgrade_node = \
+ conf.slot_pkg_map[uninstall.root].get(uninstall.slot_atom)
+ if upgrade_node is not None and \
+ uninstall not in executed_uninstalls:
+ for blocker in uninstall_parents:
+ mygraph.add(upgrade_node, blocker)
+
+ if conf.unordered_display:
+ display_list = _unordered_tree_display(mygraph, mylist)
+ else:
+ display_list = _ordered_tree_display(conf, mygraph, mylist)
+
+ _prune_tree_display(display_list)
+
+ return display_list
+
+
+def _unordered_tree_display(mygraph, mylist):
+ display_list = []
+ seen_nodes = set()
+
+ def print_node(node, depth):
+
+ if node in seen_nodes:
+ pass
+ else:
+ seen_nodes.add(node)
+
+ if isinstance(node, (Blocker, Package)):
+ display_list.append((node, depth, True))
+ else:
+ depth = -1
+
+ for child_node in mygraph.child_nodes(node):
+ print_node(child_node, depth + 1)
+
+ for root_node in mygraph.root_nodes():
+ print_node(root_node, 0)
+
+ return display_list
+
+
+def _ordered_tree_display(conf, mygraph, mylist):
+ depth = 0
+ shown_edges = set()
+ tree_nodes = []
+ display_list = []
+
+ for x in mylist:
+ depth = len(tree_nodes)
+ while depth and x not in \
+ mygraph.child_nodes(tree_nodes[depth-1]):
+ depth -= 1
+ if depth:
+ tree_nodes = tree_nodes[:depth]
+ tree_nodes.append(x)
+ display_list.append((x, depth, True))
+ shown_edges.add((x, tree_nodes[depth-1]))
+ else:
+ traversed_nodes = set() # prevent endless circles
+ traversed_nodes.add(x)
+ def add_parents(current_node, ordered):
+ parent_nodes = None
+ # Do not traverse to parents if this node is an
+ # an argument or a direct member of a set that has
+ # been specified as an argument (system or world).
+ if current_node not in conf.set_nodes:
+ parent_nodes = mygraph.parent_nodes(current_node)
+ if parent_nodes:
+ child_nodes = set(mygraph.child_nodes(current_node))
+ selected_parent = None
+ # First, try to avoid a direct cycle.
+ for node in parent_nodes:
+ if not isinstance(node, (Blocker, Package)):
+ continue
+ if node not in traversed_nodes and \
+ node not in child_nodes:
+ edge = (current_node, node)
+ if edge in shown_edges:
+ continue
+ selected_parent = node
+ break
+ if not selected_parent:
+ # A direct cycle is unavoidable.
+ for node in parent_nodes:
+ if not isinstance(node, (Blocker, Package)):
+ continue
+ if node not in traversed_nodes:
+ edge = (current_node, node)
+ if edge in shown_edges:
+ continue
+ selected_parent = node
+ break
+ if selected_parent:
+ shown_edges.add((current_node, selected_parent))
+ traversed_nodes.add(selected_parent)
+ add_parents(selected_parent, False)
+ display_list.append((current_node,
+ len(tree_nodes), ordered))
+ tree_nodes.append(current_node)
+ tree_nodes = []
+ add_parents(x, True)
+
+ return display_list
+
+
+def _prune_tree_display(display_list):
+ last_merge_depth = 0
+ for i in range(len(display_list) - 1, -1, -1):
+ node, depth, ordered = display_list[i]
+ if not ordered and depth == 0 and i > 0 \
+ and node == display_list[i-1][0] and \
+ display_list[i-1][1] == 0:
+ # An ordered node got a consecutive duplicate
+ # when the tree was being filled in.
+ del display_list[i]
+ continue
+ if ordered and isinstance(node, Package) \
+ and node.operation in ('merge', 'uninstall'):
+ last_merge_depth = depth
+ continue
+ if depth >= last_merge_depth or \
+ i < len(display_list) - 1 and \
+ depth >= display_list[i+1][1]:
+ del display_list[i]
+
+
+def _calc_changelog(ebuildpath,current,next):
+ if ebuildpath == None or not os.path.exists(ebuildpath):
+ return []
+ current = '-'.join(catpkgsplit(current)[1:])
+ if current.endswith('-r0'):
+ current = current[:-3]
+ next = '-'.join(catpkgsplit(next)[1:])
+ if next.endswith('-r0'):
+ next = next[:-3]
+ changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
+ try:
+ changelog = codecs.open(_unicode_encode(changelogpath,
+ encoding=_encodings['fs'], errors='strict'),
+ mode='r', encoding=_encodings['repo.content'], errors='replace'
+ ).read()
+ except SystemExit:
+ raise # Needed else can't exit
+ except:
+ return []
+ divisions = _find_changelog_tags(changelog)
+ #print 'XX from',current,'to',next
+ #for div,text in divisions: print 'XX',div
+ # skip entries for all revisions above the one we are about to emerge
+ for i in range(len(divisions)):
+ if divisions[i][0]==next:
+ divisions = divisions[i:]
+ break
+ # find out how many entries we are going to display
+ for i in range(len(divisions)):
+ if divisions[i][0]==current:
+ divisions = divisions[:i]
+ break
+ else:
+ # couldnt find the current revision in the list. display nothing
+ return []
+ return divisions
+
+
+def _find_changelog_tags(changelog):
+ divs = []
+ release = None
+ while 1:
+ match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
+ if match is None:
+ if release is not None:
+ divs.append((release,changelog))
+ return divs
+ if release is not None:
+ divs.append((release,changelog[:match.start()]))
+ changelog = changelog[match.end():]
+ release = match.group(1)
+ if release.endswith('.ebuild'):
+ release = release[:-7]
+ if release.endswith('-r0'):
+ release = release[:-3]
+
+
+class PkgInfo(object):
+ """Simple class to hold instance attributes for current
+ information about the pkg being printed.
+ """
+
+ __slots__ = ("ordered", "fetch_symbol", "operation", "merge",
+ "built", "cp", "ebuild_path", "repo_name", "repo_path_real",
+ "world", "system", "use", "oldbest", "ver"
+ )
+
+
+ def __init__(self):
+ self.built = False
+ self.cp = ''
+ self.ebuild_path = ''
+ self.fetch_symbol = ''
+ self.merge = ''
+ self.oldbest = ''
+ self.operation = ''
+ self.ordered = False
+ self.repo_path_real = ''
+ self.repo_name = ''
+ self.system = False
+ self.use = ''
+ self.ver = ''
+ self.world = False