summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pym/_emerge/PackageCounters.py85
-rw-r--r--pym/_emerge/RepoDisplay.py79
-rw-r--r--pym/_emerge/changelog.py65
-rw-r--r--pym/_emerge/depgraph.py803
-rw-r--r--pym/_emerge/format_size.py23
-rw-r--r--pym/_emerge/resolver/output.py1076
6 files changed, 1080 insertions, 1051 deletions
diff --git a/pym/_emerge/PackageCounters.py b/pym/_emerge/PackageCounters.py
deleted file mode 100644
index dc0c6ffda..000000000
--- a/pym/_emerge/PackageCounters.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright 1999-2009 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-from portage.output import colorize, create_color_func
-bad = create_color_func("BAD")
-
-from _emerge.format_size import format_size
-
-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)
-
diff --git a/pym/_emerge/RepoDisplay.py b/pym/_emerge/RepoDisplay.py
deleted file mode 100644
index 5a66b5b9c..000000000
--- a/pym/_emerge/RepoDisplay.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright 1999-2010 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-import sys
-
-from portage.output import teal
-from portage import os
-from portage import _encodings, _unicode_encode
-
-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 portdir:
- repo_paths.add(portdir)
- overlays = root_config.settings.get("PORTDIR_OVERLAY")
- if overlays:
- repo_paths.update(overlays.split())
- 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):
- """
- In python-2.x, str() can trigger a UnicodeEncodeError here,
- so call __str__() directly.
- """
- 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'])
diff --git a/pym/_emerge/changelog.py b/pym/_emerge/changelog.py
deleted file mode 100644
index d4d9076a5..000000000
--- a/pym/_emerge/changelog.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright 1999-2009 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-import codecs
-import re
-
-import portage
-from portage import os
-from portage import _encodings
-from portage import _unicode_encode
-
-def calc_changelog(ebuildpath,current,next):
- if ebuildpath == None or not os.path.exists(ebuildpath):
- return []
- current = '-'.join(portage.catpkgsplit(current)[1:])
- if current.endswith('-r0'):
- current = current[:-3]
- next = '-'.join(portage.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 as e:
- 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]
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index 9122232ff..29601562f 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -15,12 +15,11 @@ from portage import os
from portage import _unicode_decode
from portage.const import PORTAGE_PACKAGE_ATOM
from portage.dbapi import dbapi
-from portage.dbapi.dep_expand import dep_expand
from portage.dep import Atom, extract_affecting_use, check_required_use, human_readable_required_use
from portage.eapi import eapi_has_strong_blocks, eapi_has_required_use
from portage.exception import InvalidAtom
-from portage.output import bold, blue, colorize, create_color_func, darkblue, \
- darkgreen, green, nc_len, red, teal, turquoise, yellow
+from portage.output import colorize, create_color_func, \
+ darkgreen, green
bad = create_color_func("BAD")
from portage.package.ebuild.getmaskingstatus import \
_getmaskingstatus, _MaskReason
@@ -34,7 +33,6 @@ from _emerge.AtomArg import AtomArg
from _emerge.Blocker import Blocker
from _emerge.BlockerCache import BlockerCache
from _emerge.BlockerDepPriority import BlockerDepPriority
-from _emerge.changelog import calc_changelog
from _emerge.countdown import countdown
from _emerge.create_world_atom import create_world_atom
from _emerge.Dependency import Dependency
@@ -44,13 +42,10 @@ from _emerge.DepPriorityNormalRange import DepPriorityNormalRange
from _emerge.DepPrioritySatisfiedRange import DepPrioritySatisfiedRange
from _emerge.FakeVartree import FakeVartree
from _emerge._find_deep_system_runtime_deps import _find_deep_system_runtime_deps
-from _emerge.format_size import format_size
from _emerge.is_valid_package_atom import is_valid_package_atom
from _emerge.Package import Package
from _emerge.PackageArg import PackageArg
-from _emerge.PackageCounters import PackageCounters
from _emerge.PackageVirtualDbapi import PackageVirtualDbapi
-from _emerge.RepoDisplay import RepoDisplay
from _emerge.RootConfig import RootConfig
from _emerge.search import search
from _emerge.SetArg import SetArg
@@ -59,6 +54,7 @@ from _emerge.UnmergeDepPriority import UnmergeDepPriority
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
if sys.hexversion >= 0x3000000:
basestring = str
@@ -4560,791 +4556,7 @@ class depgraph(object):
# again via _show_merge_list().
self._dynamic_config._displayed_list = mylist
- if verbosity is None:
- verbosity = ("--quiet" in self._frozen_config.myopts and 1 or \
- "--verbose" in self._frozen_config.myopts and 3 or 2)
- favorites_set = InternalPackageSet(favorites)
- oneshot = "--oneshot" in self._frozen_config.myopts or \
- "--onlydeps" in self._frozen_config.myopts
- columns = "--columns" in self._frozen_config.myopts
- tree_display = "--tree" in self._frozen_config.myopts
- changelogs=[]
- p=[]
- blockers = []
-
- counters = PackageCounters()
-
- if verbosity == 1 and "--verbose" not in self._frozen_config.myopts:
- def create_use_string(*args):
- return ""
- else:
- def create_use_string(name, cur_iuse, iuse_forced, cur_use,
- old_iuse, old_use,
- is_new, reinst_flags,
- all_flags=(verbosity == 3 or "--quiet" in self._frozen_config.myopts),
- alphabetical=("--alphabetical" in self._frozen_config.myopts)):
- enabled = []
- if 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 \
- (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 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 \
- (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 alphabetical:
- ret = " ".join(enabled)
- else:
- ret = " ".join(enabled + disabled + removed)
- if ret:
- ret = '%s="%s" ' % (name, ret)
- return ret
-
- repo_display = RepoDisplay(self._frozen_config.roots)
- unsatisfied_blockers = []
- ordered_nodes = []
- for x in mylist:
- if isinstance(x, Blocker):
- counters.blocks += 1
- if x.satisfied:
- ordered_nodes.append(x)
- counters.blocks_satisfied += 1
- else:
- unsatisfied_blockers.append(x)
- else:
- ordered_nodes.append(x)
-
- if tree_display:
- display_list = self._tree_display(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 = self._frozen_config.trees[myroot]["porttree"].dbapi
- bindb = self._frozen_config.trees[myroot]["bintree"].dbapi
- vardb = self._frozen_config.trees[myroot]["vartree"].dbapi
- vartree = self._frozen_config.trees[myroot]["vartree"]
- pkgsettings = self._frozen_config.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 "--columns" in self._frozen_config.myopts and "--quiet" in self._frozen_config.myopts:
- 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 = self._dynamic_config._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 columns:
- continue
- p.append(addl)
- else:
- blockers.append(addl)
- 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"
- installed = pkg_type == "installed"
- pkg = x
- metadata = pkg.metadata
- ebuild_path = None
- repo_name = metadata["repository"]
- if pkg.type_name == "ebuild":
- ebuild_path = portdb.findname(pkg.cpv)
- 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(self._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):
- 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(portage.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 \
- portage.cpv_getkey(installed_versions[0]) == \
- portage.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 \
- portage.cpv_getkey(myinslotlist[0]) != \
- portage.cpv_getkey(pkg_key):
- myinslotlist = None
- if myinslotlist:
- myoldbest = myinslotlist[:]
- addl = " " + fetch
- if not portage.dep.cpvequal(pkg_key,
- portage.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
- else:
- # New slot, mark it new.
- addl = " " + green("NS") + fetch + " "
- myoldbest = vardb.match(portage.cpv_getkey(pkg_key))
- if ordered:
- counters.newslot += 1
- if pkg_type == "binary":
- counters.binary += 1
-
- if "--changelog" in self._frozen_config.myopts:
- 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)
-
- if ebuild_path_cl is not None:
- changelogs.extend(calc_changelog(
- ebuild_path_cl, inst_matches[0], pkg.cpv))
- 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 self._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 = self._dynamic_config._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(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 verbosity == 3:
- # size verbose
- mysize=0
- if pkg_type == "ebuild" and pkg_merge:
- try:
- myfilesdict = portdb.getfetchsizes(pkg_key,
- useflags=pkg_use, debug=self._frozen_config.edebug)
- except portage.exception.InvalidDependString as e:
- # 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)
- 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 = [portage.cpv_getkey(pkg_key)] + \
- list(portage.catpkgsplit(pkg_key)[2:])
- if xs[2] == "r0":
- xs[2] = ""
- else:
- xs[2] = "-" + xs[2]
-
- mywidth = 130
- if "COLUMNWIDTH" in self._frozen_config.settings:
- try:
- mywidth = int(self._frozen_config.settings["COLUMNWIDTH"])
- except ValueError as e:
- portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
- portage.writemsg(
- "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
- self._frozen_config.settings["COLUMNWIDTH"], noiselevel=-1)
- del e
- oldlp = mywidth - 30
- newlp = oldlp - 30
-
- # Convert myoldbest from a list to a string.
- if not myoldbest:
- myoldbest = ""
- else:
- for pos, key in enumerate(myoldbest):
- key = portage.catpkgsplit(key)[2] + \
- "-" + portage.catpkgsplit(key)[3]
- if key[-3:] == "-r0":
- key = key[:-3]
- myoldbest[pos] = key
- myoldbest = blue("["+", ".join(myoldbest)+"]")
-
- pkg_cp = xs[0]
- root_config = self._frozen_config.roots[myroot]
- system_set = root_config.sets["system"]
- world_set = root_config.sets["selected"]
-
- pkg_system = False
- pkg_world = False
- try:
- pkg_system = system_set.findAtomForPackage(pkg, modified_use=self._pkg_use_enabled(pkg))
- pkg_world = world_set.findAtomForPackage(pkg, modified_use=self._pkg_use_enabled(pkg))
- if not (oneshot or pkg_world) and \
- myroot == self._frozen_config.target_root and \
- favorites_set.findAtomForPackage(pkg, modified_use=self._pkg_use_enabled(pkg)):
- # Maybe it will be added to world now.
- if create_world_atom(pkg, favorites_set, root_config):
- pkg_world = True
- except portage.exception.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 "--columns" in self._frozen_config.myopts:
- if "--quiet" in self._frozen_config.myopts:
- 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)
- else:
- if "--columns" in self._frozen_config.myopts:
- if "--quiet" in self._frozen_config.myopts:
- 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)
-
- if columns and pkg.operation == "uninstall":
- continue
- p.append((myprint, verboseadd, repoadd))
-
- if "--tree" not in self._frozen_config.myopts and \
- "--quiet" not in self._frozen_config.myopts and \
- not self._frozen_config._opts_no_restart.intersection(self._frozen_config.myopts) and \
- pkg.root == self._frozen_config._running_root.root and \
- portage.match_from_list(
- portage.const.PORTAGE_PACKAGE_ATOM, [pkg]) and \
- "--quiet" not in self._frozen_config.myopts:
- 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 verbosity == 3:
- writemsg_stdout('\n%s\n' % (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,),
- noiselevel=-1)
-
- if "--changelog" in self._frozen_config.myopts:
- writemsg_stdout('\n', noiselevel=-1)
- for revision,text in changelogs:
- writemsg_stdout(bold('*'+revision) + '\n' + text,
- noiselevel=-1)
-
- return os.EX_OK
-
- def _tree_display(self, mylist):
-
- # If there are any Uninstall instances, add the
- # corresponding blockers to the digraph.
- mygraph = self._dynamic_config.digraph.copy()
-
- executed_uninstalls = set(node for node in mylist \
- if isinstance(node, Package) and node.operation == "unmerge")
-
- for uninstall in self._dynamic_config._blocker_uninstalls.leaf_nodes():
- uninstall_parents = \
- self._dynamic_config._blocker_uninstalls.parent_nodes(uninstall)
- if not uninstall_parents:
- continue
-
- # Remove the corresponding "nomerge" node and substitute
- # the Uninstall node.
- inst_pkg = self._pkg(uninstall.cpv, "installed",
- uninstall.root_config, installed=True)
-
- try:
- mygraph.remove(inst_pkg)
- except KeyError:
- pass
-
- try:
- inst_pkg_blockers = self._dynamic_config._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 self._dynamic_config._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 = \
- self._dynamic_config._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 "--unordered-display" in self._frozen_config.myopts:
- display_list = self._unordered_tree_display(mygraph, mylist)
- else:
- display_list = self._ordered_tree_display(mygraph, mylist)
-
- self._prune_tree_display(display_list)
-
- return display_list
-
- def _unordered_tree_display(self, 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(self, 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 self._dynamic_config._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(self, 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]
+ return display(self, mylist, favorites, verbosity)
def display_problems(self):
"""
@@ -6374,13 +5586,6 @@ def show_mask_docs():
writemsg_stdout("For more information, see the MASKED PACKAGES section in the emerge\n", noiselevel=-1)
writemsg_stdout("man page or refer to the Gentoo Handbook.\n", noiselevel=-1)
-def filter_iuse_defaults(iuse):
- for flag in iuse:
- if flag.startswith("+") or flag.startswith("-"):
- yield flag[1:]
- else:
- yield flag
-
def show_blocker_docs_link():
writemsg("\nFor more information about " + bad("Blocked Packages") + ", please refer to the following\n", noiselevel=-1)
writemsg("section of the Gentoo Linux x86 Handbook (architecture is irrelevant):\n\n", noiselevel=-1)
diff --git a/pym/_emerge/format_size.py b/pym/_emerge/format_size.py
deleted file mode 100644
index 4357b7654..000000000
--- a/pym/_emerge/format_size.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 1999-2009 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-import sys
-
-if sys.hexversion >= 0x3000000:
- basestring = str
-
-# 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"
-
diff --git a/pym/_emerge/resolver/output.py b/pym/_emerge/resolver/output.py
new file mode 100644
index 000000000..85b8be0c9
--- /dev/null
+++ b/pym/_emerge/resolver/output.py
@@ -0,0 +1,1076 @@
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+__all__ = (
+ "display", "filter_iuse_defaults",
+ )
+
+import codecs
+import re
+import sys
+
+from portage import os
+from portage import _encodings, _unicode_decode, _unicode_encode
+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
+bad = create_color_func("BAD")
+from portage.util import writemsg, 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
+
+if sys.hexversion >= 0x3000000:
+ basestring = str
+
+def filter_iuse_defaults(iuse):
+ 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 portdir:
+ repo_paths.add(portdir)
+ overlays = root_config.settings.get("PORTDIR_OVERLAY")
+ if overlays:
+ repo_paths.update(overlays.split())
+ 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):
+ """
+ In python-2.x, str() can trigger a UnicodeEncodeError here,
+ so call __str__() directly.
+ """
+ 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)
+ 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)
+ 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)
+ 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 = metadata["repository"]
+ if pkg.type_name == "ebuild":
+ ebuild_path = portdb.findname(pkg.cpv)
+ 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):
+ 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
+ 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)
+
+ if ebuild_path_cl is not None:
+ changelogs.extend(_calc_changelog(
+ ebuild_path_cl, inst_matches[0], pkg.cpv))
+ 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, debug=conf.edebug)
+ 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)
+ 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 = ""
+ 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
+ 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
+ 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)
+ 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)
+
+ if conf.columns and pkg.operation == "uninstall":
+ 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)
+ 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,),
+ noiselevel=-1)
+
+ if conf.changelog:
+ writemsg_stdout('\n', noiselevel=-1)
+ for revision,text in 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)
+ 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]