Move bin/emerge to pym/emerge/__init__.py to restore old import behavior as the load_...
authorMarius Mauch <genone@gentoo.org>
Sat, 17 Feb 2007 11:07:39 +0000 (11:07 -0000)
committerMarius Mauch <genone@gentoo.org>
Sat, 17 Feb 2007 11:07:39 +0000 (11:07 -0000)
svn path=/main/trunk/; revision=5978

bin/emerge
pym/emerge/__init__.py

index 8188715198e58cc1cc8bfd90003bc41e7c6f5221..d6e7c64d56592dcef9f759440ffcad4f39448f8d 100755 (executable)
-#!/usr/bin/python -O
-# Copyright 1999-2006 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-# $Id$
+#!/usr/bin/python
 
-import sys
-# This block ensures that ^C interrupts are handled quietly.
 try:
-       import signal
-
-       def exithandler(signum,frame):
-               signal.signal(signal.SIGINT, signal.SIG_IGN)
-               signal.signal(signal.SIGTERM, signal.SIG_IGN)
-               sys.exit(1)
-       
-       signal.signal(signal.SIGINT, exithandler)
-       signal.signal(signal.SIGTERM, exithandler)
-       signal.signal(signal.SIGPIPE, signal.SIG_DFL)
-
-except KeyboardInterrupt:
-       sys.exit(1)
-
-import os, stat
-
-os.environ["PORTAGE_LEGACY_GLOBALS"] = "false"
-try:
-       import portage
+       import emerge
 except ImportError:
        from os import path as osp
        sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
-       import portage
-del os.environ["PORTAGE_LEGACY_GLOBALS"]
-from portage import digraph, portdbapi
-from portage.const import NEWS_LIB_PATH
-
-import emerge.help
-import portage.xpak, commands, errno, re, socket, time, types
-import output
-from portage.output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
-       havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
-       xtermTitleReset, yellow
-from portage.output import create_color_func
-good = create_color_func("GOOD")
-bad = create_color_func("BAD")
-
-import portage.dep
-portage.dep._dep_check_strict = True
-import portage.util
-import portage.locks
-import portage.exception
-from portage.data import secpass
-from portage.util import normalize_path as normpath
-
-if not hasattr(__builtins__, "set"):
-       from sets import Set as set
-from itertools import chain, izip
-from UserDict import DictMixin
-
-try:
-       import cPickle
-except ImportError:
-       import pickle as cPickle
-
-class stdout_spinner(object):
-       scroll_msgs = [
-               "Gentoo Rocks ("+os.uname()[0]+")",
-               "Thank you for using Gentoo. :)",
-               "Are you actually trying to read this?",
-               "How many times have you stared at this?",
-               "We are generating the cache right now",
-               "You are paying too much attention.",
-               "A theory is better than its explanation.",
-               "Phasers locked on target, Captain.",
-               "Thrashing is just virtual crashing.",
-               "To be is to program.",
-               "Real Users hate Real Programmers.",
-               "When all else fails, read the instructions.",
-               "Functionality breeds Contempt.",
-               "The future lies ahead.",
-               "3.1415926535897932384626433832795028841971694",
-               "Sometimes insanity is the only alternative.",
-               "Inaccuracy saves a world of explanation.",
-       ]
-
-       twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
-
-       def __init__(self):
-               self.spinpos = 0
-               self.update = self.update_twirl
-               self.scroll_sequence = self.scroll_msgs[
-                       int(time.time() * 100) % len(self.scroll_msgs)]
-
-       def update_basic(self):
-               self.spinpos = (self.spinpos + 1) % 500
-               if (self.spinpos % 100) == 0:
-                       if self.spinpos == 0:
-                               sys.stdout.write(". ")
-                       else:
-                               sys.stdout.write(".")
-               sys.stdout.flush()
-
-       def update_scroll(self):
-               if(self.spinpos >= len(self.scroll_sequence)):
-                       sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
-                               len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
-               else:
-                       sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
-               sys.stdout.flush()
-               self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
-
-       def update_twirl(self):
-               self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
-               sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
-               sys.stdout.flush()
-
-       def update_quiet(self):
-               return
-
-def userquery(prompt, responses=None, colours=None):
-       """Displays a prompt and a set of responses, then waits for a response
-       which is checked against the responses and the first to match is
-       returned.  An empty response will match the first value in responses.  The
-       input buffer is *not* cleared prior to the prompt!
-
-       prompt: a String.
-       responses: a List of Strings.
-       colours: a List of Functions taking and returning a String, used to
-       process the responses for display. Typically these will be functions
-       like red() but could be e.g. lambda x: "DisplayString".
-       If responses is omitted, defaults to ["Yes", "No"], [green, red].
-       If only colours is omitted, defaults to [bold, ...].
-
-       Returns a member of the List responses. (If called without optional
-       arguments, returns "Yes" or "No".)
-       KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
-       printed."""
-       if responses is None:
-               responses, colours = ["Yes", "No"], [green, red]
-       elif colours is None:
-               colours=[bold]
-       colours=(colours*len(responses))[:len(responses)]
-       print bold(prompt),
-       try:
-               while True:
-                       response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
-                       for key in responses:
-                               # An empty response will match the first value in responses.
-                               if response.upper()==key[:len(response)].upper():
-                                       return key
-                       print "Sorry, response '%s' not understood." % response,
-       except (EOFError, KeyboardInterrupt):
-               print "Interrupted."
-               sys.exit(1)
-
-def sorted_versions(verlist):
-       ret = []
-       for ver in verlist:
-               verparts = ver.split("-")
-               if len(verparts) == 2:
-                       verrev = int(verparts[1][1:])
-               else:
-                       verrev = 0
-               x = 0
-               while x < len(ret):
-                       retparts = ret[x].split("-")
-                       verdiff = portage.vercmp(retparts[0], verparts[0])
-                       if verdiff > 0:
-                               break
-                       elif verdiff == 0:
-                               if len(retparts) == 2:
-                                       retrev = int(retparts[1][1:])
-                               else:
-                                       retrev = 0
-                               if retrev >= verrev:
-                                       break
-                       x += 1
-               ret.insert(x, ver)
-       return ret
-
-
-actions=[
-"clean", "config", "depclean",
-"info", "metadata",
-"prune", "regen",  "search",
-"sync",  "system", "unmerge",  "world",
-]
-options=[
-"--ask",          "--alphabetical",
-"--buildpkg",     "--buildpkgonly",
-"--changelog",    "--columns",
-"--debug",        "--deep",
-"--digest",
-"--emptytree",
-"--fetchonly",    "--fetch-all-uri",
-"--getbinpkg",    "--getbinpkgonly",
-"--help",         "--ignore-default-opts",
-"--noconfmem",
-"--newuse",       "--nocolor",
-"--nodeps",       "--noreplace",
-"--nospinner",    "--oneshot",
-"--onlydeps",     "--pretend",
-"--quiet",        "--resume",
-"--searchdesc",   "--selective",
-"--skipfirst",
-"--tree",
-"--update",
-"--usepkg",       "--usepkgonly",
-"--verbose",      "--version"
-]
-
-shortmapping={
-"1":"--oneshot",
-"a":"--ask",
-"b":"--buildpkg",  "B":"--buildpkgonly",
-"c":"--clean",     "C":"--unmerge",
-"d":"--debug",     "D":"--deep",
-"e":"--emptytree",
-"f":"--fetchonly", "F":"--fetch-all-uri",
-"g":"--getbinpkg", "G":"--getbinpkgonly",
-"h":"--help",
-"k":"--usepkg",    "K":"--usepkgonly",
-"l":"--changelog",
-"n":"--noreplace", "N":"--newuse",
-"o":"--onlydeps",  "O":"--nodeps",
-"p":"--pretend",   "P":"--prune",
-"q":"--quiet",
-"s":"--search",    "S":"--searchdesc",
-'t':"--tree",
-"u":"--update",
-"v":"--verbose",   "V":"--version"
-}
-
-def emergelog(xterm_titles, mystr, short_msg=None):
-       if xterm_titles:
-               if short_msg == None:
-                       short_msg = mystr
-               if "HOSTNAME" in os.environ.keys():
-                       short_msg = os.environ["HOSTNAME"]+": "+short_msg
-               xtermTitle(short_msg)
-       try:
-               file_path = "/var/log/emerge.log"
-               mylogfile = open(file_path, "a")
-               portage.util.apply_secpass_permissions(file_path,
-                       uid=portage.portage_uid, gid=portage.portage_gid,
-                       mode=0660)
-               mylock = None
-               try:
-                       mylock = portage.locks.lockfile(mylogfile)
-                       # seek because we may have gotten held up by the lock.
-                       # if so, we may not be positioned at the end of the file.
-                       mylogfile.seek(0, 2)
-                       mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
-                       mylogfile.flush()
-               finally:
-                       if mylock:
-                               portage.locks.unlockfile(mylock)
-                       mylogfile.close()
-       except (IOError,OSError,portage.exception.PortageException), e:
-               if secpass >= 1:
-                       print >> sys.stderr, "emergelog():",e
-
-def countdown(secs=5, doing="Starting"):
-       if secs:
-               print ">>> Waiting",secs,"seconds before starting..."
-               print ">>> (Control-C to abort)...\n"+doing+" in: ",
-               ticks=range(secs)
-               ticks.reverse()
-               for sec in ticks:
-                       sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
-                       sys.stdout.flush()
-                       time.sleep(1)
-               print
-
-# formats a size given in bytes nicely
-def format_size(mysize):
-       if type(mysize) not in [types.IntType,types.LongType]:
-               return str(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 getgccversion(chost):
-       """
-       rtype: C{str}
-       return:  the current in-use gcc version
-       """
-
-       gcc_ver_command = 'gcc -dumpversion'
-       gcc_ver_prefix = 'gcc-'
-
-       gcc_not_found_error = red(
-       "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
-       "!!! to update the environment of this terminal and possibly\n" +
-       "!!! other terminals also.\n"
-       )
-
-       mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
-       if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
-               part1, part2 = myoutput.split("/")
-               if part1.startswith(chost + "-"):
-                       return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
-
-       mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
-       if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
-               return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
-
-       mystatus, myoutput = commands.getstatusoutput(
-               chost + "-" + gcc_ver_command)
-       if mystatus == os.EX_OK:
-               return gcc_ver_prefix + myoutput
-
-       mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
-       if mystatus == os.EX_OK:
-               return gcc_ver_prefix + myoutput
-
-       portage.writemsg(gcc_not_found_error, noiselevel=-1)
-       return "[unavailable]"
-
-def getportageversion(portdir, target_root, profile, chost, vardb):
-       profilever = "unavailable"
-       if profile:
-               realpath = os.path.realpath(profile)
-               basepath   = os.path.realpath(os.path.join(portdir, "profiles"))
-               if realpath.startswith(basepath):
-                       profilever = realpath[1 + len(basepath):]
-               else:
-                       try:
-                               profilever = "!" + os.readlink(profile)
-                       except (OSError):
-                               pass
-               del realpath, basepath
-
-       libcver=[]
-       libclist  = vardb.match("virtual/libc")
-       libclist += vardb.match("virtual/glibc")
-       libclist  = portage.util.unique_array(libclist)
-       for x in libclist:
-               xs=portage.catpkgsplit(x)
-               if libcver:
-                       libcver+=","+"-".join(xs[1:])
-               else:
-                       libcver="-".join(xs[1:])
-       if libcver==[]:
-               libcver="unavailable"
-
-       gccver = getgccversion(chost)
-       unameout=os.uname()[2]+" "+os.uname()[4]
-
-       return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
-
-def create_depgraph_params(myopts, myaction):
-       #configure emerge engine parameters
-       #
-       # self:      include _this_ package regardless of if it is merged.
-       # selective: exclude the package if it is merged
-       # recurse:   go into the dependencies
-       # deep:      go into the dependencies of already merged packages
-       # empty:     pretend nothing is merged
-       myparams = ["recurse"]
-       add=[]
-       sub=[]
-       if "--update" in myopts or \
-               "--newuse" in myopts or \
-               "--noreplace" in myopts or \
-               myaction in ("system", "world"):
-               add.extend(["selective"])
-       if "--emptytree" in myopts:
-               add.extend(["empty"])
-               sub.extend(["selective"])
-       if "--nodeps" in myopts:
-               sub.extend(["recurse"])
-       if "--deep" in myopts:
-               add.extend(["deep"])
-       for x in add:
-               if (x not in myparams) and (x not in sub):
-                       myparams.append(x)
-       for x in sub:
-               if x in myparams:
-                       myparams.remove(x)
-       return myparams
-
-# search functionality
-class search:
-
-       #
-       # class constants
-       #
-       VERSION_SHORT=1
-       VERSION_RELEASE=2
-
-       #
-       # public interface
-       #
-       def __init__(self, settings, portdb, vartree, spinner, searchdesc,
-               verbose):
-               """Searches the available and installed packages for the supplied search key.
-               The list of available and installed packages is created at object instantiation.
-               This makes successive searches faster."""
-               self.settings = settings
-               self.portdb = portdb
-               self.vartree = vartree
-               self.spinner = spinner
-               self.verbose = verbose
-               self.searchdesc = searchdesc
-
-       def execute(self,searchkey):
-               """Performs the search for the supplied search key"""
-               match_category = 0
-               self.searchkey=searchkey
-               self.packagematches = []
-               if self.searchdesc:
-                       self.searchdesc=1
-                       self.matches = {"pkg":[], "desc":[]}
-               else:
-                       self.searchdesc=0
-                       self.matches = {"pkg":[]}
-               print "Searching...   ",
-
-               regexsearch = False
-               if self.searchkey[0] == '%':
-                       regexsearch = True
-                       self.searchkey = self.searchkey[1:]
-               if self.searchkey[0] == '@':
-                       match_category = 1
-                       self.searchkey = self.searchkey[1:]
-               if regexsearch:
-                       self.searchre=re.compile(self.searchkey,re.I)
-               else:
-                       self.searchre=re.compile(re.escape(self.searchkey), re.I)
-               for package in self.portdb.cp_all():
-                       self.spinner.update()
-
-                       if match_category:
-                               match_string  = package[:]
-                       else:
-                               match_string  = package.split("/")[-1]
-
-                       masked=0
-                       if self.searchre.search(match_string):
-                               if not self.portdb.xmatch("match-visible", package):
-                                       masked=1
-                               self.matches["pkg"].append([package,masked])
-                       elif self.searchdesc: # DESCRIPTION searching
-                               full_package = self.portdb.xmatch("bestmatch-visible", package)
-                               if not full_package:
-                                       #no match found; we don't want to query description
-                                       full_package = portage.best(
-                                               self.portdb.xmatch("match-all", package))
-                                       if not full_package:
-                                               continue
-                                       else:
-                                               masked=1
-                               try:
-                                       full_desc = self.portdb.aux_get(
-                                               full_package, ["DESCRIPTION"])[0]
-                               except KeyError:
-                                       print "emerge: search: aux_get() failed, skipping"
-                                       continue
-                               if self.searchre.search(full_desc):
-                                       self.matches["desc"].append([full_package,masked])
-               self.mlen=0
-               for mtype in self.matches.keys():
-                       self.matches[mtype].sort()
-                       self.mlen += len(self.matches[mtype])
-
-       def output(self):
-               """Outputs the results of the search."""
-               print "\b\b  \n[ Results for search key : "+white(self.searchkey)+" ]"
-               print "[ Applications found : "+white(str(self.mlen))+" ]"
-               print " "
-               for mtype in self.matches.keys():
-                       for match,masked in self.matches[mtype]:
-                               if mtype=="pkg":
-                                       catpack=match
-                                       full_package = self.portdb.xmatch(
-                                               "bestmatch-visible", match)
-                                       if not full_package:
-                                               #no match found; we don't want to query description
-                                               masked=1
-                                               full_package = portage.best(
-                                                       self.portdb.xmatch("match-all",match))
-                               else:
-                                       full_package = match
-                                       match        = portage.pkgsplit(match)[0]
-
-                               if full_package:
-                                       try:
-                                               desc, homepage, license = self.portdb.aux_get(
-                                                       full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
-                                       except KeyError:
-                                               print "emerge: search: aux_get() failed, skipping"
-                                               continue
-                                       if masked:
-                                               print green("*")+"  "+white(match)+" "+red("[ Masked ]")
-                                       else:
-                                               print green("*")+"  "+white(match)
-                                       myversion = self.getVersion(full_package, search.VERSION_RELEASE)
-
-                                       mysum = [0,0]
-                                       mycat = match.split("/")[0]
-                                       mypkg = match.split("/")[1]
-                                       mycpv = match + "-" + myversion
-                                       myebuild = self.portdb.findname(mycpv)
-                                       pkgdir = os.path.dirname(myebuild)
-                                       from portage import manifest
-                                       mf = manifest.Manifest(
-                                               pkgdir, self.settings["DISTDIR"])
-                                       fetchlist = self.portdb.getfetchlist(mycpv,
-                                               mysettings=self.settings, all=True)[1]
-                                       try:
-                                               mysum[0] = mf.getDistfilesSize(fetchlist)
-                                               mystr = str(mysum[0]/1024)
-                                               mycount=len(mystr)
-                                               while (mycount > 3):
-                                                       mycount-=3
-                                                       mystr=mystr[:mycount]+","+mystr[mycount:]
-                                               mysum[0]=mystr+" kB"
-                                       except KeyError, e:
-                                               mysum[0] = "Unknown (missing digest for %s)" % str(e)
-
-                                       if self.verbose:
-                                               print "     ", darkgreen("Latest version available:"),myversion
-                                               print "     ", self.getInstallationStatus(mycat+'/'+mypkg)
-                                               print "     ", darkgreen("Size of files:"),mysum[0]
-                                               print "     ", darkgreen("Homepage:")+"     ",homepage
-                                               print "     ", darkgreen("Description:")+"  ",desc
-                                               print "     ", darkgreen("License:")+"      ",license
-                                               print
-               print
-       #
-       # private interface
-       #
-       def getInstallationStatus(self,package):
-               installed_package = self.vartree.dep_bestmatch(package)
-               result = ""
-               version = self.getVersion(installed_package,search.VERSION_RELEASE)
-               if len(version) > 0:
-                       result = darkgreen("Latest version installed:")+" "+version
-               else:
-                       result = darkgreen("Latest version installed:")+" [ Not Installed ]"
-               return result
-
-       def getVersion(self,full_package,detail):
-               if len(full_package) > 1:
-                       package_parts = portage.catpkgsplit(full_package)
-                       if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
-                               result = package_parts[2]+ "-" + package_parts[3]
-                       else:
-                               result = package_parts[2]
-               else:
-                       result = ""
-               return result
-
-
-#build our package digraph
-def getlist(settings, mode):
-       if mode=="system":
-               mylines = settings.packages
-       elif mode=="world":
-               try:
-                       file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
-                       myfile = open(file_path, "r")
-                       mylines = myfile.readlines()
-                       myfile.close()
-               except (OSError, IOError), e:
-                       if e.errno == errno.ENOENT:
-                               portage.writemsg("\n!!! World file does not exist: '%s'\n" % file_path)
-                               mylines=[]
-                       else:
-                               raise
-       mynewlines=[]
-       for x in mylines:
-               myline=" ".join(x.split())
-               if not len(myline):
-                       continue
-               elif myline[0]=="#":
-                       continue
-               elif mode=="system":
-                       if myline[0]!="*":
-                               continue
-                       myline=myline[1:]
-               mynewlines.append(myline.strip())
-
-       return mynewlines
-
-def clean_world(vardb, cpv):
-       """Remove a package from the world file when unmerged."""
-       world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
-       worldlist = portage.util.grabfile(world_filename)
-       mykey = portage.cpv_getkey(cpv)
-       newworldlist = []
-       for x in worldlist:
-               if portage.dep_getkey(x) == mykey:
-                       matches = vardb.match(x, use_cache=0)
-                       if not matches:
-                               #zap our world entry
-                               pass
-                       elif len(matches) == 1 and matches[0] == cpv:
-                               #zap our world entry
-                               pass
-                       else:
-                               #others are around; keep it.
-                               newworldlist.append(x)
-               else:
-                       #this doesn't match the package we're unmerging; keep it.
-                       newworldlist.append(x)
-
-       portage.util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
-               gid=portage.portage_gid, mode=02770)
-       portage.util.write_atomic(world_filename, "\n".join(newworldlist))
-
-def genericdict(mylist):
-       mynewdict={}
-       for x in mylist:
-               mynewdict[portage.dep_getkey(x)]=x
-       return mynewdict
-
-def filter_iuse_defaults(iuse):
-       for flag in iuse:
-               if flag.startswith("+"):
-                       yield flag[1:]
-               else:
-                       yield flag
-
-class DepPriority(object):
-       """
-               This class generates an integer priority level based of various
-               attributes of the dependency relationship.  Attributes can be assigned
-               at any time and the new integer value will be generated on calls to the
-               __int__() method.  Rich comparison operators are supported.
-
-               The boolean attributes that affect the integer value are "satisfied",
-               "buildtime", "runtime", and "system".  Various combinations of
-               attributes lead to the following priority levels:
-
-               Combination of properties    Priority level
-
-               not satisfied and buildtime     0
-               not satisfied and runtime      -1
-               satisfied and buildtime        -2
-               satisfied and runtime          -3
-               (none of the above)            -4
-
-               Several integer constants are defined for categorization of priority
-               levels:
-
-               MEDIUM   The upper boundary for medium dependencies.
-               SOFT     The upper boundary for soft dependencies.
-               MIN      The lower boundary for soft dependencies.
-       """
-       __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime")
-       MEDIUM = -1
-       SOFT   = -2
-       MIN    = -4
-       def __init__(self, **kwargs):
-               for myattr in self.__slots__:
-                       if myattr == "__weakref__":
-                               continue
-                       myvalue = kwargs.get(myattr, False)
-                       setattr(self, myattr, myvalue)
-       def __int__(self):
-               if not self.satisfied:
-                       if self.buildtime:
-                               return 0
-                       if self.runtime:
-                               return -1
-               if self.buildtime:
-                       return -2
-               if self.runtime:
-                       return -3
-               return -4
-       def __lt__(self, other):
-               return self.__int__() < other
-       def __le__(self, other):
-               return self.__int__() <= other
-       def __eq__(self, other):
-               return self.__int__() == other
-       def __ne__(self, other):
-               return self.__int__() != other
-       def __gt__(self, other):
-               return self.__int__() > other
-       def __ge__(self, other):
-               return self.__int__() >= other
-       def copy(self):
-               import copy
-               return copy.copy(self)
-       def __str__(self):
-               myvalue = self.__int__()
-               if myvalue > self.MEDIUM:
-                       return "hard"
-               if myvalue > self.SOFT:
-                       return "medium"
-               return "soft"
-
-class FakeVartree(portage.vartree):
-       """This is implements an in-memory copy of a vartree instance that provides
-       all the interfaces required for use by the depgraph.  The vardb is locked
-       during the constructor call just long enough to read a copy of the
-       installed package information.  This allows the depgraph to do it's
-       dependency calculations without holding a lock on the vardb.  It also
-       allows things like vardb global updates to be done in memory so that the
-       user doesn't necessarily need write access to the vardb in cases where
-       global updates are necessary (updates are performed when necessary if there
-       is not a matching ebuild in the tree)."""
-       def __init__(self, real_vartree, portdb):
-               self.root = real_vartree.root
-               self.settings = real_vartree.settings
-               self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
-               vdb_path = os.path.join(self.root, portage.VDB_PATH)
-               try:
-                       # At least the parent needs to exist for the lock file.
-                       portage.util.ensure_dirs(vdb_path)
-               except portage.exception.PortageException:
-                       pass
-               vdb_lock = None
-               try:
-                       if os.access(vdb_path, os.W_OK):
-                               vdb_lock = portage.locks.lockdir(vdb_path)
-                       mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
-                               "DEPEND", "RDEPEND", "PDEPEND"]
-                       real_dbapi = real_vartree.dbapi
-                       slot_counters = {}
-                       for cpv in real_dbapi.cpv_all():
-                               metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
-                               myslot = metadata["SLOT"]
-                               mycp = portage.dep_getkey(cpv)
-                               myslot_atom = "%s:%s" % (mycp, myslot)
-                               try:
-                                       mycounter = long(metadata["COUNTER"])
-                               except ValueError:
-                                       mycounter = 0
-                                       metadata["COUNTER"] = str(mycounter)
-                               other_counter = slot_counters.get(myslot_atom, None)
-                               if other_counter is not None:
-                                       if other_counter > mycounter:
-                                               continue
-                               slot_counters[myslot_atom] = mycounter
-                               self.dbapi.cpv_inject(cpv, metadata=metadata)
-                       real_dbapi.flush_cache()
-               finally:
-                       if vdb_lock:
-                               portage.locks.unlockdir(vdb_lock)
-               # Populate the old-style virtuals using the cached values.
-               if not self.settings.treeVirtuals:
-                       self.settings.treeVirtuals = portage.util.map_dictlist_vals(
-                               portage.getCPFromCPV, self.get_all_provides())
-
-               # Intialize variables needed for lazy cache pulls of the live ebuild
-               # metadata.  This ensures that the vardb lock is released ASAP, without
-               # being delayed in case cache generation is triggered.
-               self._aux_get = self.dbapi.aux_get
-               self.dbapi.aux_get = self._aux_get_wrapper
-               self._aux_get_history = set()
-               self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
-               self._portdb = portdb
-               self._global_updates = None
-
-       def _aux_get_wrapper(self, pkg, wants):
-               if pkg in self._aux_get_history:
-                       return self._aux_get(pkg, wants)
-               self._aux_get_history.add(pkg)
-               try:
-                       # Use the live ebuild metadata if possible.
-                       live_metadata = dict(izip(self._portdb_keys,
-                               self._portdb.aux_get(pkg, self._portdb_keys)))
-                       self.dbapi.aux_update(pkg, live_metadata)
-               except (KeyError, portage.exception.PortageException):
-                       if self._global_updates is None:
-                               self._global_updates = \
-                                       grab_global_updates(self._portdb.porttree_root)
-                       perform_global_updates(
-                               pkg, self.dbapi, self._global_updates)
-               return self._aux_get(pkg, wants)
-
-def grab_global_updates(portdir):
-       from portage.update import grab_updates, parse_updates
-       updpath = os.path.join(portdir, "profiles", "updates")
-       try:
-               rawupdates = grab_updates(updpath)
-       except portage.exception.DirectoryNotFound:
-               rawupdates = []
-       upd_commands = []
-       for mykey, mystat, mycontent in rawupdates:
-               commands, errors = parse_updates(mycontent)
-               upd_commands.extend(commands)
-       return upd_commands
-
-def perform_global_updates(mycpv, mydb, mycommands):
-       from portage.update import update_dbentries
-       aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
-       aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
-       updates = update_dbentries(mycommands, aux_dict)
-       if updates:
-               mydb.aux_update(mycpv, updates)
-
-class BlockerCache(DictMixin):
-       """This caches blockers of installed packages so that dep_check does not
-       have to be done for every single installed package on every invocation of
-       emerge.  The cache is invalidated whenever it is detected that something
-       has changed that might alter the results of dep_check() calls:
-               1) the set of installed packages (including COUNTER) has changed
-               2) the old-style virtuals have changed
-       """
-       class BlockerData(object):
-               def __init__(self, counter, atoms):
-                       self.counter = counter
-                       self.atoms = atoms
-
-       def __init__(self, myroot, vardb):
-               self._vardb = vardb
-               self._installed_pkgs = set(vardb.cpv_all())
-               self._virtuals = vardb.settings.getvirtuals()
-               self._cache_filename = os.path.join(myroot,
-                       portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
-               self._cache_version = "1"
-               self._cache_data = None
-               self._modified = False
-               self._load()
-
-       def _load(self):
-               try:
-                       f = open(self._cache_filename)
-                       mypickle = cPickle.Unpickler(f)
-                       mypickle.find_global = None
-                       self._cache_data = mypickle.load()
-                       f.close()
-                       del f
-               except (IOError, OSError, EOFError, cPickle.UnpicklingError):
-                       pass
-               cache_valid = self._cache_data and \
-                       isinstance(self._cache_data, dict) and \
-                       self._cache_data.get("version") == self._cache_version and \
-                       self._cache_data.get("virtuals") == self._virtuals and \
-                       set(self._cache_data.get("blockers", [])) == self._installed_pkgs
-               if cache_valid:
-                       for pkg in self._installed_pkgs:
-                               if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
-                                       self[pkg].counter:
-                                       cache_valid = False
-                                       break
-               if not cache_valid:
-                       self._cache_data = {"version":self._cache_version}
-                       self._cache_data["blockers"] = {}
-                       self._cache_data["virtuals"] = self._virtuals
-               self._modified = False
-
-       def flush(self):
-               """If the current user has permission and the internal blocker cache
-               been updated, save it to disk and mark it unmodified.  This is called
-               by emerge after it has proccessed blockers for all installed packages.
-               Currently, the cache is only written if the user has superuser
-               privileges (since that's required to obtain a lock), but all users
-               have read access and benefit from faster blocker lookups (as long as
-               the entire cache is still valid).  The cache is stored as a pickled
-               dict object with the following format:
-
-               {
-                       version : "1",
-                       "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
-                       "virtuals" : vardb.settings.getvirtuals()
-               }
-               """
-               if self._modified and \
-                       secpass >= 2:
-                       try:
-                               f = portage.util.atomic_ofstream(self._cache_filename)
-                               cPickle.dump(self._cache_data, f, -1)
-                               f.close()
-                               portage.util.apply_secpass_permissions(
-                                       self._cache_filename, gid=portage.portage_gid, mode=0644)
-                       except (IOError, OSError), e:
-                               pass
-                       self._modified = False
-
-       def __setitem__(self, cpv, blocker_data):
-               """
-               Update the cache and mark it as modified for a future call to
-               self.flush().
-
-               @param cpv: Package for which to cache blockers.
-               @type cpv: String
-               @param blocker_data: An object with counter and atoms attributes.
-               @type blocker_data: BlockerData
-               """
-               self._cache_data["blockers"][cpv] = \
-                       (blocker_data.counter, blocker_data.atoms)
-               self._modified = True
-
-       def __getitem__(self, cpv):
-               """
-               @rtype: BlockerData
-               @returns: An object with counter and atoms attributes.
-               """
-               return self.BlockerData(*self._cache_data["blockers"][cpv])
-
-def show_invalid_depstring_notice(parent_node, depstring, error_msg):
-
-       from formatter import AbstractFormatter, DumbWriter
-       f = AbstractFormatter(DumbWriter(maxcol=72))
-
-       print "\n\n!!! Invalid or corrupt dependency specification: "
-       print
-       print error_msg
-       print
-       print parent_node
-       print
-       print depstring
-       print
-       p_type, p_root, p_key, p_status = parent_node
-       msg = []
-       if p_status == "nomerge":
-               category, pf = portage.catsplit(p_key)
-               pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
-               msg.append("Portage is unable to process the dependencies of the ")
-               msg.append("'%s' package. " % p_key)
-               msg.append("In order to correct this problem, the package ")
-               msg.append("should be uninstalled, reinstalled, or upgraded. ")
-               msg.append("As a temporary workaround, the --nodeps option can ")
-               msg.append("be used to ignore all dependencies.  For reference, ")
-               msg.append("the problematic dependencies can be found in the ")
-               msg.append("*DEPEND files located in '%s/'." % pkg_location)
-       else:
-               msg.append("This package can not be installed.  ")
-               msg.append("Please notify the '%s' package maintainer " % p_key)
-               msg.append("about this problem.")
-
-       for x in msg:
-               f.add_flowing_data(x)
-       f.end_paragraph(1)
-
-class depgraph:
-
-       pkg_tree_map = {
-               "ebuild":"porttree",
-               "binary":"bintree",
-               "installed":"vartree"}
-
-       def __init__(self, settings, trees, myopts, myparams, spinner):
-               self.settings = settings
-               self.target_root = settings["ROOT"]
-               self.myopts = myopts
-               self.myparams = myparams
-               self.edebug = 0
-               if settings.get("PORTAGE_DEBUG", "") == "1":
-                       self.edebug = 1
-               self.spinner = spinner
-               self.pkgsettings = {}
-               # Maps cpv to digraph node for all nodes added to the graph.
-               self.pkg_node_map = {}
-               # Maps slot atom to digraph node for all nodes added to the graph.
-               self._slot_node_map = {}
-               self.mydbapi = {}
-               self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND"]
-               self.useFlags = {}
-               self.trees = {}
-               for myroot in trees:
-                       self.trees[myroot] = {}
-                       for tree in ("porttree", "bintree"):
-                               self.trees[myroot][tree] = trees[myroot][tree]
-                       self.trees[myroot]["vartree"] = \
-                               FakeVartree(trees[myroot]["vartree"],
-                                       trees[myroot]["porttree"].dbapi)
-                       self.pkgsettings[myroot] = portage.config(
-                               clone=self.trees[myroot]["vartree"].settings)
-                       self.pkg_node_map[myroot] = {}
-                       self._slot_node_map[myroot] = {}
-                       vardb = self.trees[myroot]["vartree"].dbapi
-                       # This fakedbapi instance will model the state that the vdb will
-                       # have after new packages have been installed.
-                       fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
-                       self.mydbapi[myroot] = fakedb
-                       if "--nodeps" not in self.myopts and \
-                               "--buildpkgonly" not in self.myopts:
-                               # --nodeps bypasses this, since it isn't needed in this case
-                               # and the cache pulls might trigger (slow) cache generation.
-                               for pkg in vardb.cpv_all():
-                                       self.spinner.update()
-                                       fakedb.cpv_inject(pkg,
-                                               metadata=dict(izip(self._mydbapi_keys,
-                                               vardb.aux_get(pkg, self._mydbapi_keys))))
-                       del vardb, fakedb
-                       self.useFlags[myroot] = {}
-                       if "--usepkg" in self.myopts:
-                               self.trees[myroot]["bintree"].populate(
-                                       "--getbinpkg" in self.myopts,
-                                       "--getbinpkgonly" in self.myopts)
-               del trees
-
-               self.missingbins=[]
-               self.digraph=portage.digraph()
-               # Tracks simple parent/child relationships (PDEPEND relationships are
-               # not reversed).
-               self._parent_child_digraph = digraph()
-               self.orderedkeys=[]
-               self.outdatedpackages=[]
-               self.args_keys = []
-               self.blocker_digraph = digraph()
-               self.blocker_parents = {}
-               self._slot_collision_info = []
-               # Slot collision nodes are not allowed to block other packages since
-               # blocker validation is only able to account for one package per slot.
-               self._slot_collision_nodes = set()
-               self._altlist_cache = {}
-               self._pprovided_args = []
-
-       def _show_slot_collision_notice(self, packages):
-               """Show an informational message advising the user to mask one of the
-               the packages. In some cases it may be possible to resolve this
-               automatically, but support for backtracking (removal nodes that have
-               already been selected) will be required in order to handle all possible
-               cases."""
-
-               msg = []
-               msg.append("\n!!! Multiple versions within a single " + \
-                       "package slot have been \n")
-               msg.append("!!! pulled into the dependency graph:\n\n")
-               for node, parents in packages:
-                       msg.append(str(node))
-                       if parents:
-                               msg.append(" pulled in by\n")
-                               for parent in parents:
-                                       msg.append("  ")
-                                       msg.append(str(parent))
-                                       msg.append("\n")
-                       else:
-                               msg.append(" (no parents)\n")
-                       msg.append("\n")
-               sys.stderr.write("".join(msg))
-               sys.stderr.flush()
-
-               if "--quiet" in self.myopts:
-                       return
-
-               msg = []
-               msg.append("It may be possible to solve this problem ")
-               msg.append("by using package.mask to prevent one of ")
-               msg.append("those packages from being selected. ")
-               msg.append("However, it is also possible that conflicting ")
-               msg.append("dependencies exist such that they are impossible to ")
-               msg.append("satisfy simultaneously.  If such a conflict exists in ")
-               msg.append("the dependencies of two different packages, then those ")
-               msg.append("packages can not be installed simultaneously.")
-
-               from formatter import AbstractFormatter, DumbWriter
-               f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
-               for x in msg:
-                       f.add_flowing_data(x)
-               f.end_paragraph(1)
-
-               msg = []
-               msg.append("For more information, see MASKED PACKAGES ")
-               msg.append("section in the emerge man page or refer ")
-               msg.append("to the Gentoo Handbook.")
-               for x in msg:
-                       f.add_flowing_data(x)
-               f.end_paragraph(1)
-               f.writer.flush()
-
-       def create(self, mybigkey, myparent=None, addme=1, myuse=None,
-               priority=DepPriority(), rev_dep=False, arg=None):
-               """
-               Fills the digraph with nodes comprised of packages to merge.
-               mybigkey is the package spec of the package to merge.
-               myparent is the package depending on mybigkey ( or None )
-               addme = Should we add this package to the digraph or are we just looking at it's deps?
-                       Think --onlydeps, we need to ignore packages in that case.
-               #stuff to add:
-               #SLOT-aware emerge
-               #IUSE-aware emerge -> USE DEP aware depgraph
-               #"no downgrade" emerge
-               """
-               mytype, myroot, mykey = mybigkey
-               existing_node = None
-               if addme:
-                       existing_node = self.pkg_node_map[myroot].get(mykey)
-               if existing_node:
-                       self._parent_child_digraph.add(existing_node, myparent)
-                       if existing_node != myparent:
-                               # Refuse to make a node depend on itself so that the we don't
-                               # don't create a bogus circular dependency in self.altlist().
-                               if rev_dep and myparent:
-                                       self.digraph.addnode(myparent, existing_node,
-                                               priority=priority)
-                               else:
-                                       self.digraph.addnode(existing_node, myparent,
-                                               priority=priority)
-                       return 1
-               
-               self.spinner.update()
-               if mytype == "blocks":
-                       if myparent and \
-                               "--buildpkgonly" not in self.myopts and \
-                               "--nodeps" not in self.myopts and \
-                               myparent not in self._slot_collision_nodes:
-                               mybigkey[1] = myparent[1]
-                               self.blocker_parents.setdefault(
-                                       tuple(mybigkey), set()).add(myparent)
-                       return 1
-               if not arg and myroot == self.target_root:
-                       arg = portage.best_match_to_list(mykey, self.args_keys)
-               # select the correct /var database that we'll be checking against
-               vardbapi = self.trees[myroot]["vartree"].dbapi
-               portdb = self.trees[myroot]["porttree"].dbapi
-               bindb = self.trees[myroot]["bintree"].dbapi
-               pkgsettings = self.pkgsettings[myroot]
-
-               # if the package is already on the system, we add a "nomerge"
-               # directive, otherwise we add a "merge" directive.
-
-               mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
-
-               if myuse is None:
-                       self.pkgsettings[myroot].setcpv(mykey, mydb=portdb)
-                       myuse = self.pkgsettings[myroot]["USE"].split()
-
-               merging=1
-               if mytype == "installed":
-                       merging = 0
-               if addme and mytype != "installed":
-               # this is where we add the node to the list of packages to merge
-                       if "selective" in self.myparams or not arg:
-                               if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
-                                       merging=0
-
-                       """ If we aren't merging, perform the --newuse check.
-                           If the package has new iuse flags or different use flags then if
-                           --newuse is specified, we need to merge the package. """
-                       if merging==0 and "--newuse" in self.myopts and \
-                               vardbapi.cpv_exists(mykey):
-                               pkgsettings.setcpv(mykey, mydb=mydbapi)
-                               forced_flags = set()
-                               forced_flags.update(pkgsettings.useforce)
-                               forced_flags.update(pkgsettings.usemask)
-                               old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
-                               iuses = set(filter_iuse_defaults(
-                                       mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
-                               old_iuse = set(filter_iuse_defaults(
-                                       vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
-                               if iuses.symmetric_difference(
-                                       old_iuse).difference(forced_flags):
-                                       merging = 1
-                               elif old_iuse.intersection(old_use) != \
-                                       iuses.intersection(myuse):
-                                       merging=1
-
-               if addme and merging == 1:
-                       mybigkey.append("merge")
-               else:
-                       mybigkey.append("nomerge")
-               jbigkey = tuple(mybigkey)
-
-               if addme:
-                       metadata = dict(izip(self._mydbapi_keys,
-                               mydbapi.aux_get(mykey, self._mydbapi_keys)))
-                       if merging == 0 and vardbapi.cpv_exists(mykey):
-                               metadata["USE"] = vardbapi.aux_get(mykey, ["USE"])[0]
-                               myuse = metadata["USE"].split()
-                               metadata["SLOT"] = vardbapi.aux_get(mykey, ["SLOT"])[0]
-                       slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
-                       existing_node = self._slot_node_map[myroot].get(
-                               slot_atom, None)
-                       slot_collision = False
-                       if existing_node:
-                               e_type, myroot, e_cpv, e_status = existing_node
-                               if mykey == e_cpv:
-                                       # The existing node can be reused.
-                                       self._parent_child_digraph.add(existing_node, myparent)
-                                       if rev_dep and myparent:
-                                               ptype, proot, pkey, pstatus = myparent
-                                               self.digraph.addnode(myparent, existing_node,
-                                                       priority=priority)
-                                       else:
-                                               self.digraph.addnode(existing_node, myparent,
-                                                       priority=priority)
-                                       return 1
-                               else:
-                                       # A slot collision has occurred.  Sometimes this coincides
-                                       # with unresolvable blockers, so the slot collision will be
-                                       # shown later if there are no unresolvable blockers.
-                                       e_parents = self._parent_child_digraph.parent_nodes(
-                                               existing_node)
-                                       myparents = []
-                                       if myparent:
-                                               myparents.append(myparent)
-                                       self._slot_collision_info.append(
-                                               ((jbigkey, myparents), (existing_node, e_parents)))
-                                       self._slot_collision_nodes.add(jbigkey)
-                                       slot_collision = True
-
-                       if slot_collision:
-                               # Now add this node to the graph so that self.display()
-                               # can show use flags and --tree portage.output.  This node is
-                               # only being partially added to the graph.  It must not be
-                               # allowed to interfere with the other nodes that have been
-                               # added.  Do not overwrite data for existing nodes in
-                               # self.pkg_node_map and self.mydbapi since that data will
-                               # be used for blocker validation.
-                               self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
-                               self.useFlags[myroot].setdefault(mykey, myuse)
-                               # Even though the graph is now invalid, continue to process
-                               # dependencies so that things like --fetchonly can still
-                               # function despite collisions.
-                       else:
-                               self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
-                               self._slot_node_map[myroot][slot_atom] = jbigkey
-                               self.pkg_node_map[myroot][mykey] = jbigkey
-                               self.useFlags[myroot][mykey] = myuse
-
-                       if rev_dep and myparent:
-                               self.digraph.addnode(myparent, jbigkey,
-                                       priority=priority)
-                       else:
-                               self.digraph.addnode(jbigkey, myparent,
-                                       priority=priority)
-
-               # Do this even when addme is False (--onlydeps) so that the
-               # parent/child relationship is always known in case
-               # self._show_slot_collision_notice() needs to be called later.
-               self._parent_child_digraph.add(jbigkey, myparent)
-
-               """ 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.
-               """
-               if "deep" not in self.myparams and not merging and \
-                       not ("--update" in self.myopts and arg and merging):
-                       return 1
-               elif "recurse" not in self.myparams:
-                       return 1
-
-               """ Check DEPEND/RDEPEND/PDEPEND/SLOT
-               Pull from bintree if it's binary package, porttree if it's ebuild.
-               Binpkg's can be either remote or local. """
-
-               edepend={}
-               depkeys = ["DEPEND","RDEPEND","PDEPEND"]
-               depvalues = mydbapi.aux_get(mykey, depkeys)
-               for i in xrange(len(depkeys)):
-                       edepend[depkeys[i]] = depvalues[i]
-
-               if mytype == "ebuild":
-                       if "--buildpkgonly" in self.myopts:
-                               edepend["RDEPEND"] = ""
-                               edepend["PDEPEND"] = ""
-               if not (arg and "--onlydeps" in self.myopts and \
-                       mytype == "ebuild") and \
-                       self.myopts.get("--with-bdeps", "n") == "n" and \
-                       (mytype == "binary" or mybigkey[3] == "nomerge"):
-                       edepend["DEPEND"] = ""
-
-               """ We have retrieve the dependency information, now we need to recursively
-                   process them.  DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
-               
-               mp = tuple(mybigkey)
-
-               try:
-                       if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
-                               myuse=myuse, priority=DepPriority(buildtime=True),
-                               parent_arg=arg):
-                               return 0
-                       """RDEPEND is soft by definition.  However, in order to ensure
-                       correct merge order, we make it a hard dependency.  Otherwise, a
-                       build time dependency might not be usable due to it's run time
-                       dependencies not being installed yet.
-                       """
-                       if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
-                               myuse=myuse, priority=DepPriority(runtime=True),
-                               parent_arg=arg):
-                               return 0
-                       if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
-                               # Post Depend -- Add to the list without a parent, as it depends
-                               # on a package being present AND must be built after that package.
-                               if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
-                                       myuse=myuse, priority=DepPriority(), rev_deps=True,
-                                       parent_arg=arg):
-                                       return 0
-               except ValueError, e:
-                       pkgs = e.args[0]
-                       portage.writemsg("\n\n!!! An atom in the dependencies " + \
-                               "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
-                       for cpv in pkgs:
-                               portage.writemsg("    %s\n" % cpv, noiselevel=-1)
-                       portage.writemsg("\n", noiselevel=-1)
-                       if mytype == "binary":
-                               portage.writemsg(
-                                       "!!! This binary package cannot be installed: '%s'\n" % \
-                                       mykey, noiselevel=-1)
-                       elif mytype == "ebuild":
-                               myebuild, mylocation = portdb.findname2(mykey)
-                               portage.writemsg("!!! This ebuild cannot be installed: " + \
-                                       "'%s'\n" % myebuild, noiselevel=-1)
-                       portage.writemsg("!!! Please notify the package maintainer " + \
-                               "that atoms must be fully-qualified.\n", noiselevel=-1)
-                       return 0
-               return 1
-
-       def select_files(self,myfiles):
-               "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
-               myfavorites=[]
-               myroot = self.target_root
-               portdb = self.trees[myroot]["porttree"].dbapi
-               bindb = self.trees[myroot]["bintree"].dbapi
-               pkgsettings = self.pkgsettings[myroot]
-               arg_atoms = []
-               def visible(mylist):
-                       matches = portdb.gvisible(portdb.visible(mylist))
-                       return [x for x in mylist \
-                               if x in matches or not portdb.cpv_exists(x)]
-               for x in myfiles:
-                       ext = os.path.splitext(x)[1]
-                       if ext==".tbz2":
-                               if not os.path.exists(x):
-                                       if os.path.exists(
-                                               os.path.join(pkgsettings["PKGDIR"], "All", x)):
-                                               x = os.path.join(pkgsettings["PKGDIR"], "All", x)
-                                       elif os.path.exists(
-                                               os.path.join(pkgsettings["PKGDIR"], x)):
-                                               x = os.path.join(pkgsettings["PKGDIR"], x)
-                                       else:
-                                               print "\n\n!!! Binary package '"+str(x)+"' does not exist."
-                                               print "!!! Please ensure the tbz2 exists as specified.\n"
-                                               sys.exit(1)
-                               mytbz2=portage.xpak.tbz2(x)
-                               mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
-                               if os.path.realpath(x) != \
-                                       os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
-                                       print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
-                                       sys.exit(1)
-                               if not self.create(["binary", myroot, mykey],
-                                       None, "--onlydeps" not in self.myopts):
-                                       return (0,myfavorites)
-                               elif not "--oneshot" in self.myopts:
-                                       myfavorites.append(mykey)
-                       elif ext==".ebuild":
-                               x = os.path.realpath(x)
-                               mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
-                               ebuild_path = portdb.findname(mykey)
-                               if ebuild_path:
-                                       if os.path.realpath(ebuild_path) != x:
-                                               print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
-                                               sys.exit(1)
-                                       if mykey not in portdb.xmatch(
-                                               "match-visible", portage.dep_getkey(mykey)):
-                                               print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
-                                               print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
-                                               print colorize("BAD", "*** page for details.")
-                                               countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
-                                                       "Continuing...")
-                               else:
-                                       raise portage.exception.PackageNotFound(
-                                               "%s is not in a valid portage tree hierarchy or does not exist" % x)
-                               if not self.create(["ebuild", myroot, mykey],
-                                       None, "--onlydeps" not in self.myopts):
-                                       return (0,myfavorites)
-                               elif not "--oneshot" in self.myopts:
-                                       myfavorites.append(mykey)
-                       else:
-                               if not is_valid_package_atom(x):
-                                       portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
-                                               noiselevel=-1)
-                                       portage.writemsg("!!! Please check ebuild(5) for full details.\n")
-                                       portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
-                                       return (0,[])
-                               try:
-                                       mykey = None
-                                       if "--usepkg" in self.myopts:
-                                               mykey = portage.dep_expand(x, mydb=bindb,
-                                                       settings=pkgsettings)
-                                       if (mykey and not mykey.startswith("null/")) or \
-                                               "--usepkgonly" in self.myopts:
-                                               arg_atoms.append((x, mykey))
-                                               continue
-
-                                       mykey = portage.dep_expand(x,
-                                               mydb=portdb, settings=pkgsettings)
-                                       arg_atoms.append((x, mykey))
-                               except ValueError, errpkgs:
-                                       print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous.  Please specify"
-                                       print "!!! one of the following fully-qualified ebuild names instead:\n"
-                                       for i in errpkgs[0]:
-                                               print "    " + green(i)
-                                       print
-                                       sys.exit(1)
-
-               if "--update" in self.myopts:
-                       """Make sure all installed slots are updated when possible. Do this
-                       with --emptytree also, to ensure that all slots are remerged."""
-                       vardb = self.trees[self.target_root]["vartree"].dbapi
-                       greedy_atoms = []
-                       for myarg, myatom in arg_atoms:
-                               greedy_atoms.append((myarg, myatom))
-                               myslots = set()
-                               for cpv in vardb.match(myatom):
-                                       myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
-                               if myslots:
-                                       best_pkgs = []
-                                       if "--usepkg" in self.myopts:
-                                               mymatches = bindb.match(myatom)
-                                               if "--usepkgonly" not in self.myopts:
-                                                       mymatches = visible(mymatches)
-                                               best_pkg = portage.best(mymatches)
-                                               if best_pkg:
-                                                       best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
-                                                       best_pkgs.append(("binary", best_pkg, best_slot))
-                                       if "--usepkgonly" not in self.myopts:
-                                               best_pkg = portage.best(portdb.match(myatom))
-                                               if best_pkg:
-                                                       best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
-                                                       best_pkgs.append(("ebuild", best_pkg, best_slot))
-                                       if best_pkgs:
-                                               best_pkg = portage.best([x[1] for x in best_pkgs])
-                                               best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
-                                               best_slot = best_pkgs[0][2]
-                                               myslots.add(best_slot)
-                               if len(myslots) > 1:
-                                       for myslot in myslots:
-                                               myslot_atom = "%s:%s" % \
-                                                       (portage.dep_getkey(myatom), myslot)
-                                               available = False
-                                               if "--usepkgonly" not in self.myopts and \
-                                                       self.trees[self.target_root][
-                                                       "porttree"].dbapi.match(myslot_atom):
-                                                       available = True
-                                               elif "--usepkg" in self.myopts:
-                                                       mymatches = bindb.match(myslot_atom)
-                                                       if "--usepkgonly" not in self.myopts:
-                                                               mymatches = visible(mymatches)
-                                                       if mymatches:
-                                                               available = True
-                                               if available:
-                                                       greedy_atoms.append((myarg, myslot_atom))
-                       arg_atoms = greedy_atoms
-
-               """ These are used inside self.create() in order to ensure packages
-               that happen to match arguments are not incorrectly marked as nomerge."""
-               self.args_keys = [x[1] for x in arg_atoms]
-               for myarg, myatom in arg_atoms:
-                               try:
-                                       self.mysd = self.select_dep(myroot, myatom, arg=myarg)
-                               except portage.exception.MissingSignature, e:
-                                       portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
-                                       portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
-                                       portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
-                                       portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
-                                       portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
-                                       sys.exit(1)
-                               except portage.exception.InvalidSignature, e:
-                                       portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
-                                       portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
-                                       portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
-                                       portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
-                                       portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
-                                       sys.exit(1)
-                               except SystemExit, e:
-                                       raise # Needed else can't exit
-                               except Exception, e:
-                                       print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
-                                       print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
-                                       raise
-
-                               if not self.mysd:
-                                       return (0,myfavorites)
-                               elif not "--oneshot" in self.myopts:
-                                       mykey = portage.dep_getkey(myatom)
-                                       if mykey not in myfavorites:
-                                               myfavorites.append(mykey)
-
-               missing=0
-               if "--usepkgonly" in self.myopts:
-                       for xs in self.digraph.all_nodes():
-                               if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
-                                       if missing == 0:
-                                               print
-                                       missing += 1
-                                       print "Missing binary for:",xs[2]
-
-               if not self.validate_blockers():
-                       return False, myfavorites
-               
-               # We're true here unless we are missing binaries.
-               return (not missing,myfavorites)
-
-       def select_dep(self, myroot, depstring, myparent=None, arg=None,
-               myuse=None, raise_on_missing=False, priority=DepPriority(),
-               rev_deps=False, parent_arg=None):
-               """ Given a depstring, create the depgraph such that all dependencies are satisfied.
-                   myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
-                   myparent = the node whose depstring is being passed in
-                   arg = package was specified on the command line, merge even if it's already installed
-                   myuse = USE flags at present
-                   raise_on_missing = Given that the depgraph is not proper, raise an exception if true
-                   else continue trying.
-                   return 1 on success, 0 for failure
-               """
-
-               portdb = self.trees[myroot]["porttree"].dbapi
-               bindb  = self.trees[myroot]["bintree"].dbapi
-               vardb  = self.trees[myroot]["vartree"].dbapi
-               pkgsettings = self.pkgsettings[myroot]
-               if myparent:
-                       p_type, p_root, p_key, p_status = myparent
-
-               if "--debug" in self.myopts:
-                       print
-                       print "Parent:   ",myparent
-                       print "Depstring:",depstring
-                       if rev_deps:
-                               print "Reverse:", rev_deps
-                       print "Priority:", priority
-
-               #processing dependencies
-               """ Call portage.dep_check to evaluate the use? conditionals and make sure all
-               dependencies are satisfiable. """
-               try:
-                       if myparent and p_status == "nomerge":
-                               portage.dep._dep_check_strict = False
-                       mycheck = portage.dep_check(depstring, None,
-                               pkgsettings, myuse=myuse,
-                               use_binaries=("--usepkgonly" in self.myopts),
-                               myroot=myroot, trees=self.trees)
-               finally:
-                       portage.dep._dep_check_strict = True
-
-               if not mycheck[0]:
-                       if myparent:
-                               show_invalid_depstring_notice(myparent, depstring, mycheck[1])
-                       else:
-                               sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
-                       return 0
-               mymerge = mycheck[1]
-
-               if not mymerge and arg and \
-                       portage.best_match_to_list(depstring, self.args_keys):
-                       # A provided package has been specified on the command line.  The
-                       # package will not be merged and a warning will be displayed.
-                       self._pprovided_args.append(arg)
-
-               if myparent:
-                       # The parent is added after it's own dep_check call so that it
-                       # isn't allowed to satisfy a direct bootstrap dependency on itself
-                       # via an old-style virtual.  This isn't a problem with new-style
-                       # virtuals, which are preferenced in dep_zapdeps by looking only at
-                       # the depstring, vdb, and available packages.
-
-                       p_type, p_root, p_key, p_status = myparent
-                       if p_status == "merge":
-                               # Update old-style virtuals if this package provides any.
-                               # These are needed for dep_virtual calls inside dep_check.
-                               self.pkgsettings[p_root].setinst(p_key,
-                                       self.trees[p_root][self.pkg_tree_map[p_type]].dbapi)
-
-               if "--debug" in self.myopts:
-                       print "Candidates:",mymerge
-               for x in mymerge:
-                       selected_pkg = None
-                       if x[0]=="!":
-                               selected_pkg = ["blocks", myroot, x[1:], None]
-                       else:
-                               #We are not processing a blocker but a normal dependency
-                               if myparent:
-                                       """In some cases, dep_check will return deps that shouldn't
-                                       be proccessed any further, so they are identified and
-                                       discarded here."""
-                                       if "empty" not in self.myparams and \
-                                               "deep" not in self.myparams and \
-                                               not ("--update" in self.myopts and parent_arg) and \
-                                               vardb.match(x):
-                                               continue
-
-                               # List of acceptable packages, ordered by type preference.
-                               matched_packages = []
-                               myeb_matches = portdb.xmatch("match-visible", x)
-                               myeb = None
-                               if "--usepkgonly" not in self.myopts:
-                                       myeb = portage.best(myeb_matches)
-
-                               myeb_pkg=None
-                               if "--usepkg" in self.myopts:
-                                       # The next line assumes the binarytree has been populated.
-                                       # XXX: Need to work out how we use the binary tree with roots.
-                                       myeb_pkg_matches = bindb.match(x)
-                                       if "--usepkgonly" not in self.myopts:
-                                               # Remove any binary package entries that are masked in the portage tree (#55871)
-                                               myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
-                                                       if pkg in myeb_matches or  \
-                                                       not portdb.cpv_exists(pkg)]
-                                       if myeb_pkg_matches:
-                                               myeb_pkg = portage.best(myeb_pkg_matches)
-
-                               if myeb_pkg and "--newuse" in self.myopts:
-                                       iuses = set(filter_iuse_defaults(
-                                               bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
-                                       old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
-                                       mydb = None
-                                       if "--usepkgonly" not in self.myopts and myeb:
-                                               mydb = portdb
-                                       if myeb:
-                                               pkgsettings.setcpv(myeb, mydb=mydb)
-                                       else:
-                                               pkgsettings.setcpv(myeb_pkg, mydb=mydb)
-                                       now_use = pkgsettings["USE"].split()
-                                       forced_flags = set()
-                                       forced_flags.update(pkgsettings.useforce)
-                                       forced_flags.update(pkgsettings.usemask)
-                                       cur_iuse = iuses
-                                       if "--usepkgonly" not in self.myopts and myeb:
-                                               cur_iuse = set(filter_iuse_defaults(
-                                                       portdb.aux_get(myeb, ["IUSE"])[0].split()))
-                                       if iuses.symmetric_difference(
-                                               cur_iuse).difference(forced_flags):
-                                               myeb_pkg = None
-                                       elif iuses.intersection(old_use) != \
-                                               cur_iuse.intersection(now_use):
-                                               myeb_pkg = None
-                               if myeb_pkg:
-                                       binpkguseflags = \
-                                               self.trees[myroot]["bintree"].dbapi.aux_get(
-                                                       myeb_pkg, ["USE"])[0].split()
-                                       matched_packages.append(
-                                               ["binary", myroot, myeb_pkg, binpkguseflags])
-
-                               if "--usepkgonly" not in self.myopts and myeb_matches:
-                                       matched_packages.append(
-                                               ["ebuild", myroot, myeb, None])
-
-                               if not matched_packages and \
-                                       not (arg and "selective" not in self.myparams):
-                                       """Fall back to the installed package database.  This is a
-                                       last resort because the metadata tends to diverge from that
-                                       of the ebuild in the tree."""
-                                       myeb_inst_matches = vardb.match(x)
-                                       if "--usepkgonly" not in self.myopts:
-                                               """ TODO: Improve masking check for installed and
-                                               binary packages. bug #149816"""
-                                               myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
-                                                       if not portdb.cpv_exists(pkg)]
-                                       myeb_inst = None
-                                       if myeb_inst_matches:
-                                               myeb_inst = portage.best(myeb_inst_matches)
-                                       if myeb_inst:
-                                               binpkguseflags = vardb.aux_get(
-                                                       myeb_inst, ["USE"])[0].split()
-                                               matched_packages.append(
-                                                       ["installed", myroot, myeb_inst, binpkguseflags])
-
-                               if not matched_packages:
-                                       if raise_on_missing:
-                                               raise ValueError
-                                       if not arg:
-                                               xinfo='"'+x+'"'
-                                       else:
-                                               xinfo='"'+arg+'"'
-                                       if myparent:
-                                               xfrom = '(dependency required by '+ \
-                                                       green('"%s"' % myparent[2]) + \
-                                                       red(' [%s]' % myparent[0]) + ')'
-                                       alleb = portdb.xmatch("match-all", x)
-                                       if alleb:
-                                               if "--usepkgonly" not in self.myopts:
-                                                       print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
-                                                       print "!!! One of the following masked packages is required to complete your request:"
-                                                       oldcomment = ""
-                                                       for p in alleb:
-                                                               mreasons = portage.getmaskingstatus(p,
-                                                                       settings=pkgsettings, portdb=portdb)
-                                                               print "- "+p+" (masked by: "+", ".join(mreasons)+")"
-                                                               comment, filename = portage.getmaskingreason(p,
-                                                                       settings=pkgsettings, portdb=portdb, return_location=True)
-                                                               if comment and comment != oldcomment:
-                                                                       print filename+":"
-                                                                       print comment
-                                                                       oldcomment = comment
-                                                       print
-                                                       print "For more information, see MASKED PACKAGES section in the emerge man page or "
-                                                       print "refer to the Gentoo Handbook."
-                                               else:
-                                                       print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
-                                                       print "!!! Either add a suitable binary package or compile from an ebuild."
-                                       else:
-                                               print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
-                                       if myparent:
-                                               print xfrom
-                                       print
-                                       return 0
-
-                               if "--debug" in self.myopts:
-                                       for pkg in matched_packages:
-                                               print (pkg[0] + ":").rjust(10), pkg[2]
-
-                               if len(matched_packages) > 1:
-                                       bestmatch = portage.best(
-                                               [pkg[2] for pkg in matched_packages])
-                                       matched_packages = [pkg for pkg in matched_packages \
-                                               if pkg[2] == bestmatch]
-
-                               # ordered by type preference ("ebuild" type is the last resort)
-                               selected_pkg =  matched_packages[0]
-                               pkgtype, myroot, mycpv, myuse = selected_pkg
-                               mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
-                               slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
-                                       mydbapi.aux_get(mycpv, ["SLOT"])[0])
-                               existing_node = self._slot_node_map[myroot].get(
-                                       slot_atom, None)
-                               if existing_node:
-                                       e_type, myroot, e_cpv, e_status = existing_node
-                                       if portage.match_from_list(x, [e_cpv]):
-                                               # The existing node can be reused.
-                                               selected_pkg = [e_type, myroot, e_cpv,
-                                                       self.useFlags[myroot][e_cpv]]
-
-                       if myparent:
-                               #we are a dependency, so we want to be unconditionally added
-                               mypriority = priority.copy()
-                               if vardb.match(x):
-                                       mypriority.satisfied = True
-                               if not self.create(selected_pkg[0:3], myparent,
-                                       myuse=selected_pkg[-1], priority=mypriority,
-                                       rev_dep=rev_deps, arg=arg):
-                                       return 0
-                       else:
-                               #if mysource is not set, then we are a command-line dependency and should not be added
-                               #if --onlydeps is specified.
-                               if not self.create(selected_pkg[0:3], myparent,
-                                       addme=("--onlydeps" not in self.myopts),
-                                       myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
-                                       return 0
-
-               if "--debug" in self.myopts:
-                       print "Exiting...",myparent
-               return 1
-
-       def validate_blockers(self):
-               """Remove any blockers from the digraph that do not match any of the
-               packages within the graph.  If necessary, create hard deps to ensure
-               correct merge order such that mutually blocking packages are never
-               installed simultaneously."""
-
-               if "--buildpkgonly" in self.myopts or \
-                       "--nodeps" in self.myopts:
-                       return True
-
-               modified_slots = {}
-               for myroot in self.trees:
-                       myslots = {}
-                       modified_slots[myroot] = myslots
-                       final_db = self.mydbapi[myroot]
-                       slot_node_map = self._slot_node_map[myroot]
-                       for slot_atom, mynode in slot_node_map.iteritems():
-                               mytype, myroot, mycpv, mystatus = mynode
-                               if mystatus == "merge":
-                                       myslots[slot_atom] = mycpv
-
-               #if "deep" in self.myparams:
-               if True:
-                       # Pull in blockers from all installed packages that haven't already
-                       # been pulled into the depgraph.  This is not enabled by default
-                       # due to the performance penalty that is incurred by all the
-                       # additional dep_check calls that are required.
-
-                       # Optimization hack for dep_check calls that minimizes the
-                       # available matches by replacing the portdb with a fakedbapi
-                       # instance.
-                       class FakePortageTree(object):
-                               def __init__(self, mydb):
-                                       self.dbapi = mydb
-                       dep_check_trees = {}
-                       for myroot in self.trees:
-                               dep_check_trees[myroot] = self.trees[myroot].copy()
-                               dep_check_trees[myroot]["porttree"] = \
-                                       FakePortageTree(self.mydbapi[myroot])
-
-                       dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
-                       for myroot in self.trees:
-                               pkg_node_map = self.pkg_node_map[myroot]
-                               vardb = self.trees[myroot]["vartree"].dbapi
-                               portdb = self.trees[myroot]["porttree"].dbapi
-                               pkgsettings = self.pkgsettings[myroot]
-                               final_db = self.mydbapi[myroot]
-                               cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
-                               blocker_cache = BlockerCache(myroot, vardb)
-                               for pkg in cpv_all_installed:
-                                       blocker_atoms = None
-                                       matching_node = pkg_node_map.get(pkg, None)
-                                       if matching_node and \
-                                               matching_node[3] == "nomerge":
-                                               continue
-                                       # If this node has any blockers, create a "nomerge"
-                                       # node for it so that they can be enforced.
-                                       self.spinner.update()
-                                       blocker_data = blocker_cache.get(pkg)
-                                       if blocker_data:
-                                               blocker_atoms = blocker_data.atoms
-                                       else:
-                                               dep_vals = vardb.aux_get(pkg, dep_keys)
-                                               myuse = vardb.aux_get(pkg, ["USE"])[0].split()
-                                               depstr = " ".join(dep_vals)
-                                               # It is crucial to pass in final_db here in order to
-                                               # optimize dep_check calls by eliminating atoms via
-                                               # dep_wordreduce and dep_eval calls.
-                                               try:
-                                                       portage.dep._dep_check_strict = False
-                                                       try:
-                                                               success, atoms = portage.dep_check(depstr,
-                                                                       final_db, pkgsettings, myuse=myuse,
-                                                                       trees=dep_check_trees, myroot=myroot)
-                                                       except Exception, e:
-                                                               if isinstance(e, SystemExit):
-                                                                       raise
-                                                               # This is helpful, for example, if a ValueError
-                                                               # is thrown from cpv_expand due to multiple
-                                                               # matches (this can happen if an atom lacks a
-                                                               # category).
-                                                               show_invalid_depstring_notice(
-                                                                       ("installed", myroot, pkg, "nomerge"),
-                                                                       depstr, str(e))
-                                                               del e
-                                                               raise
-                                               finally:
-                                                       portage.dep._dep_check_strict = True
-                                               if not success:
-                                                       slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
-                                                               vardb.aux_get(pkg, ["SLOT"])[0])
-                                                       if slot_atom in modified_slots[myroot]:
-                                                               # This package is being replaced anyway, so
-                                                               # ignore invalid dependencies so as not to
-                                                               # annoy the user too much (otherwise they'd be
-                                                               # forced to manually unmerge it first).
-                                                               continue
-                                                       show_invalid_depstring_notice(
-                                                               ("installed", myroot, pkg, "nomerge"),
-                                                               depstr, atoms)
-                                                       return False
-                                               blocker_atoms = [myatom for myatom in atoms \
-                                                       if myatom.startswith("!")]
-                                               counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
-                                               blocker_cache[pkg] = \
-                                                       blocker_cache.BlockerData(counter, blocker_atoms)
-                                       if blocker_atoms:
-                                               # Don't store this parent in pkg_node_map, because it's
-                                               # not needed there and it might overwrite a "merge"
-                                               # node with the same cpv.
-                                               myparent = ("installed", myroot, pkg, "nomerge")
-                                               for myatom in blocker_atoms:
-                                                       blocker = ("blocks", myroot, myatom[1:])
-                                                       myparents = \
-                                                               self.blocker_parents.get(blocker, None)
-                                                       if not myparents:
-                                                               myparents = set()
-                                                               self.blocker_parents[blocker] = myparents
-                                                       myparents.add(myparent)
-                               blocker_cache.flush()
-                               del blocker_cache
-
-               for blocker in self.blocker_parents.keys():
-                       mytype, myroot, mydep = blocker
-                       initial_db = self.trees[myroot]["vartree"].dbapi
-                       final_db = self.mydbapi[myroot]
-                       blocked_initial = initial_db.match(mydep)
-                       blocked_final = final_db.match(mydep)
-                       if not blocked_initial and not blocked_final:
-                               del self.blocker_parents[blocker]
-                               continue
-                       blocked_slots_initial = {}
-                       blocked_slots_final = {}
-                       for cpv in blocked_initial:
-                               blocked_slots_initial[cpv] = \
-                                       "%s:%s" % (portage.dep_getkey(cpv),
-                                               initial_db.aux_get(cpv, ["SLOT"])[0])
-                       for cpv in blocked_final:
-                               blocked_slots_final[cpv] = \
-                                       "%s:%s" % (portage.dep_getkey(cpv),
-                                               final_db.aux_get(cpv, ["SLOT"])[0])
-                       blocked_slots_final_values = set(blocked_slots_final.itervalues())
-                       for parent in list(self.blocker_parents[blocker]):
-                               ptype, proot, pcpv, pstatus = parent
-                               pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
-                               pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
-                               pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
-                               parent_static = pslot_atom not in modified_slots[proot]
-                               unresolved_blocks = False
-                               depends_on_order = set()
-                               for cpv in blocked_initial:
-                                       slot_atom = blocked_slots_initial[cpv]
-                                       if slot_atom == pslot_atom:
-                                               # The parent blocks an initial package in the same
-                                               # slot as itself.  The merge/nomerge status of neither
-                                               # node matters.  In any case, this particular block is
-                                               # automatically resolved.
-                                               continue
-                                       if parent_static and \
-                                               slot_atom not in modified_slots[myroot]:
-                                               # This blocker will be handled the next time that a
-                                               # merge of either package is triggered.
-                                               continue
-                                       if pstatus == "merge" and \
-                                               slot_atom not in blocked_slots_final_values:
-                                               upgrade_matches = final_db.match(slot_atom)
-                                               if upgrade_matches:
-                                                       # Apparently an upgrade may be able to invalidate
-                                                       # this block.
-                                                       upgrade_node = \
-                                                               self.pkg_node_map[proot][upgrade_matches[0]]
-                                                       depends_on_order.add(upgrade_node)
-                                                       continue
-                                       # None of the above blocker resolutions techniques apply,
-                                       # so apparently this one is unresolvable.
-                                       unresolved_blocks = True
-                               for cpv in blocked_final:
-                                       slot_atom = blocked_slots_final[cpv]
-                                       if slot_atom == pslot_atom:
-                                               # The parent blocks itself, so the merge order does not
-                                               # need to be enforced.
-                                               continue
-                                       if parent_static and \
-                                               slot_atom not in modified_slots[myroot]:
-                                               # This blocker will be handled the next time that a
-                                               # merge of either package is triggered.
-                                               continue
-                                       # None of the above blocker resolutions techniques apply,
-                                       # so apparently this one is unresolvable.
-                                       unresolved_blocks = True
-                               if not unresolved_blocks and depends_on_order:
-                                       for node in depends_on_order:
-                                               # Enforce correct merge order with a hard dep.
-                                               self.digraph.addnode(node, parent,
-                                                       priority=DepPriority(buildtime=True))
-                                               # Count references to this blocker so that it can be
-                                               # invalidated after nodes referencing it have been
-                                               # merged.
-                                               self.blocker_digraph.addnode(node, blocker)
-                               if not unresolved_blocks and not depends_on_order:
-                                       self.blocker_parents[blocker].remove(parent)
-                       if not self.blocker_parents[blocker]:
-                               del self.blocker_parents[blocker]
-               # Validate blockers that depend on merge order.
-               if not self.blocker_digraph.empty():
-                       self.altlist()
-               if self._slot_collision_info:
-                       # The user is only notified of a slot collision if there are no
-                       # unresolvable blocks.
-                       for x in self.altlist():
-                               if x[0] == "blocks":
-                                       return True
-                       self._show_slot_collision_notice(self._slot_collision_info[0])
-                       if not self._accept_collisions():
-                               return False
-               return True
-
-       def _accept_collisions(self):
-               acceptable = False
-               for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
-                       if x in self.myopts:
-                               acceptable = True
-                               break
-               return acceptable
-
-       def altlist(self, reversed=False):
-               if reversed in self._altlist_cache:
-                       return self._altlist_cache[reversed][:]
-               if reversed:
-                       retlist = self.altlist()
-                       retlist.reverse()
-                       self._altlist_cache[reversed] = retlist[:]
-                       return retlist
-               mygraph=self.digraph.copy()
-               myblockers = self.blocker_digraph.copy()
-               retlist=[]
-               circular_blocks = False
-               blocker_deps = None
-               asap_nodes = []
-               if reversed:
-                       get_nodes = mygraph.root_nodes
-               else:
-                       get_nodes = mygraph.leaf_nodes
-                       for cpv, node in self.pkg_node_map["/"].iteritems():
-                               if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
-                                       asap_nodes.append(node)
-                                       break
-               ignore_priority_range = [None]
-               ignore_priority_range.extend(
-                       xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
-               tree_mode = "--tree" in self.myopts
-               while not mygraph.empty():
-                       ignore_priority = None
-                       nodes = None
-                       if asap_nodes:
-                               """ASAP nodes are merged before their soft deps."""
-                               for node in asap_nodes:
-                                       if not mygraph.contains(node):
-                                               asap_nodes.remove(node)
-                                               continue
-                                       if not mygraph.child_nodes(node,
-                                               ignore_priority=DepPriority.SOFT):
-                                               nodes = [node]
-                                               asap_nodes.remove(node)
-                                               break
-                       if not nodes:
-                               for ignore_priority in ignore_priority_range:
-                                       nodes = get_nodes(ignore_priority=ignore_priority)
-                                       if nodes:
-                                               break
-                       selected_nodes = None
-                       if nodes:
-                               if ignore_priority <= DepPriority.SOFT:
-                                       if ignore_priority is None and not tree_mode:
-                                               # Greedily pop all of these nodes since no relationship
-                                               # has been ignored.  This optimization destroys --tree
-                                               # output, so it's disabled in reversed mode.
-                                               selected_nodes = nodes
-                                       else:
-                                               # Only pop one node for optimal merge order.
-                                               selected_nodes = [nodes[0]]
-                               else:
-                                       """Recursively gather a group of nodes that RDEPEND on
-                                       eachother.  This ensures that they are merged as a group
-                                       and get their RDEPENDs satisfied as soon as possible."""
-                                       def gather_deps(mergeable_nodes, selected_nodes, node):
-                                               if node in selected_nodes:
-                                                       return True
-                                               if node not in mergeable_nodes:
-                                                       return False
-                                               selected_nodes.add(node)
-                                               for child in mygraph.child_nodes(node,
-                                                       ignore_priority=DepPriority.SOFT):
-                                                       if not gather_deps(
-                                                               mergeable_nodes, selected_nodes, child):
-                                                               return False
-                                               return True
-                                       mergeable_nodes = set(nodes)
-                                       for node in nodes:
-                                               selected_nodes = set()
-                                               if gather_deps(
-                                                       mergeable_nodes, selected_nodes, node):
-                                                       break
-                                               else:
-                                                       selected_nodes = None
-
-                       if not selected_nodes:
-                               if not myblockers.is_empty():
-                                       """A blocker couldn't be circumnavigated while keeping all
-                                       dependencies satisfied.  The user will have to resolve this
-                                       manually.  This is a panic condition and thus the order
-                                       doesn't really matter, so just pop a random node in order
-                                       to avoid a circular dependency panic if possible."""
-                                       if not circular_blocks:
-                                               circular_blocks = True
-                                               blocker_deps = myblockers.leaf_nodes()
-                                       if blocker_deps:
-                                               selected_nodes = [blocker_deps.pop()]
-
-                       if not selected_nodes:
-                               if reversed:
-                                       """The circular deps ouput should have less noise when
-                                       altlist is not in reversed mode."""
-                                       self.altlist()
-                               print "!!! Error: circular dependencies:"
-                               print
-                               # Reduce the noise level to a minimum via elimination of root
-                               # nodes.
-                               while True:
-                                       root_nodes = mygraph.root_nodes(
-                                               ignore_priority=DepPriority.SOFT)
-                                       if not root_nodes:
-                                               break
-                                       for node in root_nodes:
-                                               mygraph.remove(node)
-                               mygraph.debug_print()
-                               sys.exit(1)
-
-                       for node in selected_nodes:
-                               retlist.append(list(node))
-                               mygraph.remove(node)
-                               if not reversed and not circular_blocks and myblockers.contains(node):
-                                       """This node may have invalidated one or more blockers."""
-                                       myblockers.remove(node)
-                                       for blocker in myblockers.root_nodes():
-                                               if not myblockers.child_nodes(blocker):
-                                                       myblockers.remove(blocker)
-                                                       del self.blocker_parents[blocker]
-
-               if not reversed:
-                       """Blocker validation does not work with reverse mode,
-                       so self.altlist() should first be called with reverse disabled
-                       so that blockers are properly validated."""
-                       self.blocker_digraph = myblockers
-
-               """ Add any unresolved blocks so that they can be displayed."""
-               for blocker in self.blocker_parents:
-                       retlist.append(list(blocker))
-               self._altlist_cache[reversed] = retlist[:]
-               return retlist
-
-       def xcreate(self,mode="system"):
-               vardb = self.trees[self.target_root]["vartree"].dbapi
-               portdb = self.trees[self.target_root]["porttree"].dbapi
-               bindb = self.trees[self.target_root]["bintree"].dbapi
-               def visible(mylist):
-                       matches = portdb.gvisible(portdb.visible(mylist))
-                       return [x for x in mylist \
-                               if x in matches or not portdb.cpv_exists(x)]
-               world_problems = False
-               if mode=="system":
-                       mylist = getlist(self.settings, "system")
-               else:
-                       #world mode
-                       worldlist = getlist(self.settings, "world")
-                       sysdict = genericdict(getlist(self.settings, "system"))
-                       worlddict=genericdict(worldlist)
-
-                       for x in worlddict.keys():
-                               if not portage.isvalidatom(x):
-                                       world_problems = True
-                               elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
-                                       world_problems = True
-                               else:
-                                       sysdict[x]=worlddict[x]
-
-                       mylist = sysdict.keys()
-
-               newlist = []
-               for atom in mylist:
-                       mykey = portage.dep_getkey(atom)
-                       if True:
-                               newlist.append(atom)
-                               """Make sure all installed slots are updated when possible.
-                               Do this with --emptytree also, to ensure that all slots are
-                               remerged."""
-                               myslots = set()
-                               for cpv in vardb.match(mykey):
-                                       myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
-                               if myslots:
-                                       best_pkgs = []
-                                       if "--usepkg" in self.myopts:
-                                               mymatches = bindb.match(atom)
-                                               if "--usepkgonly" not in self.myopts:
-                                                       mymatches = visible(mymatches)
-                                               best_pkg = portage.best(mymatches)
-                                               if best_pkg:
-                                                       best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
-                                                       best_pkgs.append(("binary", best_pkg, best_slot))
-                                       if "--usepkgonly" not in self.myopts:
-                                               best_pkg = portage.best(portdb.match(atom))
-                                               if best_pkg:
-                                                       best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
-                                                       best_pkgs.append(("ebuild", best_pkg, best_slot))
-                                       if best_pkgs:
-                                               best_pkg = portage.best([x[1] for x in best_pkgs])
-                                               best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
-                                               best_slot = best_pkgs[0][2]
-                                               myslots.add(best_slot)
-                               if len(myslots) > 1:
-                                       for myslot in myslots:
-                                               myslot_atom = "%s:%s" % (mykey, myslot)
-                                               available = False
-                                               if "--usepkgonly" not in self.myopts and \
-                                                       self.trees[self.target_root][
-                                                       "porttree"].dbapi.match(myslot_atom):
-                                                       available = True
-                                               elif "--usepkg" in self.myopts:
-                                                       mymatches = bindb.match(myslot_atom)
-                                                       if "--usepkgonly" not in self.myopts:
-                                                               mymatches = visible(mymatches)
-                                                       if mymatches:
-                                                               available = True
-                                               if available:
-                                                       newlist.append(myslot_atom)
-               mylist = newlist
-               
-               missing_atoms = []
-               for mydep in mylist:
-                       try:
-                               if not self.select_dep(
-                                       self.target_root, mydep, raise_on_missing=True, arg=mydep):
-                                       print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
-                                       return 0
-                       except ValueError:
-                               missing_atoms.append(mydep)
-
-               if not self.validate_blockers():
-                       return False
-
-               if world_problems:
-                       print >> sys.stderr, "\n!!! Problems have been detected with your world file"
-                       print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
-
-               if missing_atoms:
-                       print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
-                               " Ebuilds for the following packages are either all"
-                       print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
-                       print >> sys.stderr, " ".join(missing_atoms) + "\n"
-
-               return 1
-
-       def display(self,mylist,verbosity=None):
-               if verbosity is None:
-                       verbosity = ("--quiet" in self.myopts and 1 or \
-                               "--verbose" in self.myopts and 3 or 2)
-               changelogs=[]
-               p=[]
-
-               counters = PackageCounters()
-
-               if verbosity == 1 and "--verbose" not in self.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, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
-                               alphabetical=("--alphabetical" in self.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
-                                       if flag in enabled_flags:
-                                               isEnabled = True
-                                               if is_new or flag in old_use and all_flags:
-                                                       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:
-                                                       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:
-                                                       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
-
-               if verbosity == 3:
-                       # FIXME: account for the possibility of different overlays in
-                       # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
-                       overlays = self.settings["PORTDIR_OVERLAY"].split()
-                       overlays_real = [os.path.realpath(t) \
-                               for t in self.settings["PORTDIR_OVERLAY"].split()]
-
-               tree_nodes = []
-               node_depth = {}
-               i = 0
-               depth = 0
-               for x in mylist:
-                       if "blocks" == x[0]:
-                               continue
-                       graph_key = tuple(x)
-                       if "--tree" in self.myopts:
-                               depth = len(tree_nodes)
-                               while depth and graph_key not in \
-                                       self.digraph.child_nodes(tree_nodes[depth-1]):
-                                               depth -= 1
-                               tree_nodes = tree_nodes[:depth]
-                               tree_nodes.append(graph_key)
-                       node_depth[graph_key] = depth
-
-               last_merge_depth = 0
-               for i in xrange(len(mylist)-1,-1,-1):
-                       if "blocks" == mylist[i][0]:
-                               continue
-                       graph_key = tuple(mylist[i])
-                       if mylist[i][-1] != "nomerge":
-                               last_merge_depth = node_depth[graph_key]
-                               continue
-                       if node_depth[graph_key] >= last_merge_depth or \
-                               i < len(mylist) - 1 and \
-                               node_depth[graph_key] >= node_depth[tuple(mylist[i+1])]:
-                                       del mylist[i]
-                                       del node_depth[graph_key]
-               del tree_nodes
-
-               display_overlays=False
-               # files to fetch list - avoids counting a same file twice
-               # in size display (verbose mode)
-               myfetchlist=[]
-               for x in mylist:
-                       pkg_type = x[0]
-                       myroot = x[1]
-                       pkg_key = x[2]
-                       portdb = self.trees[myroot]["porttree"].dbapi
-                       bindb  = self.trees[myroot]["bintree"].dbapi
-                       vardb = self.trees[myroot]["vartree"].dbapi
-                       vartree = self.trees[myroot]["vartree"]
-                       pkgsettings = self.pkgsettings[myroot]
-
-                       fetch=" "
-
-                       if x[0]=="blocks":
-                               addl=""+red("B")+"  "+fetch+"  "
-                               counters.blocks += 1
-                               resolved = portage.key_expand(
-                                       pkg_key, mydb=vardb, settings=pkgsettings)
-                               if "--columns" in self.myopts and "--quiet" in self.myopts:
-                                       print addl,red(resolved),
-                               else:
-                                       print "["+x[0]+" "+addl+"]",red(resolved),
-                               block_parents = self.blocker_parents[tuple(x)]
-                               block_parents = set([pnode[2] for pnode in block_parents])
-                               block_parents = ", ".join(block_parents)
-                               if resolved!=x[2]:
-                                       print bad("(\"%s\" is blocking %s)") % \
-                                               (pkg_key, block_parents)
-                               else:
-                                       print bad("(is blocking %s)") % block_parents
-                       else:
-                               mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
-                               binary_package = True
-                               if "ebuild" == pkg_type:
-                                       if "merge" == x[3] or \
-                                               not vartree.dbapi.cpv_exists(pkg_key):
-                                               """An ebuild "merge" node or a --onlydeps "nomerge"
-                                               node."""
-                                               binary_package = False
-                                               pkgsettings.setcpv(pkg_key, mydb=portdb)
-                                               if pkg_key not in self.useFlags[myroot]:
-                                                       self.useFlags[myroot][pkg_key] = \
-                                                               pkgsettings["USE"].split()
-                                       else:
-                                               # An ebuild "nomerge" node, so USE come from the vardb.
-                                               mydbapi = vartree.dbapi
-                               if pkg_key not in self.useFlags[myroot]:
-                                       """If this is a --resume then the USE flags need to be
-                                       fetched from the appropriate locations here."""
-                                       self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
-                                               pkg_key, ["USE"])[0].split()
-
-                               if "ebuild" == pkg_type and x[3] != "nomerge" and \
-                                       "fetch" in portdb.aux_get(
-                                       x[2], ["RESTRICT"])[0].split():
-                                       fetch = red("F")
-                                       counters.restrict_fetch += 1
-                                       if portdb.fetch_check(
-                                               pkg_key, self.useFlags[myroot][pkg_key]):
-                                               fetch = green("f")
-                                               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=""
-                               if vardb.cpv_exists(pkg_key):
-                                       addl="  "+yellow("R")+fetch+"  "
-                                       if x[3] != "nomerge":
-                                               counters.reinst += 1
-                               elif vardb.match(portage.dep_getkey(pkg_key)):
-                                       mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
-                                       myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
-                                               portage.pkgsplit(x[2])[0])
-                                       myinslotlist = [inst_pkg for inst_pkg in myoldlist
-                                               if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
-                                       if myinslotlist:
-                                               myoldbest=portage.best(myinslotlist)
-                                               addl="   "+fetch
-                                               if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
-                                                       # Downgrade in slot
-                                                       addl+=turquoise("U")+blue("D")
-                                                       counters.downgrades += 1
-                                               else:
-                                                       # Update in slot
-                                                       addl+=turquoise("U")+" "
-                                                       counters.upgrades += 1
-                                       else:
-                                               # New slot, mark it new.
-                                               addl=" "+green("NS")+fetch+"  "
-                                               counters.newslot += 1
-
-                                       if "--changelog" in self.myopts:
-                                               slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
-                                                       mydbapi.aux_get(pkg_key, ["SLOT"])[0])
-                                               inst_matches = vardb.match(slot_atom)
-                                               if inst_matches:
-                                                       changelogs.extend(self.calc_changelog(
-                                                               portdb.findname(pkg_key),
-                                                               inst_matches[0], pkg_key))
-                               else:
-                                       addl=" "+green("N")+" "+fetch+"  "
-                                       counters.new += 1
-
-                               verboseadd=""
-                               
-                               if pkg_key in self.useFlags[myroot]:
-                                       # USE flag display
-                                       cur_iuse = list(filter_iuse_defaults(
-                                               mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
-
-                                       forced_flags = set()
-                                       if not binary_package:
-                                               forced_flags.update(pkgsettings.useforce)
-                                               forced_flags.update(pkgsettings.usemask)
-
-                                       cur_iuse = portage.unique_array(cur_iuse)
-                                       cur_iuse.sort()
-                                       cur_use = self.useFlags[myroot][pkg_key]
-                                       cur_use = [flag for flag in cur_use if flag in cur_iuse]
-
-                                       if myoldbest:
-                                               pkg = myoldbest
-                                       else:
-                                               pkg = x[2]
-                                       if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
-                                               old_iuse, old_use = \
-                                                       self.trees[x[1]]["vartree"].dbapi.aux_get(
-                                                               pkg, ["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):
-                                               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]
-                                               for exp in use_expand_hidden:
-                                                       if exp in ret:
-                                                               del ret[exp]
-                                               if forcedFlags:
-                                                       return ret, forced
-                                               return ret
-
-                                       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)
-
-                               if verbosity == 3:
-                                       # size verbose
-                                       mysize=0
-                                       if x[0] == "ebuild" and x[-1]!="nomerge":
-                                               try:
-                                                       myfilesdict = portdb.getfetchsizes(pkg_key,
-                                                               useflags=self.useFlags[myroot][pkg_key],
-                                                               debug=self.edebug)
-                                               except portage.exception.InvalidDependString, e:
-                                                       src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
-                                                       show_invalid_depstring_notice(x, src_uri, str(e))
-                                                       del e
-                                                       sys.exit(1)
-                                               if myfilesdict is None:
-                                                       myfilesdict="[empty/missing/bad digest]"
-                                               else:
-                                                       for myfetchfile in myfilesdict.keys():
-                                                               if myfetchfile not in myfetchlist:
-                                                                       mysize+=myfilesdict[myfetchfile]
-                                                                       myfetchlist.append(myfetchfile)
-                                                       counters.totalsize += mysize
-                                               verboseadd+=format_size(mysize)+" "
-
-                                       # overlay verbose
-                                       # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
-                                       # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
-                                       file_name = portdb.findname(pkg_key)
-                                       if file_name: # It might not exist in the tree
-                                               dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
-                                               if (overlays_real.count(dir_name)>0):
-                                                       verboseadd+=teal("["+str(overlays_real.index(
-                                                               os.path.normpath(dir_name))+1)+"]")+" "
-                                                       display_overlays=True
-                                       else:
-                                               verboseadd += "[No ebuild?]"
-
-                               xs=portage.pkgsplit(x[2])
-                               if xs[2]=="r0":
-                                       xs[2]=""
-                               else:
-                                       xs[2]="-"+xs[2]
-
-                               mywidth = 130
-                               if "COLUMNWIDTH" in self.settings:
-                                       try:
-                                               mywidth = int(self.settings["COLUMNWIDTH"])
-                                       except ValueError, e:
-                                               portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
-                                               portage.writemsg(
-                                                       "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
-                                                       self.settings["COLUMNWIDTH"], noiselevel=-1)
-                                               del e
-                               oldlp=mywidth-30
-                               newlp=oldlp-30
-
-                               indent = " " * node_depth[tuple(x)]
-
-                               if myoldbest:
-                                       myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
-                                       if myoldbest[-3:]=="-r0":
-                                               myoldbest=myoldbest[:-3]
-                                       myoldbest=blue("["+myoldbest+"]")
-
-                               if x[1]!="/":
-                                       if myoldbest:
-                                               myoldbest +=" "
-                                       if "--columns" in self.myopts:
-                                               if "--quiet" in self.myopts:
-                                                       myprint=addl+" "+indent+darkgreen(xs[0])
-                                                       myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
-                                                       myprint=myprint+myoldbest
-                                                       myprint=myprint+darkgreen("to "+x[1])
-                                               else:
-                                                       myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
-                                                       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=myprint+darkgreen("to "+x[1])+" "+verboseadd
-                                       else:
-                                               if x[3] == "nomerge":
-                                                       myprint = darkblue("[nomerge      ] ")
-                                               else:
-                                                       myprint = "[" + pkg_type + " " + addl + "] "
-                                               myprint += indent + darkgreen(pkg_key) + " " + \
-                                                       myoldbest + darkgreen("to " + myroot) + " " + \
-                                                       verboseadd
-                               else:
-                                       if "--columns" in self.myopts:
-                                               if "--quiet" in self.myopts:
-                                                       myprint=addl+" "+indent+darkgreen(xs[0])
-                                                       myprint=myprint+" "+green(xs[1]+xs[2])+" "
-                                                       myprint=myprint+myoldbest
-                                               else:
-                                                       myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
-                                                       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=myprint+myoldbest+"  "+verboseadd
-                                       else:
-                                               if x[3]=="nomerge":
-                                                       myprint=darkblue("[nomerge      ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
-                                               else:
-                                                       myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
-                               p.append(myprint)
-
-                       mysplit = portage.pkgsplit(x[2])
-                       if "--tree" not in self.myopts and mysplit and \
-                               len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
-                               x[1] == "/":
-
-                               if mysplit[2] == "r0":
-                                       myversion = mysplit[1]
-                               else:
-                                       myversion = "%s-%s" % (mysplit[1], mysplit[2])
-
-                               if myversion != portage.VERSION and "--quiet" not in self.myopts:
-                                       if mylist.index(x) < len(mylist) - 1 and \
-                                               "livecvsportage" not in self.settings.features:
-                                               p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
-                                               p.append(colorize("WARN", "    then resume the merge."))
-                                               print
-                       del mysplit
-
-               for x in p:
-                       print x
-
-               if verbosity == 3:
-                       print
-                       print counters
-                       if overlays and display_overlays:
-                               print "Portage overlays:"
-                               y=0
-                               for x in overlays:
-                                       y=y+1
-                                       print " "+teal("["+str(y)+"]"),x
-
-               if "--changelog" in self.myopts:
-                       print
-                       for revision,text in changelogs:
-                               print bold('*'+revision)
-                               sys.stdout.write(text)
-
-               if self._pprovided_args:
-                       msg = []
-                       msg.append(bad("\nWARNING: "))
-                       if len(self._pprovided_args) > 1:
-                               msg.append("Requested packages will not be " + \
-                                       "merged because they are listed in\n")
-                       else:
-                               msg.append("A requested package will not be " + \
-                                       "merged because it is listed in\n")
-                       msg.append("         package.provided:\n\n")
-                       for arg in self._pprovided_args:
-                               msg.append("             " + arg + "\n")
-                       msg.append("\n")
-                       sys.stderr.write("".join(msg))
-
-       def calc_changelog(self,ebuildpath,current,next):
-               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 = open(changelogpath).read()
-               except SystemExit, e:
-                       raise # Needed else can't exit
-               except:
-                       return []
-               divisions = self.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(self,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]
-
-       def outdated(self):
-               return self.outdatedpackages
-
-class PackageCounters(object):
-
-       def __init__(self):
-               self.upgrades   = 0
-               self.downgrades = 0
-               self.new        = 0
-               self.newslot    = 0
-               self.reinst     = 0
-               self.blocks     = 0
-               self.totalsize  = 0
-               self.restrict_fetch           = 0
-               self.restrict_fetch_satisfied = 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.blocks > 0:
-                       details.append("%s block" % self.blocks)
-                       if self.blocks > 1:
-                               details[-1] += "s"
-               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))
-               return "".join(myoutput)
-
-class MergeTask(object):
-
-       def __init__(self, settings, trees, myopts):
-               self.settings = settings
-               self.target_root = settings["ROOT"]
-               self.trees = trees
-               self.myopts = myopts
-               self.edebug = 0
-               if settings.get("PORTAGE_DEBUG", "") == "1":
-                       self.edebug = 1
-               self.pkgsettings = {}
-               self.pkgsettings[self.target_root] = portage.config(clone=settings)
-               if self.target_root != "/":
-                       self.pkgsettings["/"] = \
-                               portage.config(clone=trees["/"]["vartree"].settings)
-
-       def merge(self, mylist, favorites, mtimedb):
-               failed_fetches = []
-               mymergelist=[]
-               ldpath_mtimes = mtimedb["ldpath"]
-               xterm_titles = "notitles" not in self.settings.features
-
-               #check for blocking dependencies
-               if "--fetchonly" not in self.myopts and \
-                       "--buildpkgonly" not in self.myopts:
-                       for x in mylist:
-                               if x[0]=="blocks":
-                                       print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
-                                       print   "!!!        the two packages cannot be installed on the same system together."
-                                       print   "!!!        Please use 'emerge --pretend' to determine blockers."
-                                       if "--quiet" not in self.myopts:
-                                               show_blocker_docs_link()
-                                       if "--pretend" not in self.myopts:
-                                               try:
-                                                       del mtimedb["resume"]
-                                               except KeyError:
-                                                       pass
-                                               sys.exit(1)
-
-               #buildsyspkg: I need mysysdict also on resume (moved from the else block)
-               mysysdict = genericdict(getlist(self.settings, "system"))
-               if "--resume" in self.myopts:
-                       # We're resuming.
-                       print colorize("GOOD", "*** Resuming merge...")
-                       emergelog(xterm_titles, " *** Resuming merge...")
-                       mymergelist=mtimedb["resume"]["mergelist"][:]
-                       if "--skipfirst" in self.myopts and mymergelist:
-                               del mtimedb["resume"]["mergelist"][0]
-                               del mymergelist[0]
-                               mtimedb.commit()
-                       validate_merge_list(self.trees, mymergelist)
-               else:
-                       myfavs = portage.grabfile(
-                               os.path.join(self.target_root, portage.WORLD_FILE))
-                       myfavdict=genericdict(myfavs)
-                       for x in range(len(mylist)):
-                               if mylist[x][3]!="nomerge":
-                                       # Add to the mergelist
-                                       mymergelist.append(mylist[x])
-                               else:
-                                       myfavkey=portage.cpv_getkey(mylist[x][2])
-                                       if "--onlydeps" in self.myopts:
-                                               continue
-                                       # Add to the world file. Since we won't be able to later.
-                                       if "--fetchonly" not in self.myopts and \
-                                               myfavkey in favorites:
-                                               #don't record if already in system profile or already recorded
-                                               if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
-                                                       #we don't have a favorites entry for this package yet; add one
-                                                       myfavdict[myfavkey]=myfavkey
-                                                       print ">>> Recording",myfavkey,"in \"world\" favorites file..."
-                       if not ("--fetchonly" in self.myopts or \
-                               "--fetch-all-uri" in self.myopts or \
-                               "--pretend" in self.myopts):
-                               portage.write_atomic(
-                                       os.path.join(self.target_root, portage.WORLD_FILE),
-                                       "\n".join(myfavdict.values()))
-
-                       mtimedb["resume"]["mergelist"]=mymergelist[:]
-                       mtimedb.commit()
-
-               myfeat = self.settings.features[:]
-               bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
-                       "--resume"])
-               if "parallel-fetch" in myfeat and \
-                       not ("--pretend" in self.myopts or \
-                       "--fetch-all-uri" in self.myopts or \
-                       "--fetchonly" in self.myopts):
-                       if "distlocks" not in myfeat:
-                               print red("!!!")
-                               print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
-                               print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
-                               print red("!!!")
-                       elif len(mymergelist) > 1:
-                               print ">>> starting parallel fetching"
-                               fetch_log = "/var/log/emerge-fetch.log"
-                               logfile = open(fetch_log, "w")
-                               fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
-                               portage.util.apply_secpass_permissions(fetch_log,
-                                       uid=portage.portage_uid, gid=portage.portage_gid,
-                                       mode=0660)
-                               fetch_env = os.environ.copy()
-                               fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
-                               fetch_env["PORTAGE_NICENESS"] = "0"
-                               fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
-                               for myopt, myarg in self.myopts.iteritems():
-                                       if myopt not in bad_resume_opts:
-                                               if myarg is True:
-                                                       fetch_args.append(myopt)
-                                               else:
-                                                       fetch_args.append(myopt +"="+ myarg)
-                               portage.process.spawn(fetch_args, env=fetch_env,
-                                       fd_pipes=fd_pipes, returnpid=True)
-                               logfile.close() # belongs to the spawned process
-
-               mergecount=0
-               for x in mymergelist:
-                       mergecount+=1
-                       myroot=x[1]
-                       pkg_key = x[2]
-                       pkgindex=2
-                       portdb = self.trees[myroot]["porttree"].dbapi
-                       bindb  = self.trees[myroot]["bintree"].dbapi
-                       vartree = self.trees[myroot]["vartree"]
-                       pkgsettings = self.pkgsettings[myroot]
-                       if x[0]=="blocks":
-                               pkgindex=3
-                       y = portdb.findname(pkg_key)
-                       if "--pretend" not in self.myopts:
-                               print "\n>>> Emerging (" + \
-                                       colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
-                                       colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
-                                       colorize("GOOD", x[pkgindex]) + " to " + x[1]
-                               emergelog(xterm_titles, " >>> emerge ("+\
-                                       str(mergecount)+" of "+str(len(mymergelist))+\
-                                       ") "+x[pkgindex]+" to "+x[1])
-
-                       pkgsettings["EMERGE_FROM"] = x[0]
-                       pkgsettings.backup_changes("EMERGE_FROM")
-                       pkgsettings.reset()
-
-                       #buildsyspkg: Check if we need to _force_ binary package creation
-                       issyspkg = ("buildsyspkg" in myfeat) \
-                                       and x[0] != "blocks" \
-                                       and mysysdict.has_key(portage.cpv_getkey(x[2])) \
-                                       and "--buildpkg" not in self.myopts
-                       if x[0] in ["ebuild","blocks"]:
-                               if x[0] == "blocks" and "--fetchonly" not in self.myopts:
-                                       raise Exception, "Merging a blocker"
-                               elif "--fetchonly" in self.myopts or \
-                                       "--fetch-all-uri" in self.myopts:
-                                       if "--fetch-all-uri" in self.myopts:
-                                               retval = portage.doebuild(y, "fetch", myroot,
-                                                       pkgsettings, self.edebug,
-                                                       "--pretend" in self.myopts, fetchonly=1,
-                                                       fetchall=1, mydbapi=portdb, tree="porttree")
-                                       else:
-                                               retval = portage.doebuild(y, "fetch", myroot,
-                                                       pkgsettings, self.edebug,
-                                                       "--pretend" in self.myopts, fetchonly=1,
-                                                       mydbapi=portdb, tree="porttree")
-                                       if (retval is None) or retval:
-                                               print
-                                               print "!!! Fetch for",y,"failed, continuing..."
-                                               print
-                                               failed_fetches.append(pkg_key)
-                                       continue
-
-                               portage.doebuild_environment(y, "setup", myroot,
-                                       pkgsettings, self.edebug, 1, portdb)
-                               catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
-                               portage.util.ensure_dirs(os.path.dirname(catdir),
-                                       uid=portage.portage_uid, gid=portage.portage_gid,
-                                       mode=070, mask=0)
-                               builddir_lock = None
-                               catdir_lock = None
-                               try:
-                                       catdir_lock = portage.locks.lockdir(catdir)
-                                       portage.util.ensure_dirs(catdir,
-                                               uid=portage.portage_uid, gid=portage.portage_gid,
-                                               mode=070, mask=0)
-                                       builddir_lock = portage.locks.lockdir(
-                                               pkgsettings["PORTAGE_BUILDDIR"])
-                                       try:
-                                               portage.locks.unlockdir(catdir_lock)
-                                       finally:
-                                               catdir_lock = None
-                                       msg = " === (%s of %s) Cleaning (%s::%s)" % \
-                                               (mergecount, len(mymergelist), pkg_key, y)
-                                       short_msg = "emerge: (%s of %s) %s Clean" % \
-                                               (mergecount, len(mymergelist), pkg_key)
-                                       emergelog(xterm_titles, msg, short_msg=short_msg)
-                                       retval = portage.doebuild(y, "clean", myroot,
-                                               pkgsettings, self.edebug, cleanup=1,
-                                               mydbapi=portdb, tree="porttree")
-                                       if retval != os.EX_OK:
-                                               return retval
-                                       if "--buildpkg" in self.myopts or issyspkg:
-                                               if issyspkg:
-                                                       print ">>> This is a system package, " + \
-                                                               "let's pack a rescue tarball."
-                                               msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
-                                                       (mergecount, len(mymergelist), pkg_key, y)
-                                               short_msg = "emerge: (%s of %s) %s Compile" % \
-                                                       (mergecount, len(mymergelist), pkg_key)
-                                               emergelog(xterm_titles, msg, short_msg=short_msg)
-                                               self.trees[myroot]["bintree"].prevent_collision(pkg_key)
-                                               retval = portage.doebuild(y, "package", myroot,
-                                                       pkgsettings, self.edebug, mydbapi=portdb,
-                                                       tree="porttree")
-                                               if retval != os.EX_OK:
-                                                       return retval
-                                               if "--buildpkgonly" not in self.myopts:
-                                                       bintree = self.trees[myroot]["bintree"]
-                                                       bintree.inject(pkg_key)
-                                                       mytbz2 = bintree.getname(pkg_key)
-                                                       msg = " === (%s of %s) Merging (%s::%s)" % \
-                                                               (mergecount, len(mymergelist), pkg_key, y)
-                                                       short_msg = "emerge: (%s of %s) %s Merge" % \
-                                                               (mergecount, len(mymergelist), pkg_key)
-                                                       emergelog(xterm_titles, msg, short_msg=short_msg)
-                                                       retval = portage.merge(pkgsettings["CATEGORY"],
-                                                               pkgsettings["PF"], pkgsettings["D"],
-                                                               os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
-                                                               "build-info"), myroot, pkgsettings,
-                                                               myebuild=pkgsettings["EBUILD"],
-                                                               mytree="porttree", mydbapi=portdb,
-                                                               vartree=vartree, prev_mtimes=ldpath_mtimes)
-                                                       if retval != os.EX_OK:
-                                                               return retval
-                                               elif "noclean" not in pkgsettings.features:
-                                                       portage.doebuild(y, "clean", myroot,
-                                                               pkgsettings, self.edebug, mydbapi=portdb,
-                                                               tree="porttree")
-                                       else:
-                                               msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
-                                                       (mergecount, len(mymergelist), pkg_key, y)
-                                               short_msg = "emerge: (%s of %s) %s Compile" % \
-                                                       (mergecount, len(mymergelist), pkg_key)
-                                               emergelog(xterm_titles, msg, short_msg=short_msg)
-                                               retval = portage.doebuild(y, "merge", myroot,
-                                                       pkgsettings, self.edebug, vartree=vartree,
-                                                       mydbapi=portdb, tree="porttree",
-                                                       prev_mtimes=ldpath_mtimes)
-                                               if retval != os.EX_OK:
-                                                       return retval
-                               finally:
-                                       if builddir_lock:
-                                               portage.locks.unlockdir(builddir_lock)
-                                       try:
-                                               if not catdir_lock:
-                                                       # Lock catdir for removal if empty.
-                                                       catdir_lock = portage.locks.lockdir(catdir)
-                                       finally:
-                                               if catdir_lock:
-                                                       try:
-                                                               os.rmdir(catdir)
-                                                       except OSError, e:
-                                                               if e.errno not in (errno.ENOENT,
-                                                                       errno.ENOTEMPTY, errno.EEXIST):
-                                                                       raise
-                                                               del e
-                                                       portage.locks.unlockdir(catdir_lock)
-
-                       elif x[0]=="binary":
-                               #merge the tbz2
-                               mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
-                               if "--getbinpkg" in self.myopts:
-                                       tbz2_lock = None
-                                       try:
-                                               if "distlocks" in pkgsettings.features and \
-                                                       os.access(pkgsettings["PKGDIR"], os.W_OK):
-                                                       portage.util.ensure_dirs(os.path.dirname(mytbz2))
-                                                       tbz2_lock = portage.locks.lockfile(mytbz2,
-                                                               wantnewlockfile=1)
-                                               if self.trees[myroot]["bintree"].isremote(pkg_key):
-                                                       msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
-                                                               (mergecount, len(mymergelist), pkg_key, mytbz2)
-                                                       short_msg = "emerge: (%s of %s) %s Fetch" % \
-                                                               (mergecount, len(mymergelist), pkg_key)
-                                                       emergelog(xterm_titles, msg, short_msg=short_msg)
-                                                       if not self.trees[myroot]["bintree"].gettbz2(
-                                                               pkg_key):
-                                                               return 1
-                                       finally:
-                                               if tbz2_lock:
-                                                       portage.locks.unlockfile(tbz2_lock)
-
-                               if "--fetchonly" in self.myopts or \
-                                       "--fetch-all-uri" in self.myopts:
-                                       continue
-
-                               short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
-                               emergelog(xterm_titles, " === ("+str(mergecount)+\
-                                       " of "+str(len(mymergelist))+") Merging Binary ("+\
-                                       x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
-                               retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
-                                       mydbapi=bindb,
-                                       vartree=self.trees[myroot]["vartree"],
-                                       prev_mtimes=ldpath_mtimes)
-                               if retval != os.EX_OK:
-                                       return retval
-                               #need to check for errors
-                       if "--buildpkgonly" not in self.myopts:
-                               self.trees[x[1]]["vartree"].inject(x[2])
-                               myfavkey=portage.cpv_getkey(x[2])
-                               if "--fetchonly" not in self.myopts and \
-                                       "--fetch-all-uri" not in self.myopts and \
-                                       myfavkey in favorites:
-                                       myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
-                                       myfavdict=genericdict(myfavs)
-                                       #don't record if already in system profile or already recorded
-                                       if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
-                                               #we don't have a favorites entry for this package yet; add one
-                                               myfavdict[myfavkey]=myfavkey
-                                               print ">>> Recording",myfavkey,"in \"world\" favorites file..."
-                                               emergelog(xterm_titles, " === ("+\
-                                                       str(mergecount)+" of "+\
-                                                       str(len(mymergelist))+\
-                                                       ") Updating world file ("+x[pkgindex]+")")
-                                               portage.write_atomic(
-                                               os.path.join(myroot, portage.WORLD_FILE),
-                                               "\n".join(myfavdict.values()))
-
-                               if "--pretend" not in self.myopts and \
-                                       "--fetchonly" not in self.myopts and \
-                                       "--fetch-all-uri" not in self.myopts:
-                                       # Clean the old package that we have merged over top of it.
-                                       if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
-                                               xsplit=portage.pkgsplit(x[2])
-                                               emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
-                                               retval = unmerge(pkgsettings, self.myopts, vartree,
-                                                       "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
-                                               if not retval:
-                                                       emergelog(xterm_titles,
-                                                               " --- AUTOCLEAN: Nothing unmerged.")
-                                       else:
-                                               portage.writemsg_stdout(colorize("WARN", "WARNING:")
-                                                       + " AUTOCLEAN is disabled.  This can cause serious"
-                                                       + " problems due to overlapping packages.\n")
-
-                                       # Figure out if we need a restart.
-                                       mysplit=portage.pkgsplit(x[2])
-                                       if mysplit[0] == "sys-apps/portage" and x[1] == "/":
-                                               myver=mysplit[1]+"-"+mysplit[2]
-                                               if myver[-3:]=='-r0':
-                                                       myver=myver[:-3]
-                                               if (myver != portage.VERSION) and \
-                                                  "livecvsportage" not in self.settings.features:
-                                                       if len(mymergelist) > mergecount:
-                                                               emergelog(xterm_titles,
-                                                                       " ::: completed emerge ("+ \
-                                                                       str(mergecount)+" of "+ \
-                                                                       str(len(mymergelist))+") "+ \
-                                                                       x[2]+" to "+x[1])
-                                                               emergelog(xterm_titles, " *** RESTARTING " + \
-                                                                       "emerge via exec() after change of " + \
-                                                                       "portage version.")
-                                                               del mtimedb["resume"]["mergelist"][0]
-                                                               mtimedb.commit()
-                                                               portage.run_exitfuncs()
-                                                               mynewargv=[sys.argv[0],"--resume"]
-                                                               for myopt, myarg in self.myopts.iteritems():
-                                                                       if myopt not in bad_resume_opts:
-                                                                               if myarg is True:
-                                                                                       mynewargv.append(myopt)
-                                                                               else:
-                                                                                       mynewargv.append(myopt +"="+ myarg)
-                                                               # priority only needs to be adjusted on the first run
-                                                               os.environ["PORTAGE_NICENESS"] = "0"
-                                                               os.execv(mynewargv[0], mynewargv)
-
-                       if "--pretend" not in self.myopts and \
-                               "--fetchonly" not in self.myopts and \
-                               "--fetch-all-uri" not in self.myopts:
-                               if "noclean" not in self.settings.features:
-                                       short_msg = "emerge: (%s of %s) %s Clean Post" % \
-                                               (mergecount, len(mymergelist), x[pkgindex])
-                                       emergelog(xterm_titles, (" === (%s of %s) " + \
-                                               "Post-Build Cleaning (%s::%s)") % \
-                                               (mergecount, len(mymergelist), x[pkgindex], y),
-                                               short_msg=short_msg)
-                               emergelog(xterm_titles, " ::: completed emerge ("+\
-                                       str(mergecount)+" of "+str(len(mymergelist))+") "+\
-                                       x[2]+" to "+x[1])
-
-                       # Unsafe for parallel merges
-                       del mtimedb["resume"]["mergelist"][0]
-                       # Commit after each merge so that --resume may still work in
-                       # in the event that portage is not allowed to exit normally
-                       # due to power failure, SIGKILL, etc...
-                       mtimedb.commit()
-
-               if "--pretend" not in self.myopts:
-                       emergelog(xterm_titles, " *** Finished. Cleaning up...")
-
-               # We're out of the loop... We're done. Delete the resume data.
-               if mtimedb.has_key("resume"):
-                       del mtimedb["resume"]
-               mtimedb.commit()
-
-               #by doing an exit this way, --fetchonly can continue to try to
-               #fetch everything even if a particular download fails.
-               if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
-                       if failed_fetches:
-                               sys.stderr.write("\n\n!!! Some fetch errors were " + \
-                                       "encountered.  Please see above for details.\n\n")
-                               for cpv in failed_fetches:
-                                       sys.stderr.write("   ")
-                                       sys.stderr.write(cpv)
-                                       sys.stderr.write("\n")
-                               sys.stderr.write("\n")
-                               sys.exit(1)
-                       else:
-                               sys.exit(0)
-               return os.EX_OK
-
-def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
-       ldpath_mtimes, autoclean=0):
-       candidate_catpkgs=[]
-       global_unmerge=0
-       xterm_titles = "notitles" not in settings.features
-
-       vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
-       try:
-               # At least the parent needs to exist for the lock file.
-               portage.util.ensure_dirs(vdb_path)
-       except portage.exception.PortageException:
-               pass
-       vdb_lock = None
-       try:
-               if os.access(vdb_path, os.W_OK):
-                       vdb_lock = portage.locks.lockdir(vdb_path)
-               realsyslist = getlist(settings, "system")
-               syslist = []
-               for x in realsyslist:
-                       mycp = portage.dep_getkey(x)
-                       if mycp in settings.getvirtuals():
-                               providers = []
-                               for provider in settings.getvirtuals()[mycp]:
-                                       if vartree.dbapi.match(provider):
-                                               providers.append(provider)
-                               if len(providers) == 1:
-                                       syslist.extend(providers)
-                       else:
-                               syslist.append(mycp)
-       
-               mysettings = portage.config(clone=settings)
-       
-               if not unmerge_files or "world" in unmerge_files or \
-                       "system" in unmerge_files:
-                       if "unmerge"==unmerge_action:
-                               print
-                               print bold("emerge unmerge") + " can only be used with " + \
-                                       "specific package names, not with "+bold("world")+" or"
-                               print bold("system")+" targets."
-                               print
-                               return 0
-                       else:
-                               global_unmerge = 1
-       
-               localtree = vartree
-               # process all arguments and add all
-               # valid db entries to candidate_catpkgs
-               if global_unmerge:
-                       if not unmerge_files or "world" in unmerge_files:
-                               candidate_catpkgs.extend(vartree.dbapi.cp_all())
-                       elif "system" in unmerge_files:
-                               candidate_catpkgs.extend(getlist(settings, "system"))
-               else:
-                       #we've got command-line arguments
-                       if not unmerge_files:
-                               print "\nNo packages to unmerge have been provided.\n"
-                               return 0
-                       for x in unmerge_files:
-                               arg_parts = x.split('/')
-                               if x[0] not in [".","/"] and \
-                                       arg_parts[-1][-7:] != ".ebuild":
-                                       #possible cat/pkg or dep; treat as such
-                                       candidate_catpkgs.append(x)
-                               elif unmerge_action in ["prune","clean"]:
-                                       print "\n!!! Prune and clean do not accept individual" + \
-                                               " ebuilds as arguments;\n    skipping.\n"
-                                       continue
-                               else:
-                                       # it appears that the user is specifying an installed
-                                       # ebuild and we're in "unmerge" mode, so it's ok.
-                                       if not os.path.exists(x):
-                                               print "\n!!! The path '"+x+"' doesn't exist.\n"
-                                               return 0
-       
-                                       absx   = os.path.abspath(x)
-                                       sp_absx = absx.split("/")
-                                       if sp_absx[-1][-7:] == ".ebuild":
-                                               del sp_absx[-1]
-                                               absx = "/".join(sp_absx)
-       
-                                       sp_absx_len = len(sp_absx)
-       
-                                       vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
-                                       vdb_len  = len(vdb_path)
-       
-                                       sp_vdb     = vdb_path.split("/")
-                                       sp_vdb_len = len(sp_vdb)
-       
-                                       if not os.path.exists(absx+"/CONTENTS"):
-                                               print "!!! Not a valid db dir: "+str(absx)
-                                               return 0
-       
-                                       if sp_absx_len <= sp_vdb_len:
-                                               # The Path is shorter... so it can't be inside the vdb.
-                                               print sp_absx
-                                               print absx
-                                               print "\n!!!",x,"cannot be inside "+ \
-                                                       vdb_path+"; aborting.\n"
-                                               return 0
-       
-                                       for idx in range(0,sp_vdb_len):
-                                               if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
-                                                       print sp_absx
-                                                       print absx
-                                                       print "\n!!!", x, "is not inside "+\
-                                                               vdb_path+"; aborting.\n"
-                                                       return 0
-       
-                                       print "="+"/".join(sp_absx[sp_vdb_len:])
-                                       candidate_catpkgs.append(
-                                               "="+"/".join(sp_absx[sp_vdb_len:]))
-       
-               newline=""
-               if (not "--quiet" in myopts):
-                       newline="\n"
-               if settings["ROOT"] != "/":
-                       print darkgreen(newline+ \
-                               ">>> Using system located in ROOT tree "+settings["ROOT"])
-               if (("--pretend" in myopts) or ("--ask" in myopts)) and \
-                       not ("--quiet" in myopts):
-                       print darkgreen(newline+\
-                               ">>> These are the packages that would be unmerged:")
-       
-               pkgmap={}
-               numselected=0
-               for x in candidate_catpkgs:
-                       # cycle through all our candidate deps and determine
-                       # what will and will not get unmerged
-                       try:
-                               mymatch=localtree.dep_match(x)
-                       except KeyError:
-                               mymatch=None
-                       except ValueError, errpkgs:
-                               print "\n\n!!! The short ebuild name \"" + \
-                                       x + "\" is ambiguous.  Please specify"
-                               print "!!! one of the following fully-qualified " + \
-                                       "ebuild names instead:\n"
-                               for i in errpkgs[0]:
-                                       print "    " + green(i)
-                               print
-                               sys.exit(1)
-       
-                       if not mymatch and x[0] not in "<>=~":
-                               #add a "=" if missing
-                               mymatch=localtree.dep_match("="+x)
-                       if not mymatch:
-                               portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
-                                       (x, unmerge_action), noiselevel=-1)
-                               continue
-                       mykey = portage.key_expand(
-                               portage.dep_getkey(
-                                       mymatch[0]), mydb=vartree.dbapi, settings=settings)
-                       if not pkgmap.has_key(mykey):
-                               pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
-                       if unmerge_action=="unmerge":
-                                       for y in mymatch:
-                                               if y not in pkgmap[mykey]["selected"]:
-                                                       pkgmap[mykey]["selected"].append(y)
-                                                       numselected=numselected+len(mymatch)
-       
-                       else:
-                               #unmerge_action in ["prune", clean"]
-                               slotmap={}
-                               for mypkg in mymatch:
-                                       if unmerge_action=="clean":
-                                               myslot=localtree.getslot(mypkg)
-                                       else:
-                                               # since we're pruning, we don't care about slots
-                                               # and put all the pkgs in together
-                                               myslot=0
-                                       if not slotmap.has_key(myslot):
-                                               slotmap[myslot]={}
-                                       slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
-                               for myslot in slotmap.keys():
-                                       counterkeys=slotmap[myslot].keys()
-                                       counterkeys.sort()
-                                       if not counterkeys:
-                                               continue
-                                       counterkeys.sort()
-                                       pkgmap[mykey]["protected"].append(
-                                               slotmap[myslot][counterkeys[-1]])
-                                       del counterkeys[-1]
-                                       #be pretty and get them in order of merge:
-                                       for ckey in counterkeys:
-                                               pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
-                                               numselected=numselected+1
-                                       # ok, now the last-merged package
-                                       # is protected, and the rest are selected
-               if global_unmerge and not numselected:
-                       print "\n>>> No outdated packages were found on your system.\n"
-                       return 0
-       
-               if not numselected:
-                       portage.writemsg_stdout(
-                               "\n>>> No packages selected for removal by " + \
-                               unmerge_action + "\n")
-                       return 0
-       finally:
-               if vdb_lock:
-                       portage.locks.unlockdir(vdb_lock)
-       for x in pkgmap.keys():
-               for y in localtree.dep_match(x):
-                       if y not in pkgmap[x]["omitted"] and \
-                          y not in pkgmap[x]["selected"] and \
-                          y not in pkgmap[x]["protected"]:
-                               pkgmap[x]["omitted"].append(y)
-               if global_unmerge and not pkgmap[x]["selected"]:
-                       #avoid cluttering the preview printout with stuff that isn't getting unmerged
-                       continue
-               if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
-                       print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
-                       print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
-                       if "--pretend" not in myopts and "--ask" not in myopts:
-                               countdown(int(settings["EMERGE_WARNING_DELAY"]),
-                                       colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
-               print "\n "+white(x)
-               for mytype in ["selected","protected","omitted"]:
-                       portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
-                       if pkgmap[x][mytype]:
-                               for mypkg in pkgmap[x][mytype]:
-                                       mysplit=portage.catpkgsplit(mypkg)
-                                       if mysplit[3]=="r0":
-                                               myversion=mysplit[2]
-                                       else:
-                                               myversion=mysplit[2]+"-"+mysplit[3]
-                                       if mytype=="selected":
-                                               portage.writemsg_stdout(
-                                                       colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
-                                       else:
-                                               portage.writemsg_stdout(
-                                                       colorize("GOOD", myversion + " "), noiselevel=-1)
-                       else:
-                               portage.writemsg_stdout("none", noiselevel=-1)
-                       portage.writemsg_stdout("\n", noiselevel=-1)
-
-       portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
-               " packages are slated for removal.\n")
-       portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
-                       " and " + colorize("GOOD", "'omitted'") + \
-                       " packages will not be removed.\n\n")
-
-       if "--pretend" in myopts:
-               #we're done... return
-               return 0
-       if "--ask" in myopts:
-               if userquery("Would you like to unmerge these packages?")=="No":
-                       # enter pretend mode for correct formatting of results
-                       myopts["--pretend"] = True
-                       print
-                       print "Quitting."
-                       print
-                       return 0
-       #the real unmerging begins, after a short delay....
-       if not autoclean:
-               countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
-
-       for x in pkgmap.keys():
-               for y in pkgmap[x]["selected"]:
-                       print ">>> Unmerging "+y+"..."
-                       emergelog(xterm_titles, "=== Unmerging... ("+y+")")
-                       mysplit=y.split("/")
-                       #unmerge...
-                       retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
-                               mysettings, unmerge_action not in ["clean","prune"],
-                               vartree=vartree, ldpath_mtimes=ldpath_mtimes)
-                       if retval != os.EX_OK:
-                               emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
-                               ebuild = vartree.dbapi.findname(y)
-                               show_unmerge_failure_message(y, ebuild, retval)
-                               sys.exit(retval)
-                       else:
-                               clean_world(vartree.dbapi, y)
-                               emergelog(xterm_titles, " >>> unmerge success: "+y)
-       return 1
-
-def show_unmerge_failure_message(pkg, ebuild, retval):
-
-       from formatter import AbstractFormatter, DumbWriter
-       f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
-
-       msg = []
-       msg.append("A removal phase of the '%s' package " % pkg)
-       msg.append("has failed with exit value %s.  " % retval)
-       msg.append("The problem occurred while executing ")
-       msg.append("the ebuild located at '%s'.  " % ebuild)
-       msg.append("If necessary, manually remove the ebuild " )
-       msg.append("in order to skip the execution of removal phases.")
-
-       f.end_paragraph(1)
-       for x in msg:
-               f.add_flowing_data(x)
-       f.end_paragraph(1)
-       f.writer.flush()
-
-def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
-
-       print
-       if os.path.exists("/usr/bin/install-info"):
-               regen_infodirs=[]
-               for z in infodirs:
-                       if z=='':
-                               continue
-                       inforoot=normpath(root+z)
-                       if os.path.isdir(inforoot):
-                               infomtime = long(os.stat(inforoot).st_mtime)
-                               if inforoot not in prev_mtimes or \
-                                       prev_mtimes[inforoot] != infomtime:
-                                               regen_infodirs.append(inforoot)
-
-               if not regen_infodirs:
-                       print " "+green("*")+" GNU info directory index is up-to-date."
-               else:
-                       print " "+green("*")+" Regenerating GNU info directory index..."
-
-                       icount=0
-                       badcount=0
-                       for inforoot in regen_infodirs:
-                               if inforoot=='':
-                                       continue
-                               for filename in ("dir", "dir.gz", "dir.bz2"):
-                                       file_path = os.path.join(inforoot, filename)
-                                       try:
-                                               os.rename(file_path, file_path + ".old")
-                                       except OSError, e:
-                                               if e.errno != errno.ENOENT:
-                                                       raise
-                                               del e
-
-                               if not os.path.isdir(inforoot):
-                                       continue
-                               errmsg = ""
-                               file_list = os.listdir(inforoot)
-                               file_list.sort()
-                               for x in file_list:
-                                       if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
-                                               continue
-                                       myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
-                                       existsstr="already exists, for file `"
-                                       if myso!="":
-                                               if re.search(existsstr,myso):
-                                                       # Already exists... Don't increment the count for this.
-                                                       pass
-                                               elif myso[:44]=="install-info: warning: no info dir entry in ":
-                                                       # This info file doesn't contain a DIR-header: install-info produces this
-                                                       # (harmless) warning (the --quiet switch doesn't seem to work).
-                                                       # Don't increment the count for this.
-                                                       pass
-                                               else:
-                                                       badcount=badcount+1
-                                                       errmsg += myso + "\n"
-                                       icount=icount+1
-
-                               #update mtime so we can potentially avoid regenerating.
-                               prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
-
-                       if badcount:
-                               print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
-                               print errmsg
-                       else:
-                               print " "+green("*")+" Processed",icount,"info files."
-
-
-def post_emerge(settings, mtimedb, retval):
-       """
-       Misc. things to run at the end of a merge session.
-       
-       Update Info Files
-       Update Config Files
-       Update News Items
-       Commit mtimeDB
-       Exit Emerge
-       
-       @param settings: Configuration settings (typically portage.settings)
-       @type settings: portage.config()
-       @param mtimedb: The mtimeDB to store data needed across merge invocations
-       @type mtimedb: MtimeDB class instance
-       @param retval: Emerge's return value
-       @type retval: Int
-       @rype: None
-       @returns:
-       1.  Calls sys.exit(retval)
-       """
-       target_root = settings["ROOT"]
-       info_mtimes = mtimedb["info"]
-
-       # Load the most current variables from ${ROOT}/etc/profile.env
-       settings.unlock()
-       settings.regenerate()
-       settings.lock()
-
-       config_protect = settings.get("CONFIG_PROTECT","").split()
-       infodirs = settings.get("INFOPATH","").split(":") + \
-               settings.get("INFODIR","").split(":")
-
-       os.chdir("/")
-
-       emergelog("notitles" not in settings.features,
-               " *** exiting successfully.")
-
-       if "noinfo" not in settings.features:
-               chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
-
-       chk_updated_cfg_files(target_root, config_protect)
-       
-       NEWS_PATH = os.path.join( "metadata", "news" )
-       UNREAD_PATH = os.path.join( target_root, NEWS_LIB_PATH, 'news')
-       porttree = portdbapi( porttree_root = settings["PORTDIR"], mysettings = settings )
-       newsReaderDisplay = False
-       
-       for repo in porttree.getRepositories():
-               unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
-               if unreadItems:
-                       print colorize("WARN", " * IMPORTANT:"),
-                       print "%s news items need reading for repository '%s'." % (unreadItems, repo)
-                       newsReaderDisplay = True
-       
-       if newsReaderDisplay:
-               print colorize("WARN", " *"),
-               print "Use " + colorize("GOOD", "eselect news") + " to read news items."
-       
-       mtimedb.commit()
-       sys.exit(retval)
-
-
-def chk_updated_cfg_files(target_root, config_protect):
-       if config_protect:
-               #number of directories with some protect files in them
-               procount=0
-               for x in config_protect:
-                       x = os.path.join(target_root, x.lstrip(os.path.sep))
-                       try:
-                               mymode = os.lstat(x).st_mode
-                       except OSError:
-                               continue
-                       if stat.S_ISDIR(mymode):
-                               mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
-                       else:
-                               mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
-                                       os.path.split(x.rstrip(os.path.sep))
-                       a = commands.getstatusoutput(mycommand + \
-                               " ! -iname '.*~' ! -iname '.*.bak'")
-                       if a[0] != 0:
-                               print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
-                       else:
-                               files = a[1].split()
-                               if files:
-                                       procount += 1
-                                       print colorize("WARN", " * IMPORTANT:"),
-                                       if stat.S_ISDIR(mymode):
-                                                print "%d config files in '%s' need updating." % \
-                                                       (len(files), x)
-                                       else:
-                                                print "config file '%s' needs updating." % x
-
-               if procount:
-                       #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
-                       print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
-
-def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
-       """
-       Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
-       Returns the number of unread (yet relevent) items.
-       
-       @param root:
-       @type root:
-       @param NEWS_PATH:
-       @type NEWS_PATH:
-       @param UNREAD_PATH:
-       @type UNREAD_PATH:
-       @param repo_id:
-       @type repo_id:
-       @rtype: Integer
-       @returns:
-       1.  The number of unread but relevant news items.
-       
-       """
-       from portage.news import NewsManager
-       manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
-       return manager.getUnreadItems( repo_id, update=True )
-
-def is_valid_package_atom(x):
-       try:
-               testkey = portage.dep_getkey(x)
-       except portage.exception.InvalidData:
-               return False
-       if testkey.startswith("null/"):
-               testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
-       elif "/" not in x:
-               testatom = "cat/"+x
-       else:
-               testatom = x
-       return portage.isvalidatom(testatom)
-
-def validate_merge_list(trees, mergelist):
-       """Validate the list to make sure all the packages are still available.
-       This is needed for --resume."""
-       for (pkg_type, myroot, pkg_key, action) in mergelist:
-               if pkg_type == "binary" and \
-                       not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
-                       pkg_type == "ebuild" and \
-                       not trees[myroot]["porttree"].dbapi.xmatch(
-                       "match-all", "="+pkg_key):
-                       print red("!!! Error: The resume list contains packages that are no longer")
-                       print red("!!!        available to be emerged. Please restart/continue")
-                       print red("!!!        the merge operation manually.")
-                       sys.exit(1)
-
-def show_blocker_docs_link():
-       print
-       print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
-       print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
-       print
-       print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
-       print
-
-def action_sync(settings, trees, mtimedb, myopts, myaction):
-       xterm_titles = "notitles" not in settings.features
-       emergelog(xterm_titles, " === sync")
-       myportdir = settings.get("PORTDIR", None)
-       if not myportdir:
-               sys.stderr.write("!!! PORTDIR is undefined.  Is /etc/make.globals missing?\n")
-               sys.exit(1)
-       if myportdir[-1]=="/":
-               myportdir=myportdir[:-1]
-       if not os.path.exists(myportdir):
-               print ">>>",myportdir,"not found, creating it."
-               os.makedirs(myportdir,0755)
-       syncuri=settings["SYNC"].rstrip()
-       os.umask(0022)
-       updatecache_flg = False
-       if myaction == "metadata":
-               print "skipping sync"
-               updatecache_flg = True
-               tmpservertimestampfile = None
-       elif syncuri[:8]=="rsync://":
-               if not os.path.exists("/usr/bin/rsync"):
-                       print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
-                       print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
-                       sys.exit(1)
-               mytimeout=180
-
-               rsync_opts = []
-
-               if settings["PORTAGE_RSYNC_OPTS"] == "":
-                       portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
-                       rsync_opts.extend([
-                               "--recursive",    # Recurse directories
-                               "--links",        # Consider symlinks
-                               "--safe-links",   # Ignore links outside of tree
-                               "--perms",        # Preserve permissions
-                               "--times",        # Preserive mod times
-                               "--compress",     # Compress the data transmitted
-                               "--force",        # Force deletion on non-empty dirs
-                               "--whole-file",   # Don't do block transfers, only entire files
-                               "--delete",       # Delete files that aren't in the master tree
-                               "--delete-after", # Delete only after everything else is done
-                               "--stats",        # Show final statistics about what was transfered
-                               "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
-                               "--exclude='/distfiles'",   # Exclude distfiles from consideration
-                               "--exclude='/local'",       # Exclude local     from consideration
-                               "--exclude='/packages'",    # Exclude packages  from consideration
-                       ])
-
-               else:
-                       # The below validation is not needed when using the above hardcoded
-                       # defaults.
-
-                       portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
-                       rsync_opts.extend(settings["PORTAGE_RSYNC_OPTS"].split())
-
-                       for opt in ("--recursive", "--times"):
-                               if opt not in rsync_opts:
-                                       portage.writemsg(yellow("WARNING:") + " adding required option " + \
-                                       "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
-                                       rsync_opts.append(opt)
-       
-                       for exclude in ("distfiles", "local", "packages"):
-                               opt = "--exclude=/%s" % exclude
-                               if opt not in rsync_opts:
-                                       portage.writemsg(yellow("WARNING:") + \
-                                       " adding required option %s not included in "  % opt + \
-                                       "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
-                                       rsync_opts.append(opt)
-       
-                       if settings["RSYNC_TIMEOUT"] != "":
-                               portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
-                               "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
-                               try:
-                                       mytimeout = int(settings["RSYNC_TIMEOUT"])
-                                       rsync_opts.append("--timeout=%d" % mytimeout)
-                               except ValueError, e:
-                                       portage.writemsg("!!! %s\n" % str(e))
-       
-                       # TODO: determine options required for official servers
-                       if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
-
-                               def rsync_opt_startswith(opt_prefix):
-                                       for x in rsync_opts:
-                                               if x.startswith(opt_prefix):
-                                                       return True
-                                       return False
-
-                               if not rsync_opt_startswith("--timeout="):
-                                       rsync_opts.append("--timeout=%d" % mytimeout)
-
-                               for opt in ("--compress", "--whole-file"):
-                                       if opt not in rsync_opts:
-                                               portage.writemsg(yellow("WARNING:") + " adding required option " + \
-                                               "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
-                                               rsync_opts.append(opt)
-
-               if "--quiet" in myopts:
-                       rsync_opts.append("--quiet")    # Shut up a lot
-               else:
-                       rsync_opts.append("--verbose")  # Print filelist
-
-               if "--verbose" in myopts:
-                       rsync_opts.append("--progress")  # Progress meter for each file
-
-               if "--debug" in myopts:
-                       rsync_opts.append("--checksum") # Force checksum on all files
-
-               if settings["RSYNC_EXCLUDEFROM"] != "":
-                       portage.writemsg(yellow("WARNING:") + \
-                       " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
-                       "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
-                       if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
-                               rsync_opts.append("--exclude-from=%s" % \
-                               settings["RSYNC_EXCLUDEFROM"])
-                       else:
-                               portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
-                               " but file does not exist.\n")
-
-               if settings["RSYNC_RATELIMIT"] != "":
-                       portage.writemsg(yellow("WARNING:") + \
-                       " usage of RSYNC_RATELIMIT is deprecated, use " + \
-                       "PORTAGE_RSYNC_EXTRA_OPTS instead")
-                       rsync_opts.append("--bwlimit=%s" % \
-                       settings["RSYNC_RATELIMIT"])
-
-               # Real local timestamp file.
-               servertimestampfile = os.path.join(
-                       myportdir, "metadata", "timestamp.chk")
-               # Temporary file for remote server timestamp comparison.
-               tmpservertimestampfile = os.path.join(
-                       settings["PORTAGE_TMPDIR"], "timestamp.chk")
-
-               content = portage.util.grabfile(servertimestampfile)
-               mytimestamp = 0
-               if content:
-                       try:
-                               mytimestamp = time.mktime(time.strptime(content[0],
-                                       "%a, %d %b %Y %H:%M:%S +0000"))
-                       except OverflowError, ValueError:
-                               pass
-               del content
-
-               try:
-                       if settings.has_key("RSYNC_RETRIES"):
-                               print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
-                               maxretries=int(settings["RSYNC_RETRIES"])                               
-                       else:
-                               maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
-               except SystemExit, e:
-                       raise # Needed else can't exit
-               except:
-                       maxretries=3 #default number of retries
-
-               retries=0
-               user_name, hostname, port = re.split(
-                       "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
-               if port is None:
-                       port=""
-               if user_name is None:
-                       user_name=""
-               updatecache_flg=True
-               all_rsync_opts = set(rsync_opts)
-               all_rsync_opts.update(
-                       settings.get("PORTAGE_RSYNC_EXTRA_OPTS","").split())
-               family = socket.AF_UNSPEC
-               if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
-                       family = socket.AF_INET
-               elif socket.has_ipv6 and \
-                       ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
-                       family = socket.AF_INET6
-               ips=[]
-               while (1):
-                       if ips:
-                               del ips[0]
-                       if ips==[]:
-                               try:
-                                       for addrinfo in socket.getaddrinfo(
-                                               hostname, None, family, socket.SOCK_STREAM):
-                                               if addrinfo[0] == socket.AF_INET6:
-                                                       # IPv6 addresses need to be enclosed in square brackets
-                                                       ips.append("[%s]" % addrinfo[4][0])
-                                               else:
-                                                       ips.append(addrinfo[4][0])
-                                       from random import shuffle
-                                       shuffle(ips)
-                               except SystemExit, e:
-                                       raise # Needed else can't exit
-                               except Exception, e:
-                                       print "Notice:",str(e)
-                                       dosyncuri=syncuri
-
-                       if ips:
-                               try:
-                                       dosyncuri = syncuri.replace(
-                                               "//" + user_name + hostname + port + "/",
-                                               "//" + user_name + ips[0] + port + "/", 1)
-                               except SystemExit, e:
-                                       raise # Needed else can't exit
-                               except Exception, e:
-                                       print "Notice:",str(e)
-                                       dosyncuri=syncuri
-
-                       if (retries==0):
-                               if "--ask" in myopts:
-                                       if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
-                                               print
-                                               print "Quitting."
-                                               print
-                                               sys.exit(0)
-                               emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
-                               if "--quiet" not in myopts:
-                                       print ">>> Starting rsync with "+dosyncuri+"..."
-                       else:
-                               emergelog(xterm_titles,
-                                       ">>> Starting retry %d of %d with %s" % \
-                                               (retries,maxretries,dosyncuri))
-                               print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
-
-                       if mytimestamp != 0 and "--quiet" not in myopts:
-                               print ">>> Checking server timestamp ..."
-
-                       rsynccommand = " ".join(["/usr/bin/rsync", " ".join(rsync_opts),
-                               settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")])
-
-                       if "--debug" in myopts:
-                               print rsynccommand
-
-                       exitcode = os.EX_OK
-                       servertimestamp = 0
-                       if mytimestamp != 0:
-                               mycommand = rsynccommand.split()
-                               mycommand.append(dosyncuri.rstrip("/") + \
-                                       "/metadata/timestamp.chk")
-                               mycommand.append(tmpservertimestampfile)
-                               try:
-                                       exitcode = portage.process.spawn(
-                                               mycommand, env=settings.environ())
-                                       content = portage.grabfile(tmpservertimestampfile)
-                                       if content:
-                                               try:
-                                                       servertimestamp = time.mktime(time.strptime(
-                                                               content[0], "%a, %d %b %Y %H:%M:%S +0000"))
-                                               except OverflowError, ValueError:
-                                                       pass
-                                       del content
-                               finally:
-                                       try:
-                                               os.unlink(tmpservertimestampfile)
-                                       except OSError:
-                                               pass
-                               del mycommand
-                       if exitcode == os.EX_OK:
-                               if (servertimestamp != 0) and (servertimestamp == mytimestamp):
-                                       emergelog(xterm_titles,
-                                               ">>> Cancelling sync -- Already current.")
-                                       print
-                                       print ">>>"
-                                       print ">>> Timestamps on the server and in the local repository are the same."
-                                       print ">>> Cancelling all further sync action. You are already up to date."
-                                       print ">>>"
-                                       print ">>> In order to force sync, remove '%s'." % servertimestampfile
-                                       print ">>>"
-                                       print
-                                       sys.exit(0)
-                               elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
-                                       emergelog(xterm_titles,
-                                               ">>> Server out of date: %s" % dosyncuri)
-                                       print
-                                       print ">>>"
-                                       print ">>> SERVER OUT OF DATE: %s" % dosyncuri
-                                       print ">>>"
-                                       print ">>> In order to force sync, remove '%s'." % servertimestampfile
-                                       print ">>>"
-                                       print
-                               elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
-                                       # actual sync
-                                       mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir
-                                       exitcode=portage.spawn(mycommand,settings,free=1)
-                                       if exitcode in [0,1,2,3,4,11,14,20,21]:
-                                               break
-                       elif exitcode in [0,1,2,3,4,11,14,20,21]:
-                               break
-
-                       retries=retries+1
-
-                       if retries<=maxretries:
-                               print ">>> Retrying..."
-                               time.sleep(11)
-                       else:
-                               # over retries
-                               # exit loop
-                               updatecache_flg=False
-                               break
-
-               if (exitcode==0):
-                       emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
-               elif (exitcode>0):
-                       print
-                       if exitcode==1:
-                               print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
-                               print darkred("!!!")+green(" that your SYNC statement is proper.")
-                               print darkred("!!!")+green(" SYNC="+settings["SYNC"])
-                       elif exitcode==11:
-                               print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
-                               print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
-                               print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
-                               print darkred("!!!")+green(" and try again after the problem has been fixed.")
-                               print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
-                       elif exitcode==20:
-                               print darkred("!!!")+green(" Rsync was killed before it finished.")
-                       else:
-                               print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
-                               print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
-                               print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
-                               print darkred("!!!")+green(" temporary problem unless complications exist with your network")
-                               print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
-                       print
-                       sys.exit(exitcode)
-       elif syncuri[:6]=="cvs://":
-               if not os.path.exists("/usr/bin/cvs"):
-                       print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
-                       print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
-                       sys.exit(1)
-               cvsroot=syncuri[6:]
-               cvsdir=os.path.dirname(myportdir)
-               if not os.path.exists(myportdir+"/CVS"):
-                       #initial checkout
-                       print ">>> Starting initial cvs checkout with "+syncuri+"..."
-                       if os.path.exists(cvsdir+"/gentoo-x86"):
-                               print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
-                               sys.exit(1)
-                       try:
-                               os.rmdir(myportdir)
-                       except OSError, e:
-                               if e.errno != errno.ENOENT:
-                                       sys.stderr.write(
-                                               "!!! existing '%s' directory; exiting.\n" % myportdir)
-                                       sys.exit(1)
-                               del e
-                       if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
-                               print "!!! cvs checkout error; exiting."
-                               sys.exit(1)
-                       os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
-               else:
-                       #cvs update
-                       print ">>> Starting cvs update with "+syncuri+"..."
-                       retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
-                               myportdir, settings, free=1)
-                       if retval != os.EX_OK:
-                               sys.exit(retval)
-               dosyncuri = syncuri
-       else:
-               print "!!! rsync setting: ",syncuri,"not recognized; exiting."
-               sys.exit(1)
-
-       if updatecache_flg and  \
-               myaction != "metadata" and \
-               "metadata-transfer" not in settings.features:
-               updatecache_flg = False
-
-       # Reload the whole config from scratch.
-       settings, trees, mtimedb = load_emerge_config(trees=trees)
-       portdb = trees[settings["ROOT"]]["porttree"].dbapi
-
-       if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
-               action_metadata(settings, portdb, myopts)
-
-       if portage.global_updates(settings, trees, mtimedb["updates"]):
-               mtimedb.commit()
-               # Reload the whole config from scratch.
-               settings, trees, mtimedb = load_emerge_config(trees=trees)
-               portdb = trees[settings["ROOT"]]["porttree"].dbapi
-
-       mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
-       mypvs = portage.best(
-               trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
-
-       chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
-
-       if myaction != "metadata":
-               if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
-                       retval = portage.process.spawn(
-                               [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
-                               dosyncuri], env=settings.environ())
-                       if retval != os.EX_OK:
-                               print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
-
-       if(mybestpv != mypvs) and not "--quiet" in myopts:
-               print
-               print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
-               print red(" * ")+"that you update portage now, before any other packages are updated."
-               print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
-               print red(" * ")+"configuration files."
-               print red(" * ")+"To update portage, run 'emerge portage'."
-               print
-
-def action_metadata(settings, portdb, myopts):
-       portage.writemsg_stdout("\n>>> Updating Portage cache:      ")
-       old_umask = os.umask(0002)
-       cachedir = os.path.normpath(settings.depcachedir)
-       if cachedir in ["/",    "/bin", "/dev",  "/etc",  "/home",
-                                       "/lib", "/opt", "/proc", "/root", "/sbin",
-                                       "/sys", "/tmp", "/usr",  "/var"]:
-               print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
-                       "ROOT DIRECTORY ON YOUR SYSTEM."
-               print >> sys.stderr, \
-                       "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
-               sys.exit(73)
-       if not os.path.exists(cachedir):
-               os.mkdir(cachedir)
-
-       ec = portage.eclass_cache.cache(portdb.porttree_root)
-       myportdir = os.path.realpath(settings["PORTDIR"])
-       cm = settings.load_best_module("portdbapi.metadbmodule")(
-               myportdir, "metadata/cache", portage.auxdbkeys[:])
-
-       from portage.cache import util
-
-       class percentage_noise_maker(util.quiet_mirroring):
-               def __init__(self, dbapi):
-                       self.dbapi = dbapi
-                       self.cp_all = dbapi.cp_all()
-                       l = len(self.cp_all)
-                       self.call_update_min = 100000000
-                       self.min_cp_all = l/100.0
-                       self.count = 1
-                       self.pstr = ''
-
-               def __iter__(self):
-                       for x in self.cp_all:
-                               self.count += 1
-                               if self.count > self.min_cp_all:
-                                       self.call_update_min = 0
-                                       self.count = 0
-                               for y in self.dbapi.cp_list(x):
-                                       yield y
-                       self.call_update_mine = 0
-
-               def update(self, *arg):
-                       try:                            self.pstr = int(self.pstr) + 1
-                       except ValueError:      self.pstr = 1
-                       sys.stdout.write("%s%i%%" % \
-                               ("\b" * (len(str(self.pstr))+1), self.pstr))
-                       sys.stdout.flush()
-                       self.call_update_min = 10000000
-
-               def finish(self, *arg):
-                       sys.stdout.write("\b\b\b\b100%\n")
-                       sys.stdout.flush()
-
-       if "--quiet" in myopts:
-               def quicky_cpv_generator(cp_all_list):
-                       for x in cp_all_list:
-                               for y in portdb.cp_list(x):
-                                       yield y
-               source = quicky_cpv_generator(portdb.cp_all())
-               noise_maker = portage.cache.util.quiet_mirroring()
-       else:
-               noise_maker = source = percentage_noise_maker(portdb)
-       portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
-               eclass_cache=ec, verbose_instance=noise_maker)
-
-       sys.stdout.flush()
-       os.umask(old_umask)
-
-def action_regen(settings, portdb):
-       xterm_titles = "notitles" not in settings.features
-       emergelog(xterm_titles, " === regen")
-       #regenerate cache entries
-       print "Regenerating cache entries... "
-       try:
-               os.close(sys.stdin.fileno())
-       except SystemExit, e:
-               raise # Needed else can't exit
-       except:
-               pass
-       sys.stdout.flush()
-       mynodes = portdb.cp_all()
-       from portage.cache.cache_errors import CacheError
-       dead_nodes = {}
-       for mytree in portdb.porttrees:
-               try:
-                       dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
-               except CacheError, e:
-                       print "\n  error listing cache entries for " + \
-                               "'%s': %s, continuing..." % (mytree, e)
-                       del e
-                       dead_nodes = None
-                       break
-       for x in mynodes:
-               mymatches = portdb.xmatch("match-all",x)
-               portage.writemsg_stdout("processing %s\n" % x)
-               for y in mymatches:
-                       try:
-                               foo = portdb.aux_get(y,["DEPEND"])
-                       except SystemExit, e:
-                               # sys.exit is an exception... And consequently, we can't catch it.
-                               raise
-                       except Exception, e:
-                               print "\n  error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
-                       if dead_nodes:
-                               for mytree in portdb.porttrees:
-                                       if portdb.findname2(y, mytree=mytree)[0]:
-                                               dead_nodes[mytree].discard(y)
-       if dead_nodes:
-               for mytree, nodes in dead_nodes.iteritems():
-                       auxdb = portdb.auxdb[mytree]
-                       for y in nodes:
-                               try:
-                                       del auxdb[y]
-                               except KeyError, CacheError:
-                                       pass
-       print "done!"
-
-def action_config(settings, trees, myopts, myfiles):
-       if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
-               print red("!!! config can only take a single package atom at this time\n")
-               sys.exit(1)
-       if not is_valid_package_atom(myfiles[0]):
-               portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
-                       noiselevel=-1)
-               portage.writemsg("!!! Please check ebuild(5) for full details.\n")
-               portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
-               sys.exit(1)
-       print
-       try:
-               pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
-       except ValueError, e:
-               # Multiple matches thrown from cpv_expand
-               pkgs = e.args[0]
-       if len(pkgs) == 0:
-               print "No packages found.\n"
-               sys.exit(0)
-       elif len(pkgs) > 1:
-               if "--ask" in myopts:
-                       options = []
-                       print "Please select a package to configure:"
-                       idx = 0
-                       for pkg in pkgs:
-                               idx += 1
-                               options.append(str(idx))
-                               print options[-1]+") "+pkg
-                       print "X) Cancel"
-                       options.append("X")
-                       idx = userquery("Selection?", options)
-                       if idx == "X":
-                               sys.exit(0)
-                       pkg = pkgs[int(idx)-1]
-               else:
-                       print "The following packages available:"
-                       for pkg in pkgs:
-                               print "* "+pkg
-                       print "\nPlease use a specific atom or the --ask option."
-                       sys.exit(1)
-       else:
-               pkg = pkgs[0]
-
-       print
-       if "--ask" in myopts:
-               if userquery("Ready to configure "+pkg+"?") == "No":
-                       sys.exit(0)
-       else:
-               print "Configuring pkg..."
-       print
-       ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
-       mysettings = portage.config(clone=settings)
-       portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
-               debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
-               mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
-       print
-
-def action_info(settings, trees, myopts, myfiles):
-       unameout=commands.getstatusoutput("uname -mrp")[1]
-       print getportageversion(settings["PORTDIR"], settings["ROOT"],
-               settings.profile_path, settings["CHOST"],
-               trees[settings["ROOT"]]["vartree"].dbapi)
-       header_width = 65
-       header_title = "System Settings"
-       if myfiles:
-               print header_width * "="
-               print header_title.rjust(int(header_width/2 + len(header_title)/2))
-       print header_width * "="
-       print "System uname: "+unameout
-       gentoo_release = portage.grabfile(os.path.join(
-               settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
-       if gentoo_release:
-               print gentoo_release[0]
-       else:
-               print "Unknown Host Operating System"
-       lastSync = portage.grabfile(os.path.join(
-               settings["PORTDIR"], "metadata", "timestamp.chk"))
-       print "Timestamp of tree:",
-       if lastSync:
-               print lastSync[0]
-       else:
-               print "Unknown"
-
-       output=commands.getstatusoutput("distcc --version")
-       if not output[0]:
-               print str(output[1].split("\n",1)[0]),
-               if "distcc" in settings.features:
-                       print "[enabled]"
-               else:
-                       print "[disabled]"
-
-       output=commands.getstatusoutput("ccache -V")
-       if not output[0]:
-               print str(output[1].split("\n",1)[0]),
-               if "ccache" in settings.features:
-                       print "[enabled]"
-               else:
-                       print "[disabled]"
-
-       myvars  = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
-                  "sys-devel/binutils", "sys-devel/libtool",  "dev-lang/python"]
-       myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
-       myvars  = portage.util.unique_array(myvars)
-       myvars.sort()
-
-       for x in myvars:
-               if portage.isvalidatom(x):
-                       pkg_matches = trees["/"]["vartree"].dbapi.match(x)
-                       pkgs = []
-                       for y in pkg_matches:
-                               mycpv   = portage.catpkgsplit(y)
-                               if(mycpv[3] != "r0"):
-                                       pkgs += [mycpv[2] + "-" + mycpv[3]]
-                               else:
-                                       pkgs += [mycpv[2]]
-                       if pkgs:
-                               pkgs = ", ".join(sorted_versions(pkgs))
-                               print "%-20s %s" % (x+":", pkgs)
-               else:
-                       print "%-20s %s" % (x+":", "[NOT VALID]")
-
-       libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
-
-       if "--verbose" in myopts:
-               myvars=settings.keys()
-       else:
-               myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
-                         'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
-                         'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
-                         'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
-
-               myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
-
-       myvars = portage.util.unique_array(myvars)
-       unset_vars = []
-       myvars.sort()
-       for x in myvars:
-               if x in settings:
-                       if x != "USE":
-                               print '%s="%s"' % (x, settings[x])
-                       else:
-                               use = set(settings["USE"].split())
-                               use_expand = settings["USE_EXPAND"].split()
-                               use_expand.sort()
-                               for varname in use_expand:
-                                       flag_prefix = varname.lower() + "_"
-                                       for f in list(use):
-                                               if f.startswith(flag_prefix):
-                                                       use.remove(f)
-                               use = list(use)
-                               use.sort()
-                               print 'USE="%s"' % " ".join(use),
-                               for varname in use_expand:
-                                       myval = settings.get(varname)
-                                       if myval:
-                                               print '%s="%s"' % (varname, myval),
-                               print
-               else:
-                       unset_vars.append(x)
-       if unset_vars:
-               print "Unset:  "+", ".join(unset_vars)
-       print
-
-       if "--debug" in myopts:
-               for x in dir(portage):
-                       module = getattr(portage, x)
-                       if "cvs_id_string" in dir(module):
-                               print "%s: %s" % (str(x), str(module.cvs_id_string))
-
-       # See if we can find any packages installed matching the strings
-       # passed on the command line
-       mypkgs = []
-       vardb = trees[settings["ROOT"]]["vartree"].dbapi
-       portdb = trees[settings["ROOT"]]["porttree"].dbapi
-       for x in myfiles:
-               mypkgs.extend(vardb.match(x))
-
-       # If some packages were found...
-       if mypkgs:
-               # Get our global settings (we only print stuff if it varies from
-               # the current config)
-               mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
-               auxkeys = mydesiredvars + [ "USE", "IUSE"]
-               global_vals = {}
-               pkgsettings = portage.config(clone=settings)
-
-               for myvar in mydesiredvars:
-                       global_vals[myvar] = set(settings.get(myvar, "").split())
-
-               # Loop through each package
-               # Only print settings if they differ from global settings
-               header_printed = False
-               for pkg in mypkgs:
-                       # Get all package specific variables
-                       auxvalues = vardb.aux_get(pkg, auxkeys)
-                       valuesmap = {}
-                       for i in xrange(len(auxkeys)):
-                               valuesmap[auxkeys[i]] = set(auxvalues[i].split())
-                       diff_values = {}
-                       for myvar in mydesiredvars:
-                               # If the package variable doesn't match the
-                               # current global variable, something has changed
-                               # so set diff_found so we know to print
-                               if valuesmap[myvar] != global_vals[myvar]:
-                                       diff_values[myvar] = valuesmap[myvar]
-                       valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
-                       valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
-                       pkgsettings.reset()
-                       # If a matching ebuild is no longer available in the tree, maybe it
-                       # would make sense to compare against the flags for the best
-                       # available version with the same slot?
-                       mydb = None
-                       if portdb.cpv_exists(pkg):
-                               mydb = portdb
-                       pkgsettings.setcpv(pkg, mydb=mydb)
-                       if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
-                               valuesmap["USE"]:
-                               diff_values["USE"] = valuesmap["USE"]
-                       # If a difference was found, print the info for
-                       # this package.
-                       if diff_values:
-
-                               # If we have not yet printed the header, 
-                               # print it now
-                               if not header_printed:
-                                       header_title = "Package Settings"
-                                       print header_width * "="
-                                       print header_title.rjust(int(header_width/2 + len(header_title)/2))
-                                       print header_width * "="
-                                       header_printed = True
-
-                               # Print package info
-                               print "%s was built with the following:" % pkg
-                               for myvar in mydesiredvars + ["USE"]:
-                                       if myvar in diff_values:
-                                               mylist = list(diff_values[myvar])
-                                               mylist.sort()
-                                               print "%s=\"%s\"" % (myvar, " ".join(mylist))
-                               print
-
-def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
-       if not myfiles:
-               print "emerge: no search terms provided."
-       else:
-               searchinstance = search(settings, portdb,
-                       vartree, spinner, "--searchdesc" in myopts,
-                       "--quiet" not in myopts)
-               for mysearch in myfiles:
-                       try:
-                               searchinstance.execute(mysearch)
-                       except re.error, comment:
-                               print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
-                               sys.exit(1)
-                       searchinstance.output()
-
-def action_depclean(settings, trees, ldpath_mtimes,
-       myopts, spinner):
-       # Kill packages that aren't explicitly merged or are required as a
-       # dependency of another package. World file is explicit.
-
-       warn_prefix = colorize("BAD", "*** WARNING ***  ")
-       print
-       print warn_prefix + "Depclean may break link level dependencies.  Thus, it is"
-       print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
-       print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
-       print warn_prefix
-       print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
-       print warn_prefix + "mistakes. Packages that are part of the world set will always"
-       print warn_prefix + "be kept.  They can be manually added to this set with"
-       print warn_prefix + good("`emerge --noreplace <atom>`") + ".  Packages that are listed in"
-       print warn_prefix + "package.provided (see portage(5)) will be removed by"
-       print warn_prefix + "depclean, even if they are part of the world set."
-       print warn_prefix
-       print warn_prefix + "As a safety measure, depclean will not remove any packages"
-       print warn_prefix + "unless *all* required dependencies have been resolved.  As a"
-       print warn_prefix + "consequence, it is often necessary to run "
-       print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
-
-       xterm_titles = "notitles" not in settings.features
-       myroot = settings["ROOT"]
-       dep_check_trees = {}
-       dep_check_trees[myroot] = {}
-       dep_check_trees[myroot]["vartree"] = \
-               FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
-       vardb = dep_check_trees[myroot]["vartree"].dbapi
-       # Constrain dependency selection to the installed packages.
-       dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
-       syslist = getlist(settings, "system")
-       worldlist = getlist(settings, "world")
-       fakedb = portage.fakedbapi(settings=settings)
-       myvarlist = vardb.cpv_all()
-
-       if not syslist:
-               print "\n!!! You have no system list.",
-       if not worldlist:
-               print "\n!!! You have no world file.",
-       if not myvarlist:
-               print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
-
-       if not (syslist and worldlist and myvarlist):
-               print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
-               print " break your installation.\n"
-               if "--pretend" not in myopts:
-                       countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
-
-       if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
-               emergelog(xterm_titles, " >>> depclean")
-
-       if "--quiet" not in myopts:
-               print "\nCalculating dependencies  ",
-
-       soft = 0
-       hard = 1
-       remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
-       remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
-       unresolveable = {}
-       aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
-
-       while remaining_atoms:
-               atom, parent, priority = remaining_atoms.pop()
-               pkgs = vardb.match(atom)
-               if not pkgs:
-                       if not atom.startswith("!") and priority == hard:
-                               unresolveable.setdefault(atom, []).append(parent)
-                       continue
-               # Could put slot checking here to ensure that there aren't two
-               # packages with the same slot...
-               for pkg in pkgs:
-                       if fakedb.cpv_exists(pkg):
-                               continue
-                       spinner.update()
-                       fakedb.cpv_inject(pkg)
-                       myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
-                       mydeps = []
-                       if myopts.get("--with-bdeps", "y") == "y":
-                               mydeps.append((myaux["DEPEND"], soft))
-                       del myaux["DEPEND"]
-                       mydeps.append((" ".join(myaux.values()), hard))
-                       usedef = vardb.aux_get(pkg, ["USE"])[0].split()
-                       for depstr, priority in mydeps:
-
-                               if not depstr:
-                                       continue
-
-                               if "--debug" in myopts:
-                                       print
-                                       print "Parent:   ", pkg
-                                       print "Depstring:", depstr
-                                       print "Priority:",
-                                       if priority == soft:
-                                               print "soft"
-                                       else:
-                                               print "hard"
-
-                               try:
-                                       portage.dep._dep_check_strict = False
-                                       success, atoms = portage.dep_check(depstr, None, settings,
-                                               myuse=usedef, trees=dep_check_trees, myroot=myroot)
-                               finally:
-                                       portage.dep._dep_check_strict = True
-                               if not success:
-                                       show_invalid_depstring_notice(
-                                               ("installed", myroot, pkg, "nomerge"),
-                                               depstr, atoms)
-                                       return
-
-                               if "--debug" in myopts:
-                                       print "Candidates:", atoms
-
-                               for atom in atoms:
-                                       remaining_atoms.append((atom, pkg, priority))
-
-       if "--quiet" not in myopts:
-               print "\b\b... done!\n"
-
-       if unresolveable:
-               print "Dependencies could not be completely resolved due to"
-               print "the following required packages not being installed:"
-               print
-               for atom in unresolveable:
-                       print atom, "required by", " ".join(unresolveable[atom])
-               print
-               print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
-               print "depclean?  It may also be necessary to manually uninstalled packages that no"
-               print "longer exist in the portage tree since it may not be possible to satisfy their"
-               print "dependencies."
-               print
-               return
-
-       cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
-
-       if len(cleanlist):
-               unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
-                       "unmerge", cleanlist, ldpath_mtimes)
-
-       print "Packages installed:   "+str(len(myvarlist))
-       print "Packages in world:    "+str(len(worldlist))
-       print "Packages in system:   "+str(len(syslist))
-       print "Unique package names: "+str(len(myvarlist))
-       print "Required packages:    "+str(len(fakedb.cpv_all()))
-       if "--pretend" in myopts:
-               print "Number to remove:     "+str(len(cleanlist))
-       else:
-               print "Number removed:       "+str(len(cleanlist))
-
-def action_build(settings, trees, mtimedb,
-       myopts, myaction, myfiles, spinner):
-       ldpath_mtimes = mtimedb["ldpath"]
-       favorites=[]
-       if ("--ask" in myopts or "--pretend" in myopts) and not "--quiet" in myopts:
-               action = ""
-               if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
-                       action = "fetched"
-               else:
-                       action = "merged"
-               if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
-                       print
-                       print darkgreen("These are the packages that would be %s, in reverse order:") % action
-                       print
-               else:
-                       print
-                       print darkgreen("These are the packages that would be %s, in order:") % action
-                       print
-
-       # validate the state of the resume data
-       # so that we can make assumptions later.
-       for k in ("resume", "resume_backup"):
-               if k in mtimedb:
-                       if "mergelist" in mtimedb[k]:
-                               if not mtimedb[k]["mergelist"]:
-                                       del mtimedb[k]
-                       else:
-                               del mtimedb[k]
-
-       if "--resume" in myopts and \
-               ("resume" in mtimedb or
-               "resume_backup" in mtimedb):
-               if "resume" not in mtimedb:
-                       mtimedb["resume"] = mtimedb["resume_backup"]
-                       del mtimedb["resume_backup"]
-                       mtimedb.commit()
-               # XXX: "myopts" is a list for backward compatibility.
-               myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
-
-               for opt in ("--skipfirst", "--ask", "--tree"):
-                       myresumeopts.pop(opt, None)
-
-               for myopt, myarg in myopts.iteritems():
-                       if myopt not in myresumeopts:
-                               myresumeopts[myopt] = myarg
-               myopts=myresumeopts
-               myparams = create_depgraph_params(myopts, myaction)
-               if not "--quiet" in myopts:
-                       print "Calculating dependencies  ",
-               mydepgraph = depgraph(settings, trees,
-                       myopts, myparams, spinner)
-               if not "--quiet" in myopts:
-                       print "\b\b... done!"
-       else:
-               if ("--resume" in myopts):
-                       print darkgreen("emerge: It seems we have nothing to resume...")
-                       sys.exit(0)
-
-               myparams = create_depgraph_params(myopts, myaction)
-               if myaction in ["system","world"]:
-                       if not ("--quiet" in myopts):
-                               print "Calculating",myaction,"dependencies  ",
-                               sys.stdout.flush()
-                       mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
-                       if not mydepgraph.xcreate(myaction):
-                               print "!!! Depgraph creation failed."
-                               sys.exit(1)
-                       if not ("--quiet" in myopts):
-                               print "\b\b... done!"
-               else:
-                       if not ("--quiet" in myopts):
-                               print "Calculating dependencies  ",
-                               sys.stdout.flush()
-                       mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
-                       try:
-                               retval, favorites = mydepgraph.select_files(myfiles)
-                       except portage.exception.PackageNotFound, e:
-                               portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
-                               sys.exit(1)
-                       if not retval:
-                               sys.exit(1)
-                       if not ("--quiet" in myopts):
-                               print "\b\b... done!"
-
-                       if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
-                               sys.stderr.write(red("The following binaries are not available for merging...\n"))
-
-               if mydepgraph.missingbins:
-                       for x in mydepgraph.missingbins:
-                               sys.stderr.write("   "+str(x)+"\n")
-                       sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
-                       sys.exit(1)
-
-       if "--ask" in myopts:
-               if "--resume" in myopts:
-                       validate_merge_list(trees, mtimedb["resume"]["mergelist"])
-                       mymergelist = mtimedb["resume"]["mergelist"]
-                       if "--skipfirst" in myopts:
-                               mymergelist = mymergelist[1:]
-                       if len(mymergelist) == 0:
-                               print colorize("INFORM", "emerge: It seems we have nothing to resume...")
-                               sys.exit(0)
-                       mydepgraph.display(mymergelist)
-                       prompt="Would you like to resume merging these packages?"
-               else:
-                       mydepgraph.display(
-                               mydepgraph.altlist(reversed=("--tree" in myopts)))
-                       mergecount=0
-                       for x in mydepgraph.altlist():
-                               if x[0] != "blocks" and x[3] != "nomerge":
-                                       mergecount+=1
-                               #check for blocking dependencies
-                               if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
-                                       print "\n!!! Error: The above package list contains packages which cannot be installed"
-                                       print   "!!!        at the same time on the same system."
-                                       if "--quiet" not in myopts:
-                                               show_blocker_docs_link()
-                                       sys.exit(1)
-                       if mergecount==0:
-                               if "--noreplace" in myopts and favorites:
-                                       print
-                                       for x in favorites:
-                                               print " %s %s" % (good("*"), x)
-                                       prompt="Would you like to add these packages to your world favorites?"
-                               elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
-                                       prompt="Nothing to merge; would you like to auto-clean packages?"
-                               else:
-                                       print
-                                       print "Nothing to merge; quitting."
-                                       print
-                                       sys.exit(0)
-                       elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
-                               prompt="Would you like to fetch the source files for these packages?"
-                       else:
-                               prompt="Would you like to merge these packages?"
-               print
-               if userquery(prompt)=="No":
-                       print
-                       print "Quitting."
-                       print
-                       sys.exit(0)
-               # Don't ask again (e.g. when auto-cleaning packages after merge)
-               del myopts["--ask"]
-
-       if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
-               if ("--resume" in myopts):
-                       validate_merge_list(trees, mtimedb["resume"]["mergelist"])
-                       mymergelist = mtimedb["resume"]["mergelist"]
-                       if "--skipfirst" in myopts:
-                               mymergelist = mymergelist[1:]
-                       if len(mymergelist) == 0:
-                               print colorize("INFORM", "emerge: It seems we have nothing to resume...")
-                               sys.exit(0)
-                       mydepgraph.display(mymergelist)
-               else:
-                       mydepgraph.display(
-                               mydepgraph.altlist(reversed=("--tree" in myopts)))
-       else:
-               if ("--buildpkgonly" in myopts):
-                       if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
-                               print "\n!!! --buildpkgonly requires all dependencies to be merged."
-                               print "!!! Cannot merge requested packages. Merge deps and try again.\n"
-                               sys.exit(1)
-
-               if ("--resume" in myopts):
-                       favorites=mtimedb["resume"]["favorites"]
-                       mergetask = MergeTask(settings, trees, myopts)
-                       if "--fetchonly" in myopts:
-                               """ parallel-fetch uses --resume --fetchonly and we don't want
-                               it to write the mtimedb"""
-                               mtimedb.filename = None
-                               time.sleep(3) # allow the parent to have first fetch
-                       del mydepgraph
-                       retval = mergetask.merge(
-                               mtimedb["resume"]["mergelist"], favorites, mtimedb)
-                       if retval != os.EX_OK:
-                               sys.exit(retval)
-               else:
-                       if "resume" in mtimedb and \
-                       "mergelist" in mtimedb["resume"] and \
-                       len(mtimedb["resume"]["mergelist"]) > 1:
-                               mtimedb["resume_backup"] = mtimedb["resume"]
-                               del mtimedb["resume"]
-                               mtimedb.commit()
-                       mtimedb["resume"]={}
-                       # XXX: Stored as a list for backward compatibility.
-                       mtimedb["resume"]["myopts"] = \
-                               [k for k in myopts if myopts[k] is True]
-                       mtimedb["resume"]["favorites"]=favorites
-                       if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
-                               for pkgline in mydepgraph.altlist():
-                                       if pkgline[0]=="ebuild" and pkgline[3]=="merge":
-                                               y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
-                                               tmpsettings = portage.config(clone=settings)
-                                               edebug = 0
-                                               if settings.get("PORTAGE_DEBUG", "") == "1":
-                                                       edebug = 1
-                                               retval = portage.doebuild(
-                                                       y, "digest", settings["ROOT"], tmpsettings, edebug,
-                                                       ("--pretend" in myopts),
-                                                       mydbapi=trees[pkgline[1]]["porttree"].dbapi,
-                                                       tree="porttree")
-                       if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
-                               pkglist = []
-                               for pkg in mydepgraph.altlist():
-                                       if pkg[0] != "blocks":
-                                               pkglist.append(pkg)
-                       else:
-                               pkglist = mydepgraph.altlist()
-                       del mydepgraph
-                       mergetask = MergeTask(settings, trees, myopts)
-                       retval = mergetask.merge(pkglist, favorites, mtimedb)
-                       if retval != os.EX_OK:
-                               sys.exit(retval)
-
-               if mtimedb.has_key("resume"):
-                       del mtimedb["resume"]
-               if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
-                       print ">>> Auto-cleaning packages..."
-                       vartree = trees[settings["ROOT"]]["vartree"]
-                       unmerge(settings, myopts, vartree, "clean", ["world"],
-                               ldpath_mtimes, autoclean=1)
-               else:
-                       portage.writemsg_stdout(colorize("WARN", "WARNING:")
-                               + " AUTOCLEAN is disabled.  This can cause serious"
-                               + " problems due to overlapping packages.\n")
-
-def multiple_actions(action1, action2):
-       sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
-       sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
-       sys.exit(1)
-
-def parse_opts(tmpcmdline, silent=False):
-       myaction=None
-       myopts = {}
-       myfiles=[]
-
-       global actions, options, shortmapping
-
-       longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
-       argument_options = {
-               "--config-root": {
-                       "help":"specify the location for portage configuration files",
-                       "action":"store"
-               },
-               "--color": {
-                       "help":"enable or disable color output",
-                       "type":"choice",
-                       "choices":("y", "n")
-               },
-               "--with-bdeps": {
-                       "help":"include unnecessary build time dependencies",
-                       "type":"choice",
-                       "choices":("y", "n")
-               }
-       }
-
-       from optparse import OptionParser
-       parser = OptionParser()
-       if parser.has_option("--help"):
-               parser.remove_option("--help")
-
-       for action_opt in actions:
-               parser.add_option("--" + action_opt, action="store_true",
-                       dest=action_opt.replace("-", "_"), default=False)
-       for myopt in options:
-               parser.add_option(myopt, action="store_true",
-                       dest=myopt.lstrip("--").replace("-", "_"), default=False)
-       for shortopt, longopt in shortmapping.iteritems():
-               parser.add_option("-" + shortopt, action="store_true",
-                       dest=longopt.lstrip("--").replace("-", "_"), default=False)
-       for myalias, myopt in longopt_aliases.iteritems():
-               parser.add_option(myalias, action="store_true",
-                       dest=myopt.lstrip("--").replace("-", "_"), default=False)
-
-       for myopt, kwargs in argument_options.iteritems():
-               parser.add_option(myopt,
-                       dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
-
-       myoptions, myargs = parser.parse_args(args=tmpcmdline)
-
-       for myopt in options:
-               v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
-               if v:
-                       myopts[myopt] = True
-
-       for myopt in argument_options:
-               v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
-               if v is not None:
-                       myopts[myopt] = v
-
-       for action_opt in actions:
-               v = getattr(myoptions, action_opt.replace("-", "_"))
-               if v:
-                       if myaction:
-                               multiple_actions(myaction, action_opt)
-                               sys.exit(1)
-                       myaction = action_opt
-
-       for x in myargs:
-               if x in actions and myaction != "search":
-                       if not silent and x not in ["system", "world"]:
-                               print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
-                       # special case "search" so people can search for action terms, e.g. emerge -s sync
-                       if myaction:
-                               multiple_actions(myaction, x)
-                               sys.exit(1)
-                       myaction = x
-               else:
-                       myfiles.append(x)
-
-       if "--nocolor" in myopts:
-               if not silent:
-                       sys.stderr.write("*** Deprecated use of '--nocolor', " + \
-                               "use '--color=n' instead.\n")
-               del myopts["--nocolor"]
-               myopts["--color"] = "n"
-
-       return myaction, myopts, myfiles
-
-def validate_ebuild_environment(trees):
-       for myroot in trees:
-               mysettings = trees[myroot]["vartree"].settings
-               if not mysettings.get("ARCH", None):
-                       print >> sys.stderr, bad("\a!!! ARCH is not set... " + \
-                               "Are you missing the '%setc/make.profile' symlink?" % \
-                               mysettings["PORTAGE_CONFIGROOT"])
-                       print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
-                               "Is your portage tree complete?\n")
-                       sys.exit(9)
-               del myroot, mysettings
-
-def load_emerge_config(trees=None):
-       kwargs = {}
-       for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
-               kwargs[k] = os.environ.get(envvar, None)
-       trees = portage.create_trees(trees=trees, **kwargs)
-
-       settings = trees["/"]["vartree"].settings
-
-       for myroot in trees:
-               if myroot != "/":
-                       settings = trees[myroot]["vartree"].settings
-                       break
-
-       mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
-       mtimedb = portage.MtimeDB(mtimedbfile)
-       return settings, trees, mtimedb
-
-def adjust_config(myopts, settings):
-       """Make emerge specific adjustments to the config."""
-
-       # To enhance usability, make some vars case insensitive by forcing them to
-       # lower case.
-       for myvar in ("AUTOCLEAN", "NOCOLOR"):
-               if myvar in settings:
-                       settings[myvar] = settings[myvar].lower()
-                       settings.backup_changes(myvar)
-       del myvar
-
-       # Kill noauto as it will break merges otherwise.
-       if "noauto" in settings.features:
-               while "noauto" in settings.features:
-                       settings.features.remove("noauto")
-               settings["FEATURES"] = " ".join(settings.features)
-               settings.backup_changes("FEATURES")
-
-       CLEAN_DELAY = 5
-       try:
-               CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
-       except ValueError, e:
-               portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
-               portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
-                       settings["CLEAN_DELAY"], noiselevel=-1)
-       settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
-       settings.backup_changes("CLEAN_DELAY")
-
-       EMERGE_WARNING_DELAY = 10
-       try:
-               EMERGE_WARNING_DELAY = int(settings.get(
-                       "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
-       except ValueError, e:
-               portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
-               portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
-                       settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
-       settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
-       settings.backup_changes("EMERGE_WARNING_DELAY")
-
-       if "--quiet" in myopts:
-               settings["PORTAGE_QUIET"]="1"
-               settings.backup_changes("PORTAGE_QUIET")
-
-       # Set so that configs will be merged regardless of remembered status
-       if ("--noconfmem" in myopts):
-               settings["NOCONFMEM"]="1"
-               settings.backup_changes("NOCONFMEM")
-
-       # Set various debug markers... They should be merged somehow.
-       PORTAGE_DEBUG = 0
-       try:
-               PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
-               if PORTAGE_DEBUG not in (0, 1):
-                       portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
-                               PORTAGE_DEBUG, noiselevel=-1)
-                       portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
-                               noiselevel=-1)
-                       PORTAGE_DEBUG = 0
-       except ValueError, e:
-               portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
-               portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
-                       settings["PORTAGE_DEBUG"], noiselevel=-1)
-               del e
-       if "--debug" in myopts:
-               PORTAGE_DEBUG = 1
-       settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
-       settings.backup_changes("PORTAGE_DEBUG")
-
-       if settings.get("NOCOLOR") not in ("yes","true"):
-               portage.output.havecolor = 1
-
-       """The explicit --color < y | n > option overrides the NOCOLOR environment
-       variable and stdout auto-detection."""
-       if "--color" in myopts:
-               if "y" == myopts["--color"]:
-                       portage.output.havecolor = 1
-                       settings["NOCOLOR"] = "false"
-               else:
-                       portage.output.havecolor = 0
-                       settings["NOCOLOR"] = "true"
-               settings.backup_changes("NOCOLOR")
-       elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
-               portage.output.havecolor = 0
-               settings["NOCOLOR"] = "true"
-               settings.backup_changes("NOCOLOR")
-
-def emerge_main():
-       global portage  # NFC why this is necessary now - genone
-       # Disable color until we're sure that it should be enabled (after
-       # EMERGE_DEFAULT_OPTS has been parsed).
-       portage.output.havecolor = 0
-       # This first pass is just for options that need to be known as early as
-       # possible, such as --config-root.  They will be parsed again later,
-       # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
-       # the value of --config-root).
-       myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
-       if "--debug" in myopts:
-               os.environ["PORTAGE_DEBUG"] = "1"
-       if "--config-root" in myopts:
-               os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
-
-       # Portage needs to ensure a sane umask for the files it creates.
-       os.umask(022)
-       settings, trees, mtimedb = load_emerge_config()
-       portdb = trees[settings["ROOT"]]["porttree"].dbapi
-
-       try:
-               os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
-       except (OSError, ValueError), e:
-               portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
-                       settings["PORTAGE_NICENESS"])
-               portage.writemsg("!!! %s\n" % str(e))
-               del e
-
-       if portage.global_updates(settings, trees, mtimedb["updates"]):
-               mtimedb.commit()
-               # Reload the whole config from scratch.
-               settings, trees, mtimedb = load_emerge_config(trees=trees)
-               portdb = trees[settings["ROOT"]]["porttree"].dbapi
-
-       xterm_titles = "notitles" not in settings.features
-
-       tmpcmdline = []
-       if "--ignore-default-opts" not in sys.argv:
-               tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
-       tmpcmdline.extend(sys.argv[1:])
-       myaction, myopts, myfiles = parse_opts(tmpcmdline)
-
-       if "--digest" in myopts:
-               os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
-               # Reload the whole config from scratch so that the portdbapi internal
-               # config is updated with new FEATURES.
-               settings, trees, mtimedb = load_emerge_config(trees=trees)
-               portdb = trees[settings["ROOT"]]["porttree"].dbapi
-
-       for myroot in trees:
-               mysettings =  trees[myroot]["vartree"].settings
-               mysettings.unlock()
-               adjust_config(myopts, mysettings)
-               mysettings.lock()
-               del myroot, mysettings
-
-       spinner = stdout_spinner()
-       if "candy" in settings.features:
-               spinner.update = spinner.update_scroll
-
-       portage.deprecated_profile_check()
-
-       #Freeze the portdbapi for enhanced performance:
-       for myroot in trees:
-               trees[myroot]["porttree"].dbapi.freeze()
-               del myroot
-
-       if "moo" in myfiles:
-               print """
-
-  Larry loves Gentoo (""" + os.uname()[0] + """)
-
- _______________________
-< Have you mooed today? >
- -----------------------
-        \   ^__^
-         \  (oo)\_______
-            (__)\       )\/\ 
-                ||----w |
-                ||     ||
-
-"""
-
-       if (myaction in ["world", "system"]) and myfiles:
-               print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
-               sys.exit(1)
-
-       for x in myfiles:
-               ext = os.path.splitext(x)[1]
-               if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
-                       print "emerging by path implies --oneshot... adding --oneshot to options."
-                       print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
-                       break
-
-       if ("--tree" in myopts) and ("--columns" in myopts):
-               print "emerge: can't specify both of \"--tree\" and \"--columns\"."
-               sys.exit(1)
-
-       if ("--quiet" in myopts):
-               spinner.update = spinner.update_quiet
-               portage.util.noiselimit = -1
-
-       # Always create packages if FEATURES=buildpkg
-       # Imply --buildpkg if --buildpkgonly
-       if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
-               if "--buildpkg" not in myopts:
-                       myopts["--buildpkg"] = True
-
-       # Also allow -S to invoke search action (-sS)
-       if ("--searchdesc" in myopts):
-               if myaction and myaction != "search":
-                       myfiles.append(myaction)
-               if "--search" not in myopts:
-                       myopts["--search"] = True
-               myaction = "search"
-
-       # Always try and fetch binary packages if FEATURES=getbinpkg
-       if ("getbinpkg" in settings.features):
-               myopts["--getbinpkg"] = True
-
-       if "--skipfirst" in myopts and "--resume" not in myopts:
-               myopts["--resume"] = True
-
-       if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
-               myopts["--usepkgonly"] = True
-
-       if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
-               myopts["--getbinpkg"] = True
-
-       if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
-               myopts["--usepkg"] = True
-
-       # Also allow -K to apply --usepkg/-k
-       if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
-               myopts["--usepkg"] = True
-
-       # Allow -p to remove --ask
-       if ("--pretend" in myopts) and ("--ask" in myopts):
-               print ">>> --pretend disables --ask... removing --ask from options."
-               del myopts["--ask"]
-
-       # forbid --ask when not in a terminal
-       # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
-       if ("--ask" in myopts) and (not sys.stdin.isatty()):
-               portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
-                       noiselevel=-1)
-               sys.exit(1)
-
-       if settings.get("PORTAGE_DEBUG", "") == "1":
-               spinner.update = spinner.update_quiet
-               portage.debug=1
-               if "python-trace" in settings.features:
-                       import portage.debug
-                       portage.debug.set_trace(True)
-
-       if ("--resume" in myopts):
-               if "--tree" in myopts:
-                       print "* --tree is currently broken with --resume. Disabling..."
-                       del myopts["--tree"]
-
-       if not ("--quiet" in myopts):
-               if not sys.stdout.isatty() or ("--nospinner" in myopts):
-                       spinner.update = spinner.update_basic
-
-       if "--version" in myopts:
-               print getportageversion(settings["PORTDIR"], settings["ROOT"],
-                       settings.profile_path, settings["CHOST"],
-                       trees[settings["ROOT"]]["vartree"].dbapi)
-               sys.exit(0)
-       elif "--help" in myopts:
-               emerge.help.help(myaction, myopts, portage.output.havecolor)
-               sys.exit(0)
-
-       if portage.wheelgid == portage.portage_gid:
-               print "emerge: wheel group use is being deprecated. Please update group and passwd to"
-               print "        include the portage user as noted above, and then use group portage."
-
-       if "--debug" in myopts:
-               print "myaction", myaction
-               print "myopts", myopts
-
-       if not myaction and not myfiles and "--resume" not in myopts:
-               emerge.help.help(myaction, myopts, portage.output.havecolor)
-               sys.exit(1)
-
-       # check if root user is the current user for the actions where emerge needs this
-       if portage.secpass < 2:
-               # We've already allowed "--version" and "--help" above.
-               if "--pretend" not in myopts and \
-               myaction not in ("search","info"):
-                       need_superuser = not \
-                               ("--fetchonly" in myopts or \
-                               "--fetch-all-uri" in myopts or \
-                               myaction in ("metadata", "regen"))
-                       if portage.secpass < 1 or \
-                               need_superuser:
-                               if need_superuser:
-                                       access_desc = "superuser"
-                               else:
-                                       access_desc = "portage group"
-                               # Always show portage_group_warning() when only portage group
-                               # access is required but the user is not in the portage group.
-                               from portage.data import portage_group_warning
-                               if "--ask" in myopts:
-                                       myopts["--pretend"] = True
-                                       del myopts["--ask"]
-                                       print ("%s access would be required... " + \
-                                               "adding --pretend to options.\n") % access_desc
-                                       if portage.secpass < 1 and not need_superuser:
-                                               portage_group_warning()
-                               else:
-                                       sys.stderr.write(("emerge: %s access would be " + \
-                                               "required.\n\n") % access_desc)
-                                       if portage.secpass < 1 and not need_superuser:
-                                               portage_group_warning()
-                                       return 1
-
-       disable_emergelog = False
-       for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
-               if x in myopts:
-                       disable_emergelog = True
-                       break
-       if myaction in ("search", "info"):
-               disable_emergelog = True
-       if disable_emergelog:
-               """ Disable emergelog for everything except build or unmerge
-               operations.  This helps minimize parallel emerge.log entries that can
-               confuse log parsers.  We especially want it disabled during
-               parallel-fetch, which uses --resume --fetchonly."""
-               global emergelog
-               def emergelog(*pargs, **kargs):
-                       pass
-
-       if not "--pretend" in myopts:
-               emergelog(xterm_titles, "Started emerge on: "+\
-                       time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
-               myelogstr=""
-               if myopts:
-                       myelogstr=" ".join(myopts)
-               if myaction:
-                       myelogstr+=" "+myaction
-               if myfiles:
-                       myelogstr+=" "+" ".join(myfiles)
-               emergelog(xterm_titles, " *** emerge " + myelogstr)
-
-       def emergeexitsig(signum, frame):
-               signal.signal(signal.SIGINT, signal.SIG_IGN)
-               signal.signal(signal.SIGTERM, signal.SIG_IGN)
-               portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
-               sys.exit(100+signum)
-       signal.signal(signal.SIGINT, emergeexitsig)
-       signal.signal(signal.SIGTERM, emergeexitsig)
-
-       def emergeexit():
-               """This gets out final log message in before we quit."""
-               if "--pretend" not in myopts:
-                       emergelog(xterm_titles, " *** terminating.")
-               if "notitles" not in settings.features:
-                       xtermTitleReset()
-       portage.atexit_register(emergeexit)
-
-       if myaction in ("config", "metadata", "regen", "sync"):
-               if "--pretend" in myopts:
-                       sys.stderr.write(("emerge: The '%s' action does " + \
-                               "not support '--pretend'.\n") % myaction)
-                       return 1
-       if "sync" == myaction:
-               action_sync(settings, trees, mtimedb, myopts, myaction)
-       elif "metadata" == myaction:
-               action_metadata(settings, portdb, myopts)
-       elif myaction=="regen":
-               validate_ebuild_environment(trees)
-               action_regen(settings, portdb)
-       # HELP action
-       elif "config"==myaction:
-               validate_ebuild_environment(trees)
-               action_config(settings, trees, myopts, myfiles)
-       
-       # INFO action
-       elif "info"==myaction:
-               action_info(settings, trees, myopts, myfiles)
-
-       # SEARCH action
-       elif "search"==myaction:
-               validate_ebuild_environment(trees)
-               action_search(settings, portdb, trees["/"]["vartree"],
-                       myopts, myfiles, spinner)
-       elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
-               validate_ebuild_environment(trees)
-               vartree = trees[settings["ROOT"]]["vartree"]
-               if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
-                       mtimedb["ldpath"]):
-                       if "--pretend" not in myopts:
-                               post_emerge(settings, mtimedb, 0)
-
-       elif "depclean"==myaction:
-               validate_ebuild_environment(trees)
-               action_depclean(settings, trees, mtimedb["ldpath"],
-                       myopts, spinner)
-               if "--pretend" not in myopts:
-                       post_emerge(settings, mtimedb, 0)
-       # "update", "system", or just process files:
-       else:
-               validate_ebuild_environment(trees)
-               action_build(settings, trees, mtimedb,
-                       myopts, myaction, myfiles, spinner)
-               if "--pretend" not in myopts:
-                       post_emerge(settings, mtimedb, 0)
+       import emerge
 
 if __name__ == "__main__":
-       retval = emerge_main()
-       sys.exit(retval)
+       import sys
+       sys.exit(emerge.emerge_main())
index 123faf4809debe6197e7e2a3d84691d19ca63174..08b11d8b5d99126efbb9a6fb995cde4214a17555 100644 (file)
-# To emulate old behavior, import everything from the normal emerge script
-import imp
-emerge = imp.load_source("emerge", "/usr/bin/emerge")
-from emerge import *
-del emerge, imp
+#!/usr/bin/python -O
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: emerge 5976 2007-02-17 09:14:53Z genone $
+
+import sys
+# This block ensures that ^C interrupts are handled quietly.
+try:
+       import signal
+
+       def exithandler(signum,frame):
+               signal.signal(signal.SIGINT, signal.SIG_IGN)
+               signal.signal(signal.SIGTERM, signal.SIG_IGN)
+               sys.exit(1)
+       
+       signal.signal(signal.SIGINT, exithandler)
+       signal.signal(signal.SIGTERM, exithandler)
+       signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+except KeyboardInterrupt:
+       sys.exit(1)
+
+import os, stat
+
+os.environ["PORTAGE_LEGACY_GLOBALS"] = "false"
+try:
+       import portage
+except ImportError:
+       from os import path as osp
+       sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+       import portage
+del os.environ["PORTAGE_LEGACY_GLOBALS"]
+from portage import digraph, portdbapi
+from portage.const import NEWS_LIB_PATH
+
+import emerge.help
+import portage.xpak, commands, errno, re, socket, time, types
+import output
+from portage.output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
+       havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
+       xtermTitleReset, yellow
+from portage.output import create_color_func
+good = create_color_func("GOOD")
+bad = create_color_func("BAD")
+
+import portage.dep
+portage.dep._dep_check_strict = True
+import portage.util
+import portage.locks
+import portage.exception
+from portage.data import secpass
+from portage.util import normalize_path as normpath
+
+if not hasattr(__builtins__, "set"):
+       from sets import Set as set
+from itertools import chain, izip
+from UserDict import DictMixin
+
+try:
+       import cPickle
+except ImportError:
+       import pickle as cPickle
+
+class stdout_spinner(object):
+       scroll_msgs = [
+               "Gentoo Rocks ("+os.uname()[0]+")",
+               "Thank you for using Gentoo. :)",
+               "Are you actually trying to read this?",
+               "How many times have you stared at this?",
+               "We are generating the cache right now",
+               "You are paying too much attention.",
+               "A theory is better than its explanation.",
+               "Phasers locked on target, Captain.",
+               "Thrashing is just virtual crashing.",
+               "To be is to program.",
+               "Real Users hate Real Programmers.",
+               "When all else fails, read the instructions.",
+               "Functionality breeds Contempt.",
+               "The future lies ahead.",
+               "3.1415926535897932384626433832795028841971694",
+               "Sometimes insanity is the only alternative.",
+               "Inaccuracy saves a world of explanation.",
+       ]
+
+       twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
+
+       def __init__(self):
+               self.spinpos = 0
+               self.update = self.update_twirl
+               self.scroll_sequence = self.scroll_msgs[
+                       int(time.time() * 100) % len(self.scroll_msgs)]
+
+       def update_basic(self):
+               self.spinpos = (self.spinpos + 1) % 500
+               if (self.spinpos % 100) == 0:
+                       if self.spinpos == 0:
+                               sys.stdout.write(". ")
+                       else:
+                               sys.stdout.write(".")
+               sys.stdout.flush()
+
+       def update_scroll(self):
+               if(self.spinpos >= len(self.scroll_sequence)):
+                       sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
+                               len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
+               else:
+                       sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
+               sys.stdout.flush()
+               self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
+
+       def update_twirl(self):
+               self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
+               sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
+               sys.stdout.flush()
+
+       def update_quiet(self):
+               return
+
+def userquery(prompt, responses=None, colours=None):
+       """Displays a prompt and a set of responses, then waits for a response
+       which is checked against the responses and the first to match is
+       returned.  An empty response will match the first value in responses.  The
+       input buffer is *not* cleared prior to the prompt!
+
+       prompt: a String.
+       responses: a List of Strings.
+       colours: a List of Functions taking and returning a String, used to
+       process the responses for display. Typically these will be functions
+       like red() but could be e.g. lambda x: "DisplayString".
+       If responses is omitted, defaults to ["Yes", "No"], [green, red].
+       If only colours is omitted, defaults to [bold, ...].
+
+       Returns a member of the List responses. (If called without optional
+       arguments, returns "Yes" or "No".)
+       KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
+       printed."""
+       if responses is None:
+               responses, colours = ["Yes", "No"], [green, red]
+       elif colours is None:
+               colours=[bold]
+       colours=(colours*len(responses))[:len(responses)]
+       print bold(prompt),
+       try:
+               while True:
+                       response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
+                       for key in responses:
+                               # An empty response will match the first value in responses.
+                               if response.upper()==key[:len(response)].upper():
+                                       return key
+                       print "Sorry, response '%s' not understood." % response,
+       except (EOFError, KeyboardInterrupt):
+               print "Interrupted."
+               sys.exit(1)
+
+def sorted_versions(verlist):
+       ret = []
+       for ver in verlist:
+               verparts = ver.split("-")
+               if len(verparts) == 2:
+                       verrev = int(verparts[1][1:])
+               else:
+                       verrev = 0
+               x = 0
+               while x < len(ret):
+                       retparts = ret[x].split("-")
+                       verdiff = portage.vercmp(retparts[0], verparts[0])
+                       if verdiff > 0:
+                               break
+                       elif verdiff == 0:
+                               if len(retparts) == 2:
+                                       retrev = int(retparts[1][1:])
+                               else:
+                                       retrev = 0
+                               if retrev >= verrev:
+                                       break
+                       x += 1
+               ret.insert(x, ver)
+       return ret
+
+
+actions=[
+"clean", "config", "depclean",
+"info", "metadata",
+"prune", "regen",  "search",
+"sync",  "system", "unmerge",  "world",
+]
+options=[
+"--ask",          "--alphabetical",
+"--buildpkg",     "--buildpkgonly",
+"--changelog",    "--columns",
+"--debug",        "--deep",
+"--digest",
+"--emptytree",
+"--fetchonly",    "--fetch-all-uri",
+"--getbinpkg",    "--getbinpkgonly",
+"--help",         "--ignore-default-opts",
+"--noconfmem",
+"--newuse",       "--nocolor",
+"--nodeps",       "--noreplace",
+"--nospinner",    "--oneshot",
+"--onlydeps",     "--pretend",
+"--quiet",        "--resume",
+"--searchdesc",   "--selective",
+"--skipfirst",
+"--tree",
+"--update",
+"--usepkg",       "--usepkgonly",
+"--verbose",      "--version"
+]
+
+shortmapping={
+"1":"--oneshot",
+"a":"--ask",
+"b":"--buildpkg",  "B":"--buildpkgonly",
+"c":"--clean",     "C":"--unmerge",
+"d":"--debug",     "D":"--deep",
+"e":"--emptytree",
+"f":"--fetchonly", "F":"--fetch-all-uri",
+"g":"--getbinpkg", "G":"--getbinpkgonly",
+"h":"--help",
+"k":"--usepkg",    "K":"--usepkgonly",
+"l":"--changelog",
+"n":"--noreplace", "N":"--newuse",
+"o":"--onlydeps",  "O":"--nodeps",
+"p":"--pretend",   "P":"--prune",
+"q":"--quiet",
+"s":"--search",    "S":"--searchdesc",
+'t':"--tree",
+"u":"--update",
+"v":"--verbose",   "V":"--version"
+}
+
+def emergelog(xterm_titles, mystr, short_msg=None):
+       if xterm_titles:
+               if short_msg == None:
+                       short_msg = mystr
+               if "HOSTNAME" in os.environ.keys():
+                       short_msg = os.environ["HOSTNAME"]+": "+short_msg
+               xtermTitle(short_msg)
+       try:
+               file_path = "/var/log/emerge.log"
+               mylogfile = open(file_path, "a")
+               portage.util.apply_secpass_permissions(file_path,
+                       uid=portage.portage_uid, gid=portage.portage_gid,
+                       mode=0660)
+               mylock = None
+               try:
+                       mylock = portage.locks.lockfile(mylogfile)
+                       # seek because we may have gotten held up by the lock.
+                       # if so, we may not be positioned at the end of the file.
+                       mylogfile.seek(0, 2)
+                       mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
+                       mylogfile.flush()
+               finally:
+                       if mylock:
+                               portage.locks.unlockfile(mylock)
+                       mylogfile.close()
+       except (IOError,OSError,portage.exception.PortageException), e:
+               if secpass >= 1:
+                       print >> sys.stderr, "emergelog():",e
+
+def countdown(secs=5, doing="Starting"):
+       if secs:
+               print ">>> Waiting",secs,"seconds before starting..."
+               print ">>> (Control-C to abort)...\n"+doing+" in: ",
+               ticks=range(secs)
+               ticks.reverse()
+               for sec in ticks:
+                       sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
+                       sys.stdout.flush()
+                       time.sleep(1)
+               print
+
+# formats a size given in bytes nicely
+def format_size(mysize):
+       if type(mysize) not in [types.IntType,types.LongType]:
+               return str(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 getgccversion(chost):
+       """
+       rtype: C{str}
+       return:  the current in-use gcc version
+       """
+
+       gcc_ver_command = 'gcc -dumpversion'
+       gcc_ver_prefix = 'gcc-'
+
+       gcc_not_found_error = red(
+       "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
+       "!!! to update the environment of this terminal and possibly\n" +
+       "!!! other terminals also.\n"
+       )
+
+       mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
+       if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
+               part1, part2 = myoutput.split("/")
+               if part1.startswith(chost + "-"):
+                       return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
+
+       mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
+       if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
+               return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
+
+       mystatus, myoutput = commands.getstatusoutput(
+               chost + "-" + gcc_ver_command)
+       if mystatus == os.EX_OK:
+               return gcc_ver_prefix + myoutput
+
+       mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
+       if mystatus == os.EX_OK:
+               return gcc_ver_prefix + myoutput
+
+       portage.writemsg(gcc_not_found_error, noiselevel=-1)
+       return "[unavailable]"
+
+def getportageversion(portdir, target_root, profile, chost, vardb):
+       profilever = "unavailable"
+       if profile:
+               realpath = os.path.realpath(profile)
+               basepath   = os.path.realpath(os.path.join(portdir, "profiles"))
+               if realpath.startswith(basepath):
+                       profilever = realpath[1 + len(basepath):]
+               else:
+                       try:
+                               profilever = "!" + os.readlink(profile)
+                       except (OSError):
+                               pass
+               del realpath, basepath
+
+       libcver=[]
+       libclist  = vardb.match("virtual/libc")
+       libclist += vardb.match("virtual/glibc")
+       libclist  = portage.util.unique_array(libclist)
+       for x in libclist:
+               xs=portage.catpkgsplit(x)
+               if libcver:
+                       libcver+=","+"-".join(xs[1:])
+               else:
+                       libcver="-".join(xs[1:])
+       if libcver==[]:
+               libcver="unavailable"
+
+       gccver = getgccversion(chost)
+       unameout=os.uname()[2]+" "+os.uname()[4]
+
+       return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
+
+def create_depgraph_params(myopts, myaction):
+       #configure emerge engine parameters
+       #
+       # self:      include _this_ package regardless of if it is merged.
+       # selective: exclude the package if it is merged
+       # recurse:   go into the dependencies
+       # deep:      go into the dependencies of already merged packages
+       # empty:     pretend nothing is merged
+       myparams = ["recurse"]
+       add=[]
+       sub=[]
+       if "--update" in myopts or \
+               "--newuse" in myopts or \
+               "--noreplace" in myopts or \
+               myaction in ("system", "world"):
+               add.extend(["selective"])
+       if "--emptytree" in myopts:
+               add.extend(["empty"])
+               sub.extend(["selective"])
+       if "--nodeps" in myopts:
+               sub.extend(["recurse"])
+       if "--deep" in myopts:
+               add.extend(["deep"])
+       for x in add:
+               if (x not in myparams) and (x not in sub):
+                       myparams.append(x)
+       for x in sub:
+               if x in myparams:
+                       myparams.remove(x)
+       return myparams
+
+# search functionality
+class search:
+
+       #
+       # class constants
+       #
+       VERSION_SHORT=1
+       VERSION_RELEASE=2
+
+       #
+       # public interface
+       #
+       def __init__(self, settings, portdb, vartree, spinner, searchdesc,
+               verbose):
+               """Searches the available and installed packages for the supplied search key.
+               The list of available and installed packages is created at object instantiation.
+               This makes successive searches faster."""
+               self.settings = settings
+               self.portdb = portdb
+               self.vartree = vartree
+               self.spinner = spinner
+               self.verbose = verbose
+               self.searchdesc = searchdesc
+
+       def execute(self,searchkey):
+               """Performs the search for the supplied search key"""
+               match_category = 0
+               self.searchkey=searchkey
+               self.packagematches = []
+               if self.searchdesc:
+                       self.searchdesc=1
+                       self.matches = {"pkg":[], "desc":[]}
+               else:
+                       self.searchdesc=0
+                       self.matches = {"pkg":[]}
+               print "Searching...   ",
+
+               regexsearch = False
+               if self.searchkey[0] == '%':
+                       regexsearch = True
+                       self.searchkey = self.searchkey[1:]
+               if self.searchkey[0] == '@':
+                       match_category = 1
+                       self.searchkey = self.searchkey[1:]
+               if regexsearch:
+                       self.searchre=re.compile(self.searchkey,re.I)
+               else:
+                       self.searchre=re.compile(re.escape(self.searchkey), re.I)
+               for package in self.portdb.cp_all():
+                       self.spinner.update()
+
+                       if match_category:
+                               match_string  = package[:]
+                       else:
+                               match_string  = package.split("/")[-1]
+
+                       masked=0
+                       if self.searchre.search(match_string):
+                               if not self.portdb.xmatch("match-visible", package):
+                                       masked=1
+                               self.matches["pkg"].append([package,masked])
+                       elif self.searchdesc: # DESCRIPTION searching
+                               full_package = self.portdb.xmatch("bestmatch-visible", package)
+                               if not full_package:
+                                       #no match found; we don't want to query description
+                                       full_package = portage.best(
+                                               self.portdb.xmatch("match-all", package))
+                                       if not full_package:
+                                               continue
+                                       else:
+                                               masked=1
+                               try:
+                                       full_desc = self.portdb.aux_get(
+                                               full_package, ["DESCRIPTION"])[0]
+                               except KeyError:
+                                       print "emerge: search: aux_get() failed, skipping"
+                                       continue
+                               if self.searchre.search(full_desc):
+                                       self.matches["desc"].append([full_package,masked])
+               self.mlen=0
+               for mtype in self.matches.keys():
+                       self.matches[mtype].sort()
+                       self.mlen += len(self.matches[mtype])
+
+       def output(self):
+               """Outputs the results of the search."""
+               print "\b\b  \n[ Results for search key : "+white(self.searchkey)+" ]"
+               print "[ Applications found : "+white(str(self.mlen))+" ]"
+               print " "
+               for mtype in self.matches.keys():
+                       for match,masked in self.matches[mtype]:
+                               if mtype=="pkg":
+                                       catpack=match
+                                       full_package = self.portdb.xmatch(
+                                               "bestmatch-visible", match)
+                                       if not full_package:
+                                               #no match found; we don't want to query description
+                                               masked=1
+                                               full_package = portage.best(
+                                                       self.portdb.xmatch("match-all",match))
+                               else:
+                                       full_package = match
+                                       match        = portage.pkgsplit(match)[0]
+
+                               if full_package:
+                                       try:
+                                               desc, homepage, license = self.portdb.aux_get(
+                                                       full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
+                                       except KeyError:
+                                               print "emerge: search: aux_get() failed, skipping"
+                                               continue
+                                       if masked:
+                                               print green("*")+"  "+white(match)+" "+red("[ Masked ]")
+                                       else:
+                                               print green("*")+"  "+white(match)
+                                       myversion = self.getVersion(full_package, search.VERSION_RELEASE)
+
+                                       mysum = [0,0]
+                                       mycat = match.split("/")[0]
+                                       mypkg = match.split("/")[1]
+                                       mycpv = match + "-" + myversion
+                                       myebuild = self.portdb.findname(mycpv)
+                                       pkgdir = os.path.dirname(myebuild)
+                                       from portage import manifest
+                                       mf = manifest.Manifest(
+                                               pkgdir, self.settings["DISTDIR"])
+                                       fetchlist = self.portdb.getfetchlist(mycpv,
+                                               mysettings=self.settings, all=True)[1]
+                                       try:
+                                               mysum[0] = mf.getDistfilesSize(fetchlist)
+                                               mystr = str(mysum[0]/1024)
+                                               mycount=len(mystr)
+                                               while (mycount > 3):
+                                                       mycount-=3
+                                                       mystr=mystr[:mycount]+","+mystr[mycount:]
+                                               mysum[0]=mystr+" kB"
+                                       except KeyError, e:
+                                               mysum[0] = "Unknown (missing digest for %s)" % str(e)
+
+                                       if self.verbose:
+                                               print "     ", darkgreen("Latest version available:"),myversion
+                                               print "     ", self.getInstallationStatus(mycat+'/'+mypkg)
+                                               print "     ", darkgreen("Size of files:"),mysum[0]
+                                               print "     ", darkgreen("Homepage:")+"     ",homepage
+                                               print "     ", darkgreen("Description:")+"  ",desc
+                                               print "     ", darkgreen("License:")+"      ",license
+                                               print
+               print
+       #
+       # private interface
+       #
+       def getInstallationStatus(self,package):
+               installed_package = self.vartree.dep_bestmatch(package)
+               result = ""
+               version = self.getVersion(installed_package,search.VERSION_RELEASE)
+               if len(version) > 0:
+                       result = darkgreen("Latest version installed:")+" "+version
+               else:
+                       result = darkgreen("Latest version installed:")+" [ Not Installed ]"
+               return result
+
+       def getVersion(self,full_package,detail):
+               if len(full_package) > 1:
+                       package_parts = portage.catpkgsplit(full_package)
+                       if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
+                               result = package_parts[2]+ "-" + package_parts[3]
+                       else:
+                               result = package_parts[2]
+               else:
+                       result = ""
+               return result
+
+
+#build our package digraph
+def getlist(settings, mode):
+       if mode=="system":
+               mylines = settings.packages
+       elif mode=="world":
+               try:
+                       file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
+                       myfile = open(file_path, "r")
+                       mylines = myfile.readlines()
+                       myfile.close()
+               except (OSError, IOError), e:
+                       if e.errno == errno.ENOENT:
+                               portage.writemsg("\n!!! World file does not exist: '%s'\n" % file_path)
+                               mylines=[]
+                       else:
+                               raise
+       mynewlines=[]
+       for x in mylines:
+               myline=" ".join(x.split())
+               if not len(myline):
+                       continue
+               elif myline[0]=="#":
+                       continue
+               elif mode=="system":
+                       if myline[0]!="*":
+                               continue
+                       myline=myline[1:]
+               mynewlines.append(myline.strip())
+
+       return mynewlines
+
+def clean_world(vardb, cpv):
+       """Remove a package from the world file when unmerged."""
+       world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
+       worldlist = portage.util.grabfile(world_filename)
+       mykey = portage.cpv_getkey(cpv)
+       newworldlist = []
+       for x in worldlist:
+               if portage.dep_getkey(x) == mykey:
+                       matches = vardb.match(x, use_cache=0)
+                       if not matches:
+                               #zap our world entry
+                               pass
+                       elif len(matches) == 1 and matches[0] == cpv:
+                               #zap our world entry
+                               pass
+                       else:
+                               #others are around; keep it.
+                               newworldlist.append(x)
+               else:
+                       #this doesn't match the package we're unmerging; keep it.
+                       newworldlist.append(x)
+
+       portage.util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
+               gid=portage.portage_gid, mode=02770)
+       portage.util.write_atomic(world_filename, "\n".join(newworldlist))
+
+def genericdict(mylist):
+       mynewdict={}
+       for x in mylist:
+               mynewdict[portage.dep_getkey(x)]=x
+       return mynewdict
+
+def filter_iuse_defaults(iuse):
+       for flag in iuse:
+               if flag.startswith("+"):
+                       yield flag[1:]
+               else:
+                       yield flag
+
+class DepPriority(object):
+       """
+               This class generates an integer priority level based of various
+               attributes of the dependency relationship.  Attributes can be assigned
+               at any time and the new integer value will be generated on calls to the
+               __int__() method.  Rich comparison operators are supported.
+
+               The boolean attributes that affect the integer value are "satisfied",
+               "buildtime", "runtime", and "system".  Various combinations of
+               attributes lead to the following priority levels:
+
+               Combination of properties    Priority level
+
+               not satisfied and buildtime     0
+               not satisfied and runtime      -1
+               satisfied and buildtime        -2
+               satisfied and runtime          -3
+               (none of the above)            -4
+
+               Several integer constants are defined for categorization of priority
+               levels:
+
+               MEDIUM   The upper boundary for medium dependencies.
+               SOFT     The upper boundary for soft dependencies.
+               MIN      The lower boundary for soft dependencies.
+       """
+       __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime")
+       MEDIUM = -1
+       SOFT   = -2
+       MIN    = -4
+       def __init__(self, **kwargs):
+               for myattr in self.__slots__:
+                       if myattr == "__weakref__":
+                               continue
+                       myvalue = kwargs.get(myattr, False)
+                       setattr(self, myattr, myvalue)
+       def __int__(self):
+               if not self.satisfied:
+                       if self.buildtime:
+                               return 0
+                       if self.runtime:
+                               return -1
+               if self.buildtime:
+                       return -2
+               if self.runtime:
+                       return -3
+               return -4
+       def __lt__(self, other):
+               return self.__int__() < other
+       def __le__(self, other):
+               return self.__int__() <= other
+       def __eq__(self, other):
+               return self.__int__() == other
+       def __ne__(self, other):
+               return self.__int__() != other
+       def __gt__(self, other):
+               return self.__int__() > other
+       def __ge__(self, other):
+               return self.__int__() >= other
+       def copy(self):
+               import copy
+               return copy.copy(self)
+       def __str__(self):
+               myvalue = self.__int__()
+               if myvalue > self.MEDIUM:
+                       return "hard"
+               if myvalue > self.SOFT:
+                       return "medium"
+               return "soft"
+
+class FakeVartree(portage.vartree):
+       """This is implements an in-memory copy of a vartree instance that provides
+       all the interfaces required for use by the depgraph.  The vardb is locked
+       during the constructor call just long enough to read a copy of the
+       installed package information.  This allows the depgraph to do it's
+       dependency calculations without holding a lock on the vardb.  It also
+       allows things like vardb global updates to be done in memory so that the
+       user doesn't necessarily need write access to the vardb in cases where
+       global updates are necessary (updates are performed when necessary if there
+       is not a matching ebuild in the tree)."""
+       def __init__(self, real_vartree, portdb):
+               self.root = real_vartree.root
+               self.settings = real_vartree.settings
+               self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
+               vdb_path = os.path.join(self.root, portage.VDB_PATH)
+               try:
+                       # At least the parent needs to exist for the lock file.
+                       portage.util.ensure_dirs(vdb_path)
+               except portage.exception.PortageException:
+                       pass
+               vdb_lock = None
+               try:
+                       if os.access(vdb_path, os.W_OK):
+                               vdb_lock = portage.locks.lockdir(vdb_path)
+                       mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
+                               "DEPEND", "RDEPEND", "PDEPEND"]
+                       real_dbapi = real_vartree.dbapi
+                       slot_counters = {}
+                       for cpv in real_dbapi.cpv_all():
+                               metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
+                               myslot = metadata["SLOT"]
+                               mycp = portage.dep_getkey(cpv)
+                               myslot_atom = "%s:%s" % (mycp, myslot)
+                               try:
+                                       mycounter = long(metadata["COUNTER"])
+                               except ValueError:
+                                       mycounter = 0
+                                       metadata["COUNTER"] = str(mycounter)
+                               other_counter = slot_counters.get(myslot_atom, None)
+                               if other_counter is not None:
+                                       if other_counter > mycounter:
+                                               continue
+                               slot_counters[myslot_atom] = mycounter
+                               self.dbapi.cpv_inject(cpv, metadata=metadata)
+                       real_dbapi.flush_cache()
+               finally:
+                       if vdb_lock:
+                               portage.locks.unlockdir(vdb_lock)
+               # Populate the old-style virtuals using the cached values.
+               if not self.settings.treeVirtuals:
+                       self.settings.treeVirtuals = portage.util.map_dictlist_vals(
+                               portage.getCPFromCPV, self.get_all_provides())
+
+               # Intialize variables needed for lazy cache pulls of the live ebuild
+               # metadata.  This ensures that the vardb lock is released ASAP, without
+               # being delayed in case cache generation is triggered.
+               self._aux_get = self.dbapi.aux_get
+               self.dbapi.aux_get = self._aux_get_wrapper
+               self._aux_get_history = set()
+               self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
+               self._portdb = portdb
+               self._global_updates = None
+
+       def _aux_get_wrapper(self, pkg, wants):
+               if pkg in self._aux_get_history:
+                       return self._aux_get(pkg, wants)
+               self._aux_get_history.add(pkg)
+               try:
+                       # Use the live ebuild metadata if possible.
+                       live_metadata = dict(izip(self._portdb_keys,
+                               self._portdb.aux_get(pkg, self._portdb_keys)))
+                       self.dbapi.aux_update(pkg, live_metadata)
+               except (KeyError, portage.exception.PortageException):
+                       if self._global_updates is None:
+                               self._global_updates = \
+                                       grab_global_updates(self._portdb.porttree_root)
+                       perform_global_updates(
+                               pkg, self.dbapi, self._global_updates)
+               return self._aux_get(pkg, wants)
+
+def grab_global_updates(portdir):
+       from portage.update import grab_updates, parse_updates
+       updpath = os.path.join(portdir, "profiles", "updates")
+       try:
+               rawupdates = grab_updates(updpath)
+       except portage.exception.DirectoryNotFound:
+               rawupdates = []
+       upd_commands = []
+       for mykey, mystat, mycontent in rawupdates:
+               commands, errors = parse_updates(mycontent)
+               upd_commands.extend(commands)
+       return upd_commands
+
+def perform_global_updates(mycpv, mydb, mycommands):
+       from portage.update import update_dbentries
+       aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
+       aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
+       updates = update_dbentries(mycommands, aux_dict)
+       if updates:
+               mydb.aux_update(mycpv, updates)
+
+class BlockerCache(DictMixin):
+       """This caches blockers of installed packages so that dep_check does not
+       have to be done for every single installed package on every invocation of
+       emerge.  The cache is invalidated whenever it is detected that something
+       has changed that might alter the results of dep_check() calls:
+               1) the set of installed packages (including COUNTER) has changed
+               2) the old-style virtuals have changed
+       """
+       class BlockerData(object):
+               def __init__(self, counter, atoms):
+                       self.counter = counter
+                       self.atoms = atoms
+
+       def __init__(self, myroot, vardb):
+               self._vardb = vardb
+               self._installed_pkgs = set(vardb.cpv_all())
+               self._virtuals = vardb.settings.getvirtuals()
+               self._cache_filename = os.path.join(myroot,
+                       portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
+               self._cache_version = "1"
+               self._cache_data = None
+               self._modified = False
+               self._load()
+
+       def _load(self):
+               try:
+                       f = open(self._cache_filename)
+                       mypickle = cPickle.Unpickler(f)
+                       mypickle.find_global = None
+                       self._cache_data = mypickle.load()
+                       f.close()
+                       del f
+               except (IOError, OSError, EOFError, cPickle.UnpicklingError):
+                       pass
+               cache_valid = self._cache_data and \
+                       isinstance(self._cache_data, dict) and \
+                       self._cache_data.get("version") == self._cache_version and \
+                       self._cache_data.get("virtuals") == self._virtuals and \
+                       set(self._cache_data.get("blockers", [])) == self._installed_pkgs
+               if cache_valid:
+                       for pkg in self._installed_pkgs:
+                               if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
+                                       self[pkg].counter:
+                                       cache_valid = False
+                                       break
+               if not cache_valid:
+                       self._cache_data = {"version":self._cache_version}
+                       self._cache_data["blockers"] = {}
+                       self._cache_data["virtuals"] = self._virtuals
+               self._modified = False
+
+       def flush(self):
+               """If the current user has permission and the internal blocker cache
+               been updated, save it to disk and mark it unmodified.  This is called
+               by emerge after it has proccessed blockers for all installed packages.
+               Currently, the cache is only written if the user has superuser
+               privileges (since that's required to obtain a lock), but all users
+               have read access and benefit from faster blocker lookups (as long as
+               the entire cache is still valid).  The cache is stored as a pickled
+               dict object with the following format:
+
+               {
+                       version : "1",
+                       "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
+                       "virtuals" : vardb.settings.getvirtuals()
+               }
+               """
+               if self._modified and \
+                       secpass >= 2:
+                       try:
+                               f = portage.util.atomic_ofstream(self._cache_filename)
+                               cPickle.dump(self._cache_data, f, -1)
+                               f.close()
+                               portage.util.apply_secpass_permissions(
+                                       self._cache_filename, gid=portage.portage_gid, mode=0644)
+                       except (IOError, OSError), e:
+                               pass
+                       self._modified = False
+
+       def __setitem__(self, cpv, blocker_data):
+               """
+               Update the cache and mark it as modified for a future call to
+               self.flush().
+
+               @param cpv: Package for which to cache blockers.
+               @type cpv: String
+               @param blocker_data: An object with counter and atoms attributes.
+               @type blocker_data: BlockerData
+               """
+               self._cache_data["blockers"][cpv] = \
+                       (blocker_data.counter, blocker_data.atoms)
+               self._modified = True
+
+       def __getitem__(self, cpv):
+               """
+               @rtype: BlockerData
+               @returns: An object with counter and atoms attributes.
+               """
+               return self.BlockerData(*self._cache_data["blockers"][cpv])
+
+def show_invalid_depstring_notice(parent_node, depstring, error_msg):
+
+       from formatter import AbstractFormatter, DumbWriter
+       f = AbstractFormatter(DumbWriter(maxcol=72))
+
+       print "\n\n!!! Invalid or corrupt dependency specification: "
+       print
+       print error_msg
+       print
+       print parent_node
+       print
+       print depstring
+       print
+       p_type, p_root, p_key, p_status = parent_node
+       msg = []
+       if p_status == "nomerge":
+               category, pf = portage.catsplit(p_key)
+               pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
+               msg.append("Portage is unable to process the dependencies of the ")
+               msg.append("'%s' package. " % p_key)
+               msg.append("In order to correct this problem, the package ")
+               msg.append("should be uninstalled, reinstalled, or upgraded. ")
+               msg.append("As a temporary workaround, the --nodeps option can ")
+               msg.append("be used to ignore all dependencies.  For reference, ")
+               msg.append("the problematic dependencies can be found in the ")
+               msg.append("*DEPEND files located in '%s/'." % pkg_location)
+       else:
+               msg.append("This package can not be installed.  ")
+               msg.append("Please notify the '%s' package maintainer " % p_key)
+               msg.append("about this problem.")
+
+       for x in msg:
+               f.add_flowing_data(x)
+       f.end_paragraph(1)
+
+class depgraph:
+
+       pkg_tree_map = {
+               "ebuild":"porttree",
+               "binary":"bintree",
+               "installed":"vartree"}
+
+       def __init__(self, settings, trees, myopts, myparams, spinner):
+               self.settings = settings
+               self.target_root = settings["ROOT"]
+               self.myopts = myopts
+               self.myparams = myparams
+               self.edebug = 0
+               if settings.get("PORTAGE_DEBUG", "") == "1":
+                       self.edebug = 1
+               self.spinner = spinner
+               self.pkgsettings = {}
+               # Maps cpv to digraph node for all nodes added to the graph.
+               self.pkg_node_map = {}
+               # Maps slot atom to digraph node for all nodes added to the graph.
+               self._slot_node_map = {}
+               self.mydbapi = {}
+               self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND"]
+               self.useFlags = {}
+               self.trees = {}
+               for myroot in trees:
+                       self.trees[myroot] = {}
+                       for tree in ("porttree", "bintree"):
+                               self.trees[myroot][tree] = trees[myroot][tree]
+                       self.trees[myroot]["vartree"] = \
+                               FakeVartree(trees[myroot]["vartree"],
+                                       trees[myroot]["porttree"].dbapi)
+                       self.pkgsettings[myroot] = portage.config(
+                               clone=self.trees[myroot]["vartree"].settings)
+                       self.pkg_node_map[myroot] = {}
+                       self._slot_node_map[myroot] = {}
+                       vardb = self.trees[myroot]["vartree"].dbapi
+                       # This fakedbapi instance will model the state that the vdb will
+                       # have after new packages have been installed.
+                       fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
+                       self.mydbapi[myroot] = fakedb
+                       if "--nodeps" not in self.myopts and \
+                               "--buildpkgonly" not in self.myopts:
+                               # --nodeps bypasses this, since it isn't needed in this case
+                               # and the cache pulls might trigger (slow) cache generation.
+                               for pkg in vardb.cpv_all():
+                                       self.spinner.update()
+                                       fakedb.cpv_inject(pkg,
+                                               metadata=dict(izip(self._mydbapi_keys,
+                                               vardb.aux_get(pkg, self._mydbapi_keys))))
+                       del vardb, fakedb
+                       self.useFlags[myroot] = {}
+                       if "--usepkg" in self.myopts:
+                               self.trees[myroot]["bintree"].populate(
+                                       "--getbinpkg" in self.myopts,
+                                       "--getbinpkgonly" in self.myopts)
+               del trees
+
+               self.missingbins=[]
+               self.digraph=portage.digraph()
+               # Tracks simple parent/child relationships (PDEPEND relationships are
+               # not reversed).
+               self._parent_child_digraph = digraph()
+               self.orderedkeys=[]
+               self.outdatedpackages=[]
+               self.args_keys = []
+               self.blocker_digraph = digraph()
+               self.blocker_parents = {}
+               self._slot_collision_info = []
+               # Slot collision nodes are not allowed to block other packages since
+               # blocker validation is only able to account for one package per slot.
+               self._slot_collision_nodes = set()
+               self._altlist_cache = {}
+               self._pprovided_args = []
+
+       def _show_slot_collision_notice(self, packages):
+               """Show an informational message advising the user to mask one of the
+               the packages. In some cases it may be possible to resolve this
+               automatically, but support for backtracking (removal nodes that have
+               already been selected) will be required in order to handle all possible
+               cases."""
+
+               msg = []
+               msg.append("\n!!! Multiple versions within a single " + \
+                       "package slot have been \n")
+               msg.append("!!! pulled into the dependency graph:\n\n")
+               for node, parents in packages:
+                       msg.append(str(node))
+                       if parents:
+                               msg.append(" pulled in by\n")
+                               for parent in parents:
+                                       msg.append("  ")
+                                       msg.append(str(parent))
+                                       msg.append("\n")
+                       else:
+                               msg.append(" (no parents)\n")
+                       msg.append("\n")
+               sys.stderr.write("".join(msg))
+               sys.stderr.flush()
+
+               if "--quiet" in self.myopts:
+                       return
+
+               msg = []
+               msg.append("It may be possible to solve this problem ")
+               msg.append("by using package.mask to prevent one of ")
+               msg.append("those packages from being selected. ")
+               msg.append("However, it is also possible that conflicting ")
+               msg.append("dependencies exist such that they are impossible to ")
+               msg.append("satisfy simultaneously.  If such a conflict exists in ")
+               msg.append("the dependencies of two different packages, then those ")
+               msg.append("packages can not be installed simultaneously.")
+
+               from formatter import AbstractFormatter, DumbWriter
+               f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
+               for x in msg:
+                       f.add_flowing_data(x)
+               f.end_paragraph(1)
+
+               msg = []
+               msg.append("For more information, see MASKED PACKAGES ")
+               msg.append("section in the emerge man page or refer ")
+               msg.append("to the Gentoo Handbook.")
+               for x in msg:
+                       f.add_flowing_data(x)
+               f.end_paragraph(1)
+               f.writer.flush()
+
+       def create(self, mybigkey, myparent=None, addme=1, myuse=None,
+               priority=DepPriority(), rev_dep=False, arg=None):
+               """
+               Fills the digraph with nodes comprised of packages to merge.
+               mybigkey is the package spec of the package to merge.
+               myparent is the package depending on mybigkey ( or None )
+               addme = Should we add this package to the digraph or are we just looking at it's deps?
+                       Think --onlydeps, we need to ignore packages in that case.
+               #stuff to add:
+               #SLOT-aware emerge
+               #IUSE-aware emerge -> USE DEP aware depgraph
+               #"no downgrade" emerge
+               """
+               mytype, myroot, mykey = mybigkey
+               existing_node = None
+               if addme:
+                       existing_node = self.pkg_node_map[myroot].get(mykey)
+               if existing_node:
+                       self._parent_child_digraph.add(existing_node, myparent)
+                       if existing_node != myparent:
+                               # Refuse to make a node depend on itself so that the we don't
+                               # don't create a bogus circular dependency in self.altlist().
+                               if rev_dep and myparent:
+                                       self.digraph.addnode(myparent, existing_node,
+                                               priority=priority)
+                               else:
+                                       self.digraph.addnode(existing_node, myparent,
+                                               priority=priority)
+                       return 1
+               
+               self.spinner.update()
+               if mytype == "blocks":
+                       if myparent and \
+                               "--buildpkgonly" not in self.myopts and \
+                               "--nodeps" not in self.myopts and \
+                               myparent not in self._slot_collision_nodes:
+                               mybigkey[1] = myparent[1]
+                               self.blocker_parents.setdefault(
+                                       tuple(mybigkey), set()).add(myparent)
+                       return 1
+               if not arg and myroot == self.target_root:
+                       arg = portage.best_match_to_list(mykey, self.args_keys)
+               # select the correct /var database that we'll be checking against
+               vardbapi = self.trees[myroot]["vartree"].dbapi
+               portdb = self.trees[myroot]["porttree"].dbapi
+               bindb = self.trees[myroot]["bintree"].dbapi
+               pkgsettings = self.pkgsettings[myroot]
+
+               # if the package is already on the system, we add a "nomerge"
+               # directive, otherwise we add a "merge" directive.
+
+               mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
+
+               if myuse is None:
+                       self.pkgsettings[myroot].setcpv(mykey, mydb=portdb)
+                       myuse = self.pkgsettings[myroot]["USE"].split()
+
+               merging=1
+               if mytype == "installed":
+                       merging = 0
+               if addme and mytype != "installed":
+               # this is where we add the node to the list of packages to merge
+                       if "selective" in self.myparams or not arg:
+                               if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
+                                       merging=0
+
+                       """ If we aren't merging, perform the --newuse check.
+                           If the package has new iuse flags or different use flags then if
+                           --newuse is specified, we need to merge the package. """
+                       if merging==0 and "--newuse" in self.myopts and \
+                               vardbapi.cpv_exists(mykey):
+                               pkgsettings.setcpv(mykey, mydb=mydbapi)
+                               forced_flags = set()
+                               forced_flags.update(pkgsettings.useforce)
+                               forced_flags.update(pkgsettings.usemask)
+                               old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
+                               iuses = set(filter_iuse_defaults(
+                                       mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
+                               old_iuse = set(filter_iuse_defaults(
+                                       vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
+                               if iuses.symmetric_difference(
+                                       old_iuse).difference(forced_flags):
+                                       merging = 1
+                               elif old_iuse.intersection(old_use) != \
+                                       iuses.intersection(myuse):
+                                       merging=1
+
+               if addme and merging == 1:
+                       mybigkey.append("merge")
+               else:
+                       mybigkey.append("nomerge")
+               jbigkey = tuple(mybigkey)
+
+               if addme:
+                       metadata = dict(izip(self._mydbapi_keys,
+                               mydbapi.aux_get(mykey, self._mydbapi_keys)))
+                       if merging == 0 and vardbapi.cpv_exists(mykey):
+                               metadata["USE"] = vardbapi.aux_get(mykey, ["USE"])[0]
+                               myuse = metadata["USE"].split()
+                               metadata["SLOT"] = vardbapi.aux_get(mykey, ["SLOT"])[0]
+                       slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
+                       existing_node = self._slot_node_map[myroot].get(
+                               slot_atom, None)
+                       slot_collision = False
+                       if existing_node:
+                               e_type, myroot, e_cpv, e_status = existing_node
+                               if mykey == e_cpv:
+                                       # The existing node can be reused.
+                                       self._parent_child_digraph.add(existing_node, myparent)
+                                       if rev_dep and myparent:
+                                               ptype, proot, pkey, pstatus = myparent
+                                               self.digraph.addnode(myparent, existing_node,
+                                                       priority=priority)
+                                       else:
+                                               self.digraph.addnode(existing_node, myparent,
+                                                       priority=priority)
+                                       return 1
+                               else:
+                                       # A slot collision has occurred.  Sometimes this coincides
+                                       # with unresolvable blockers, so the slot collision will be
+                                       # shown later if there are no unresolvable blockers.
+                                       e_parents = self._parent_child_digraph.parent_nodes(
+                                               existing_node)
+                                       myparents = []
+                                       if myparent:
+                                               myparents.append(myparent)
+                                       self._slot_collision_info.append(
+                                               ((jbigkey, myparents), (existing_node, e_parents)))
+                                       self._slot_collision_nodes.add(jbigkey)
+                                       slot_collision = True
+
+                       if slot_collision:
+                               # Now add this node to the graph so that self.display()
+                               # can show use flags and --tree portage.output.  This node is
+                               # only being partially added to the graph.  It must not be
+                               # allowed to interfere with the other nodes that have been
+                               # added.  Do not overwrite data for existing nodes in
+                               # self.pkg_node_map and self.mydbapi since that data will
+                               # be used for blocker validation.
+                               self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
+                               self.useFlags[myroot].setdefault(mykey, myuse)
+                               # Even though the graph is now invalid, continue to process
+                               # dependencies so that things like --fetchonly can still
+                               # function despite collisions.
+                       else:
+                               self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
+                               self._slot_node_map[myroot][slot_atom] = jbigkey
+                               self.pkg_node_map[myroot][mykey] = jbigkey
+                               self.useFlags[myroot][mykey] = myuse
+
+                       if rev_dep and myparent:
+                               self.digraph.addnode(myparent, jbigkey,
+                                       priority=priority)
+                       else:
+                               self.digraph.addnode(jbigkey, myparent,
+                                       priority=priority)
+
+               # Do this even when addme is False (--onlydeps) so that the
+               # parent/child relationship is always known in case
+               # self._show_slot_collision_notice() needs to be called later.
+               self._parent_child_digraph.add(jbigkey, myparent)
+
+               """ 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.
+               """
+               if "deep" not in self.myparams and not merging and \
+                       not ("--update" in self.myopts and arg and merging):
+                       return 1
+               elif "recurse" not in self.myparams:
+                       return 1
+
+               """ Check DEPEND/RDEPEND/PDEPEND/SLOT
+               Pull from bintree if it's binary package, porttree if it's ebuild.
+               Binpkg's can be either remote or local. """
+
+               edepend={}
+               depkeys = ["DEPEND","RDEPEND","PDEPEND"]
+               depvalues = mydbapi.aux_get(mykey, depkeys)
+               for i in xrange(len(depkeys)):
+                       edepend[depkeys[i]] = depvalues[i]
+
+               if mytype == "ebuild":
+                       if "--buildpkgonly" in self.myopts:
+                               edepend["RDEPEND"] = ""
+                               edepend["PDEPEND"] = ""
+               if not (arg and "--onlydeps" in self.myopts and \
+                       mytype == "ebuild") and \
+                       self.myopts.get("--with-bdeps", "n") == "n" and \
+                       (mytype == "binary" or mybigkey[3] == "nomerge"):
+                       edepend["DEPEND"] = ""
+
+               """ We have retrieve the dependency information, now we need to recursively
+                   process them.  DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
+               
+               mp = tuple(mybigkey)
+
+               try:
+                       if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
+                               myuse=myuse, priority=DepPriority(buildtime=True),
+                               parent_arg=arg):
+                               return 0
+                       """RDEPEND is soft by definition.  However, in order to ensure
+                       correct merge order, we make it a hard dependency.  Otherwise, a
+                       build time dependency might not be usable due to it's run time
+                       dependencies not being installed yet.
+                       """
+                       if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
+                               myuse=myuse, priority=DepPriority(runtime=True),
+                               parent_arg=arg):
+                               return 0
+                       if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
+                               # Post Depend -- Add to the list without a parent, as it depends
+                               # on a package being present AND must be built after that package.
+                               if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
+                                       myuse=myuse, priority=DepPriority(), rev_deps=True,
+                                       parent_arg=arg):
+                                       return 0
+               except ValueError, e:
+                       pkgs = e.args[0]
+                       portage.writemsg("\n\n!!! An atom in the dependencies " + \
+                               "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
+                       for cpv in pkgs:
+                               portage.writemsg("    %s\n" % cpv, noiselevel=-1)
+                       portage.writemsg("\n", noiselevel=-1)
+                       if mytype == "binary":
+                               portage.writemsg(
+                                       "!!! This binary package cannot be installed: '%s'\n" % \
+                                       mykey, noiselevel=-1)
+                       elif mytype == "ebuild":
+                               myebuild, mylocation = portdb.findname2(mykey)
+                               portage.writemsg("!!! This ebuild cannot be installed: " + \
+                                       "'%s'\n" % myebuild, noiselevel=-1)
+                       portage.writemsg("!!! Please notify the package maintainer " + \
+                               "that atoms must be fully-qualified.\n", noiselevel=-1)
+                       return 0
+               return 1
+
+       def select_files(self,myfiles):
+               "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
+               myfavorites=[]
+               myroot = self.target_root
+               portdb = self.trees[myroot]["porttree"].dbapi
+               bindb = self.trees[myroot]["bintree"].dbapi
+               pkgsettings = self.pkgsettings[myroot]
+               arg_atoms = []
+               def visible(mylist):
+                       matches = portdb.gvisible(portdb.visible(mylist))
+                       return [x for x in mylist \
+                               if x in matches or not portdb.cpv_exists(x)]
+               for x in myfiles:
+                       ext = os.path.splitext(x)[1]
+                       if ext==".tbz2":
+                               if not os.path.exists(x):
+                                       if os.path.exists(
+                                               os.path.join(pkgsettings["PKGDIR"], "All", x)):
+                                               x = os.path.join(pkgsettings["PKGDIR"], "All", x)
+                                       elif os.path.exists(
+                                               os.path.join(pkgsettings["PKGDIR"], x)):
+                                               x = os.path.join(pkgsettings["PKGDIR"], x)
+                                       else:
+                                               print "\n\n!!! Binary package '"+str(x)+"' does not exist."
+                                               print "!!! Please ensure the tbz2 exists as specified.\n"
+                                               sys.exit(1)
+                               mytbz2=portage.xpak.tbz2(x)
+                               mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
+                               if os.path.realpath(x) != \
+                                       os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
+                                       print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
+                                       sys.exit(1)
+                               if not self.create(["binary", myroot, mykey],
+                                       None, "--onlydeps" not in self.myopts):
+                                       return (0,myfavorites)
+                               elif not "--oneshot" in self.myopts:
+                                       myfavorites.append(mykey)
+                       elif ext==".ebuild":
+                               x = os.path.realpath(x)
+                               mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
+                               ebuild_path = portdb.findname(mykey)
+                               if ebuild_path:
+                                       if os.path.realpath(ebuild_path) != x:
+                                               print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
+                                               sys.exit(1)
+                                       if mykey not in portdb.xmatch(
+                                               "match-visible", portage.dep_getkey(mykey)):
+                                               print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
+                                               print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
+                                               print colorize("BAD", "*** page for details.")
+                                               countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
+                                                       "Continuing...")
+                               else:
+                                       raise portage.exception.PackageNotFound(
+                                               "%s is not in a valid portage tree hierarchy or does not exist" % x)
+                               if not self.create(["ebuild", myroot, mykey],
+                                       None, "--onlydeps" not in self.myopts):
+                                       return (0,myfavorites)
+                               elif not "--oneshot" in self.myopts:
+                                       myfavorites.append(mykey)
+                       else:
+                               if not is_valid_package_atom(x):
+                                       portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
+                                               noiselevel=-1)
+                                       portage.writemsg("!!! Please check ebuild(5) for full details.\n")
+                                       portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
+                                       return (0,[])
+                               try:
+                                       mykey = None
+                                       if "--usepkg" in self.myopts:
+                                               mykey = portage.dep_expand(x, mydb=bindb,
+                                                       settings=pkgsettings)
+                                       if (mykey and not mykey.startswith("null/")) or \
+                                               "--usepkgonly" in self.myopts:
+                                               arg_atoms.append((x, mykey))
+                                               continue
+
+                                       mykey = portage.dep_expand(x,
+                                               mydb=portdb, settings=pkgsettings)
+                                       arg_atoms.append((x, mykey))
+                               except ValueError, errpkgs:
+                                       print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous.  Please specify"
+                                       print "!!! one of the following fully-qualified ebuild names instead:\n"
+                                       for i in errpkgs[0]:
+                                               print "    " + green(i)
+                                       print
+                                       sys.exit(1)
+
+               if "--update" in self.myopts:
+                       """Make sure all installed slots are updated when possible. Do this
+                       with --emptytree also, to ensure that all slots are remerged."""
+                       vardb = self.trees[self.target_root]["vartree"].dbapi
+                       greedy_atoms = []
+                       for myarg, myatom in arg_atoms:
+                               greedy_atoms.append((myarg, myatom))
+                               myslots = set()
+                               for cpv in vardb.match(myatom):
+                                       myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
+                               if myslots:
+                                       best_pkgs = []
+                                       if "--usepkg" in self.myopts:
+                                               mymatches = bindb.match(myatom)
+                                               if "--usepkgonly" not in self.myopts:
+                                                       mymatches = visible(mymatches)
+                                               best_pkg = portage.best(mymatches)
+                                               if best_pkg:
+                                                       best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
+                                                       best_pkgs.append(("binary", best_pkg, best_slot))
+                                       if "--usepkgonly" not in self.myopts:
+                                               best_pkg = portage.best(portdb.match(myatom))
+                                               if best_pkg:
+                                                       best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
+                                                       best_pkgs.append(("ebuild", best_pkg, best_slot))
+                                       if best_pkgs:
+                                               best_pkg = portage.best([x[1] for x in best_pkgs])
+                                               best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
+                                               best_slot = best_pkgs[0][2]
+                                               myslots.add(best_slot)
+                               if len(myslots) > 1:
+                                       for myslot in myslots:
+                                               myslot_atom = "%s:%s" % \
+                                                       (portage.dep_getkey(myatom), myslot)
+                                               available = False
+                                               if "--usepkgonly" not in self.myopts and \
+                                                       self.trees[self.target_root][
+                                                       "porttree"].dbapi.match(myslot_atom):
+                                                       available = True
+                                               elif "--usepkg" in self.myopts:
+                                                       mymatches = bindb.match(myslot_atom)
+                                                       if "--usepkgonly" not in self.myopts:
+                                                               mymatches = visible(mymatches)
+                                                       if mymatches:
+                                                               available = True
+                                               if available:
+                                                       greedy_atoms.append((myarg, myslot_atom))
+                       arg_atoms = greedy_atoms
+
+               """ These are used inside self.create() in order to ensure packages
+               that happen to match arguments are not incorrectly marked as nomerge."""
+               self.args_keys = [x[1] for x in arg_atoms]
+               for myarg, myatom in arg_atoms:
+                               try:
+                                       self.mysd = self.select_dep(myroot, myatom, arg=myarg)
+                               except portage.exception.MissingSignature, e:
+                                       portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
+                                       portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
+                                       portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
+                                       portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
+                                       portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
+                                       sys.exit(1)
+                               except portage.exception.InvalidSignature, e:
+                                       portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
+                                       portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
+                                       portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
+                                       portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
+                                       portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
+                                       sys.exit(1)
+                               except SystemExit, e:
+                                       raise # Needed else can't exit
+                               except Exception, e:
+                                       print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
+                                       print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
+                                       raise
+
+                               if not self.mysd:
+                                       return (0,myfavorites)
+                               elif not "--oneshot" in self.myopts:
+                                       mykey = portage.dep_getkey(myatom)
+                                       if mykey not in myfavorites:
+                                               myfavorites.append(mykey)
+
+               missing=0
+               if "--usepkgonly" in self.myopts:
+                       for xs in self.digraph.all_nodes():
+                               if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
+                                       if missing == 0:
+                                               print
+                                       missing += 1
+                                       print "Missing binary for:",xs[2]
+
+               if not self.validate_blockers():
+                       return False, myfavorites
+               
+               # We're true here unless we are missing binaries.
+               return (not missing,myfavorites)
+
+       def select_dep(self, myroot, depstring, myparent=None, arg=None,
+               myuse=None, raise_on_missing=False, priority=DepPriority(),
+               rev_deps=False, parent_arg=None):
+               """ Given a depstring, create the depgraph such that all dependencies are satisfied.
+                   myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
+                   myparent = the node whose depstring is being passed in
+                   arg = package was specified on the command line, merge even if it's already installed
+                   myuse = USE flags at present
+                   raise_on_missing = Given that the depgraph is not proper, raise an exception if true
+                   else continue trying.
+                   return 1 on success, 0 for failure
+               """
+
+               portdb = self.trees[myroot]["porttree"].dbapi
+               bindb  = self.trees[myroot]["bintree"].dbapi
+               vardb  = self.trees[myroot]["vartree"].dbapi
+               pkgsettings = self.pkgsettings[myroot]
+               if myparent:
+                       p_type, p_root, p_key, p_status = myparent
+
+               if "--debug" in self.myopts:
+                       print
+                       print "Parent:   ",myparent
+                       print "Depstring:",depstring
+                       if rev_deps:
+                               print "Reverse:", rev_deps
+                       print "Priority:", priority
+
+               #processing dependencies
+               """ Call portage.dep_check to evaluate the use? conditionals and make sure all
+               dependencies are satisfiable. """
+               try:
+                       if myparent and p_status == "nomerge":
+                               portage.dep._dep_check_strict = False
+                       mycheck = portage.dep_check(depstring, None,
+                               pkgsettings, myuse=myuse,
+                               use_binaries=("--usepkgonly" in self.myopts),
+                               myroot=myroot, trees=self.trees)
+               finally:
+                       portage.dep._dep_check_strict = True
+
+               if not mycheck[0]:
+                       if myparent:
+                               show_invalid_depstring_notice(myparent, depstring, mycheck[1])
+                       else:
+                               sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
+                       return 0
+               mymerge = mycheck[1]
+
+               if not mymerge and arg and \
+                       portage.best_match_to_list(depstring, self.args_keys):
+                       # A provided package has been specified on the command line.  The
+                       # package will not be merged and a warning will be displayed.
+                       self._pprovided_args.append(arg)
+
+               if myparent:
+                       # The parent is added after it's own dep_check call so that it
+                       # isn't allowed to satisfy a direct bootstrap dependency on itself
+                       # via an old-style virtual.  This isn't a problem with new-style
+                       # virtuals, which are preferenced in dep_zapdeps by looking only at
+                       # the depstring, vdb, and available packages.
+
+                       p_type, p_root, p_key, p_status = myparent
+                       if p_status == "merge":
+                               # Update old-style virtuals if this package provides any.
+                               # These are needed for dep_virtual calls inside dep_check.
+                               self.pkgsettings[p_root].setinst(p_key,
+                                       self.trees[p_root][self.pkg_tree_map[p_type]].dbapi)
+
+               if "--debug" in self.myopts:
+                       print "Candidates:",mymerge
+               for x in mymerge:
+                       selected_pkg = None
+                       if x[0]=="!":
+                               selected_pkg = ["blocks", myroot, x[1:], None]
+                       else:
+                               #We are not processing a blocker but a normal dependency
+                               if myparent:
+                                       """In some cases, dep_check will return deps that shouldn't
+                                       be proccessed any further, so they are identified and
+                                       discarded here."""
+                                       if "empty" not in self.myparams and \
+                                               "deep" not in self.myparams and \
+                                               not ("--update" in self.myopts and parent_arg) and \
+                                               vardb.match(x):
+                                               continue
+
+                               # List of acceptable packages, ordered by type preference.
+                               matched_packages = []
+                               myeb_matches = portdb.xmatch("match-visible", x)
+                               myeb = None
+                               if "--usepkgonly" not in self.myopts:
+                                       myeb = portage.best(myeb_matches)
+
+                               myeb_pkg=None
+                               if "--usepkg" in self.myopts:
+                                       # The next line assumes the binarytree has been populated.
+                                       # XXX: Need to work out how we use the binary tree with roots.
+                                       myeb_pkg_matches = bindb.match(x)
+                                       if "--usepkgonly" not in self.myopts:
+                                               # Remove any binary package entries that are masked in the portage tree (#55871)
+                                               myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
+                                                       if pkg in myeb_matches or  \
+                                                       not portdb.cpv_exists(pkg)]
+                                       if myeb_pkg_matches:
+                                               myeb_pkg = portage.best(myeb_pkg_matches)
+
+                               if myeb_pkg and "--newuse" in self.myopts:
+                                       iuses = set(filter_iuse_defaults(
+                                               bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
+                                       old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
+                                       mydb = None
+                                       if "--usepkgonly" not in self.myopts and myeb:
+                                               mydb = portdb
+                                       if myeb:
+                                               pkgsettings.setcpv(myeb, mydb=mydb)
+                                       else:
+                                               pkgsettings.setcpv(myeb_pkg, mydb=mydb)
+                                       now_use = pkgsettings["USE"].split()
+                                       forced_flags = set()
+                                       forced_flags.update(pkgsettings.useforce)
+                                       forced_flags.update(pkgsettings.usemask)
+                                       cur_iuse = iuses
+                                       if "--usepkgonly" not in self.myopts and myeb:
+                                               cur_iuse = set(filter_iuse_defaults(
+                                                       portdb.aux_get(myeb, ["IUSE"])[0].split()))
+                                       if iuses.symmetric_difference(
+                                               cur_iuse).difference(forced_flags):
+                                               myeb_pkg = None
+                                       elif iuses.intersection(old_use) != \
+                                               cur_iuse.intersection(now_use):
+                                               myeb_pkg = None
+                               if myeb_pkg:
+                                       binpkguseflags = \
+                                               self.trees[myroot]["bintree"].dbapi.aux_get(
+                                                       myeb_pkg, ["USE"])[0].split()
+                                       matched_packages.append(
+                                               ["binary", myroot, myeb_pkg, binpkguseflags])
+
+                               if "--usepkgonly" not in self.myopts and myeb_matches:
+                                       matched_packages.append(
+                                               ["ebuild", myroot, myeb, None])
+
+                               if not matched_packages and \
+                                       not (arg and "selective" not in self.myparams):
+                                       """Fall back to the installed package database.  This is a
+                                       last resort because the metadata tends to diverge from that
+                                       of the ebuild in the tree."""
+                                       myeb_inst_matches = vardb.match(x)
+                                       if "--usepkgonly" not in self.myopts:
+                                               """ TODO: Improve masking check for installed and
+                                               binary packages. bug #149816"""
+                                               myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
+                                                       if not portdb.cpv_exists(pkg)]
+                                       myeb_inst = None
+                                       if myeb_inst_matches:
+                                               myeb_inst = portage.best(myeb_inst_matches)
+                                       if myeb_inst:
+                                               binpkguseflags = vardb.aux_get(
+                                                       myeb_inst, ["USE"])[0].split()
+                                               matched_packages.append(
+                                                       ["installed", myroot, myeb_inst, binpkguseflags])
+
+                               if not matched_packages:
+                                       if raise_on_missing:
+                                               raise ValueError
+                                       if not arg:
+                                               xinfo='"'+x+'"'
+                                       else:
+                                               xinfo='"'+arg+'"'
+                                       if myparent:
+                                               xfrom = '(dependency required by '+ \
+                                                       green('"%s"' % myparent[2]) + \
+                                                       red(' [%s]' % myparent[0]) + ')'
+                                       alleb = portdb.xmatch("match-all", x)
+                                       if alleb:
+                                               if "--usepkgonly" not in self.myopts:
+                                                       print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
+                                                       print "!!! One of the following masked packages is required to complete your request:"
+                                                       oldcomment = ""
+                                                       for p in alleb:
+                                                               mreasons = portage.getmaskingstatus(p,
+                                                                       settings=pkgsettings, portdb=portdb)
+                                                               print "- "+p+" (masked by: "+", ".join(mreasons)+")"
+                                                               comment, filename = portage.getmaskingreason(p,
+                                                                       settings=pkgsettings, portdb=portdb, return_location=True)
+                                                               if comment and comment != oldcomment:
+                                                                       print filename+":"
+                                                                       print comment
+                                                                       oldcomment = comment
+                                                       print
+                                                       print "For more information, see MASKED PACKAGES section in the emerge man page or "
+                                                       print "refer to the Gentoo Handbook."
+                                               else:
+                                                       print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
+                                                       print "!!! Either add a suitable binary package or compile from an ebuild."
+                                       else:
+                                               print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
+                                       if myparent:
+                                               print xfrom
+                                       print
+                                       return 0
+
+                               if "--debug" in self.myopts:
+                                       for pkg in matched_packages:
+                                               print (pkg[0] + ":").rjust(10), pkg[2]
+
+                               if len(matched_packages) > 1:
+                                       bestmatch = portage.best(
+                                               [pkg[2] for pkg in matched_packages])
+                                       matched_packages = [pkg for pkg in matched_packages \
+                                               if pkg[2] == bestmatch]
+
+                               # ordered by type preference ("ebuild" type is the last resort)
+                               selected_pkg =  matched_packages[0]
+                               pkgtype, myroot, mycpv, myuse = selected_pkg
+                               mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
+                               slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
+                                       mydbapi.aux_get(mycpv, ["SLOT"])[0])
+                               existing_node = self._slot_node_map[myroot].get(
+                                       slot_atom, None)
+                               if existing_node:
+                                       e_type, myroot, e_cpv, e_status = existing_node
+                                       if portage.match_from_list(x, [e_cpv]):
+                                               # The existing node can be reused.
+                                               selected_pkg = [e_type, myroot, e_cpv,
+                                                       self.useFlags[myroot][e_cpv]]
+
+                       if myparent:
+                               #we are a dependency, so we want to be unconditionally added
+                               mypriority = priority.copy()
+                               if vardb.match(x):
+                                       mypriority.satisfied = True
+                               if not self.create(selected_pkg[0:3], myparent,
+                                       myuse=selected_pkg[-1], priority=mypriority,
+                                       rev_dep=rev_deps, arg=arg):
+                                       return 0
+                       else:
+                               #if mysource is not set, then we are a command-line dependency and should not be added
+                               #if --onlydeps is specified.
+                               if not self.create(selected_pkg[0:3], myparent,
+                                       addme=("--onlydeps" not in self.myopts),
+                                       myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
+                                       return 0
+
+               if "--debug" in self.myopts:
+                       print "Exiting...",myparent
+               return 1
+
+       def validate_blockers(self):
+               """Remove any blockers from the digraph that do not match any of the
+               packages within the graph.  If necessary, create hard deps to ensure
+               correct merge order such that mutually blocking packages are never
+               installed simultaneously."""
+
+               if "--buildpkgonly" in self.myopts or \
+                       "--nodeps" in self.myopts:
+                       return True
+
+               modified_slots = {}
+               for myroot in self.trees:
+                       myslots = {}
+                       modified_slots[myroot] = myslots
+                       final_db = self.mydbapi[myroot]
+                       slot_node_map = self._slot_node_map[myroot]
+                       for slot_atom, mynode in slot_node_map.iteritems():
+                               mytype, myroot, mycpv, mystatus = mynode
+                               if mystatus == "merge":
+                                       myslots[slot_atom] = mycpv
+
+               #if "deep" in self.myparams:
+               if True:
+                       # Pull in blockers from all installed packages that haven't already
+                       # been pulled into the depgraph.  This is not enabled by default
+                       # due to the performance penalty that is incurred by all the
+                       # additional dep_check calls that are required.
+
+                       # Optimization hack for dep_check calls that minimizes the
+                       # available matches by replacing the portdb with a fakedbapi
+                       # instance.
+                       class FakePortageTree(object):
+                               def __init__(self, mydb):
+                                       self.dbapi = mydb
+                       dep_check_trees = {}
+                       for myroot in self.trees:
+                               dep_check_trees[myroot] = self.trees[myroot].copy()
+                               dep_check_trees[myroot]["porttree"] = \
+                                       FakePortageTree(self.mydbapi[myroot])
+
+                       dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
+                       for myroot in self.trees:
+                               pkg_node_map = self.pkg_node_map[myroot]
+                               vardb = self.trees[myroot]["vartree"].dbapi
+                               portdb = self.trees[myroot]["porttree"].dbapi
+                               pkgsettings = self.pkgsettings[myroot]
+                               final_db = self.mydbapi[myroot]
+                               cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
+                               blocker_cache = BlockerCache(myroot, vardb)
+                               for pkg in cpv_all_installed:
+                                       blocker_atoms = None
+                                       matching_node = pkg_node_map.get(pkg, None)
+                                       if matching_node and \
+                                               matching_node[3] == "nomerge":
+                                               continue
+                                       # If this node has any blockers, create a "nomerge"
+                                       # node for it so that they can be enforced.
+                                       self.spinner.update()
+                                       blocker_data = blocker_cache.get(pkg)
+                                       if blocker_data:
+                                               blocker_atoms = blocker_data.atoms
+                                       else:
+                                               dep_vals = vardb.aux_get(pkg, dep_keys)
+                                               myuse = vardb.aux_get(pkg, ["USE"])[0].split()
+                                               depstr = " ".join(dep_vals)
+                                               # It is crucial to pass in final_db here in order to
+                                               # optimize dep_check calls by eliminating atoms via
+                                               # dep_wordreduce and dep_eval calls.
+                                               try:
+                                                       portage.dep._dep_check_strict = False
+                                                       try:
+                                                               success, atoms = portage.dep_check(depstr,
+                                                                       final_db, pkgsettings, myuse=myuse,
+                                                                       trees=dep_check_trees, myroot=myroot)
+                                                       except Exception, e:
+                                                               if isinstance(e, SystemExit):
+                                                                       raise
+                                                               # This is helpful, for example, if a ValueError
+                                                               # is thrown from cpv_expand due to multiple
+                                                               # matches (this can happen if an atom lacks a
+                                                               # category).
+                                                               show_invalid_depstring_notice(
+                                                                       ("installed", myroot, pkg, "nomerge"),
+                                                                       depstr, str(e))
+                                                               del e
+                                                               raise
+                                               finally:
+                                                       portage.dep._dep_check_strict = True
+                                               if not success:
+                                                       slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
+                                                               vardb.aux_get(pkg, ["SLOT"])[0])
+                                                       if slot_atom in modified_slots[myroot]:
+                                                               # This package is being replaced anyway, so
+                                                               # ignore invalid dependencies so as not to
+                                                               # annoy the user too much (otherwise they'd be
+                                                               # forced to manually unmerge it first).
+                                                               continue
+                                                       show_invalid_depstring_notice(
+                                                               ("installed", myroot, pkg, "nomerge"),
+                                                               depstr, atoms)
+                                                       return False
+                                               blocker_atoms = [myatom for myatom in atoms \
+                                                       if myatom.startswith("!")]
+                                               counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
+                                               blocker_cache[pkg] = \
+                                                       blocker_cache.BlockerData(counter, blocker_atoms)
+                                       if blocker_atoms:
+                                               # Don't store this parent in pkg_node_map, because it's
+                                               # not needed there and it might overwrite a "merge"
+                                               # node with the same cpv.
+                                               myparent = ("installed", myroot, pkg, "nomerge")
+                                               for myatom in blocker_atoms:
+                                                       blocker = ("blocks", myroot, myatom[1:])
+                                                       myparents = \
+                                                               self.blocker_parents.get(blocker, None)
+                                                       if not myparents:
+                                                               myparents = set()
+                                                               self.blocker_parents[blocker] = myparents
+                                                       myparents.add(myparent)
+                               blocker_cache.flush()
+                               del blocker_cache
+
+               for blocker in self.blocker_parents.keys():
+                       mytype, myroot, mydep = blocker
+                       initial_db = self.trees[myroot]["vartree"].dbapi
+                       final_db = self.mydbapi[myroot]
+                       blocked_initial = initial_db.match(mydep)
+                       blocked_final = final_db.match(mydep)
+                       if not blocked_initial and not blocked_final:
+                               del self.blocker_parents[blocker]
+                               continue
+                       blocked_slots_initial = {}
+                       blocked_slots_final = {}
+                       for cpv in blocked_initial:
+                               blocked_slots_initial[cpv] = \
+                                       "%s:%s" % (portage.dep_getkey(cpv),
+                                               initial_db.aux_get(cpv, ["SLOT"])[0])
+                       for cpv in blocked_final:
+                               blocked_slots_final[cpv] = \
+                                       "%s:%s" % (portage.dep_getkey(cpv),
+                                               final_db.aux_get(cpv, ["SLOT"])[0])
+                       blocked_slots_final_values = set(blocked_slots_final.itervalues())
+                       for parent in list(self.blocker_parents[blocker]):
+                               ptype, proot, pcpv, pstatus = parent
+                               pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
+                               pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
+                               pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
+                               parent_static = pslot_atom not in modified_slots[proot]
+                               unresolved_blocks = False
+                               depends_on_order = set()
+                               for cpv in blocked_initial:
+                                       slot_atom = blocked_slots_initial[cpv]
+                                       if slot_atom == pslot_atom:
+                                               # The parent blocks an initial package in the same
+                                               # slot as itself.  The merge/nomerge status of neither
+                                               # node matters.  In any case, this particular block is
+                                               # automatically resolved.
+                                               continue
+                                       if parent_static and \
+                                               slot_atom not in modified_slots[myroot]:
+                                               # This blocker will be handled the next time that a
+                                               # merge of either package is triggered.
+                                               continue
+                                       if pstatus == "merge" and \
+                                               slot_atom not in blocked_slots_final_values:
+                                               upgrade_matches = final_db.match(slot_atom)
+                                               if upgrade_matches:
+                                                       # Apparently an upgrade may be able to invalidate
+                                                       # this block.
+                                                       upgrade_node = \
+                                                               self.pkg_node_map[proot][upgrade_matches[0]]
+                                                       depends_on_order.add(upgrade_node)
+                                                       continue
+                                       # None of the above blocker resolutions techniques apply,
+                                       # so apparently this one is unresolvable.
+                                       unresolved_blocks = True
+                               for cpv in blocked_final:
+                                       slot_atom = blocked_slots_final[cpv]
+                                       if slot_atom == pslot_atom:
+                                               # The parent blocks itself, so the merge order does not
+                                               # need to be enforced.
+                                               continue
+                                       if parent_static and \
+                                               slot_atom not in modified_slots[myroot]:
+                                               # This blocker will be handled the next time that a
+                                               # merge of either package is triggered.
+                                               continue
+                                       # None of the above blocker resolutions techniques apply,
+                                       # so apparently this one is unresolvable.
+                                       unresolved_blocks = True
+                               if not unresolved_blocks and depends_on_order:
+                                       for node in depends_on_order:
+                                               # Enforce correct merge order with a hard dep.
+                                               self.digraph.addnode(node, parent,
+                                                       priority=DepPriority(buildtime=True))
+                                               # Count references to this blocker so that it can be
+                                               # invalidated after nodes referencing it have been
+                                               # merged.
+                                               self.blocker_digraph.addnode(node, blocker)
+                               if not unresolved_blocks and not depends_on_order:
+                                       self.blocker_parents[blocker].remove(parent)
+                       if not self.blocker_parents[blocker]:
+                               del self.blocker_parents[blocker]
+               # Validate blockers that depend on merge order.
+               if not self.blocker_digraph.empty():
+                       self.altlist()
+               if self._slot_collision_info:
+                       # The user is only notified of a slot collision if there are no
+                       # unresolvable blocks.
+                       for x in self.altlist():
+                               if x[0] == "blocks":
+                                       return True
+                       self._show_slot_collision_notice(self._slot_collision_info[0])
+                       if not self._accept_collisions():
+                               return False
+               return True
+
+       def _accept_collisions(self):
+               acceptable = False
+               for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
+                       if x in self.myopts:
+                               acceptable = True
+                               break
+               return acceptable
+
+       def altlist(self, reversed=False):
+               if reversed in self._altlist_cache:
+                       return self._altlist_cache[reversed][:]
+               if reversed:
+                       retlist = self.altlist()
+                       retlist.reverse()
+                       self._altlist_cache[reversed] = retlist[:]
+                       return retlist
+               mygraph=self.digraph.copy()
+               myblockers = self.blocker_digraph.copy()
+               retlist=[]
+               circular_blocks = False
+               blocker_deps = None
+               asap_nodes = []
+               if reversed:
+                       get_nodes = mygraph.root_nodes
+               else:
+                       get_nodes = mygraph.leaf_nodes
+                       for cpv, node in self.pkg_node_map["/"].iteritems():
+                               if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
+                                       asap_nodes.append(node)
+                                       break
+               ignore_priority_range = [None]
+               ignore_priority_range.extend(
+                       xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
+               tree_mode = "--tree" in self.myopts
+               while not mygraph.empty():
+                       ignore_priority = None
+                       nodes = None
+                       if asap_nodes:
+                               """ASAP nodes are merged before their soft deps."""
+                               for node in asap_nodes:
+                                       if not mygraph.contains(node):
+                                               asap_nodes.remove(node)
+                                               continue
+                                       if not mygraph.child_nodes(node,
+                                               ignore_priority=DepPriority.SOFT):
+                                               nodes = [node]
+                                               asap_nodes.remove(node)
+                                               break
+                       if not nodes:
+                               for ignore_priority in ignore_priority_range:
+                                       nodes = get_nodes(ignore_priority=ignore_priority)
+                                       if nodes:
+                                               break
+                       selected_nodes = None
+                       if nodes:
+                               if ignore_priority <= DepPriority.SOFT:
+                                       if ignore_priority is None and not tree_mode:
+                                               # Greedily pop all of these nodes since no relationship
+                                               # has been ignored.  This optimization destroys --tree
+                                               # output, so it's disabled in reversed mode.
+                                               selected_nodes = nodes
+                                       else:
+                                               # Only pop one node for optimal merge order.
+                                               selected_nodes = [nodes[0]]
+                               else:
+                                       """Recursively gather a group of nodes that RDEPEND on
+                                       eachother.  This ensures that they are merged as a group
+                                       and get their RDEPENDs satisfied as soon as possible."""
+                                       def gather_deps(mergeable_nodes, selected_nodes, node):
+                                               if node in selected_nodes:
+                                                       return True
+                                               if node not in mergeable_nodes:
+                                                       return False
+                                               selected_nodes.add(node)
+                                               for child in mygraph.child_nodes(node,
+                                                       ignore_priority=DepPriority.SOFT):
+                                                       if not gather_deps(
+                                                               mergeable_nodes, selected_nodes, child):
+                                                               return False
+                                               return True
+                                       mergeable_nodes = set(nodes)
+                                       for node in nodes:
+                                               selected_nodes = set()
+                                               if gather_deps(
+                                                       mergeable_nodes, selected_nodes, node):
+                                                       break
+                                               else:
+                                                       selected_nodes = None
+
+                       if not selected_nodes:
+                               if not myblockers.is_empty():
+                                       """A blocker couldn't be circumnavigated while keeping all
+                                       dependencies satisfied.  The user will have to resolve this
+                                       manually.  This is a panic condition and thus the order
+                                       doesn't really matter, so just pop a random node in order
+                                       to avoid a circular dependency panic if possible."""
+                                       if not circular_blocks:
+                                               circular_blocks = True
+                                               blocker_deps = myblockers.leaf_nodes()
+                                       if blocker_deps:
+                                               selected_nodes = [blocker_deps.pop()]
+
+                       if not selected_nodes:
+                               if reversed:
+                                       """The circular deps ouput should have less noise when
+                                       altlist is not in reversed mode."""
+                                       self.altlist()
+                               print "!!! Error: circular dependencies:"
+                               print
+                               # Reduce the noise level to a minimum via elimination of root
+                               # nodes.
+                               while True:
+                                       root_nodes = mygraph.root_nodes(
+                                               ignore_priority=DepPriority.SOFT)
+                                       if not root_nodes:
+                                               break
+                                       for node in root_nodes:
+                                               mygraph.remove(node)
+                               mygraph.debug_print()
+                               sys.exit(1)
+
+                       for node in selected_nodes:
+                               retlist.append(list(node))
+                               mygraph.remove(node)
+                               if not reversed and not circular_blocks and myblockers.contains(node):
+                                       """This node may have invalidated one or more blockers."""
+                                       myblockers.remove(node)
+                                       for blocker in myblockers.root_nodes():
+                                               if not myblockers.child_nodes(blocker):
+                                                       myblockers.remove(blocker)
+                                                       del self.blocker_parents[blocker]
+
+               if not reversed:
+                       """Blocker validation does not work with reverse mode,
+                       so self.altlist() should first be called with reverse disabled
+                       so that blockers are properly validated."""
+                       self.blocker_digraph = myblockers
+
+               """ Add any unresolved blocks so that they can be displayed."""
+               for blocker in self.blocker_parents:
+                       retlist.append(list(blocker))
+               self._altlist_cache[reversed] = retlist[:]
+               return retlist
+
+       def xcreate(self,mode="system"):
+               vardb = self.trees[self.target_root]["vartree"].dbapi
+               portdb = self.trees[self.target_root]["porttree"].dbapi
+               bindb = self.trees[self.target_root]["bintree"].dbapi
+               def visible(mylist):
+                       matches = portdb.gvisible(portdb.visible(mylist))
+                       return [x for x in mylist \
+                               if x in matches or not portdb.cpv_exists(x)]
+               world_problems = False
+               if mode=="system":
+                       mylist = getlist(self.settings, "system")
+               else:
+                       #world mode
+                       worldlist = getlist(self.settings, "world")
+                       sysdict = genericdict(getlist(self.settings, "system"))
+                       worlddict=genericdict(worldlist)
+
+                       for x in worlddict.keys():
+                               if not portage.isvalidatom(x):
+                                       world_problems = True
+                               elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
+                                       world_problems = True
+                               else:
+                                       sysdict[x]=worlddict[x]
+
+                       mylist = sysdict.keys()
+
+               newlist = []
+               for atom in mylist:
+                       mykey = portage.dep_getkey(atom)
+                       if True:
+                               newlist.append(atom)
+                               """Make sure all installed slots are updated when possible.
+                               Do this with --emptytree also, to ensure that all slots are
+                               remerged."""
+                               myslots = set()
+                               for cpv in vardb.match(mykey):
+                                       myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
+                               if myslots:
+                                       best_pkgs = []
+                                       if "--usepkg" in self.myopts:
+                                               mymatches = bindb.match(atom)
+                                               if "--usepkgonly" not in self.myopts:
+                                                       mymatches = visible(mymatches)
+                                               best_pkg = portage.best(mymatches)
+                                               if best_pkg:
+                                                       best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
+                                                       best_pkgs.append(("binary", best_pkg, best_slot))
+                                       if "--usepkgonly" not in self.myopts:
+                                               best_pkg = portage.best(portdb.match(atom))
+                                               if best_pkg:
+                                                       best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
+                                                       best_pkgs.append(("ebuild", best_pkg, best_slot))
+                                       if best_pkgs:
+                                               best_pkg = portage.best([x[1] for x in best_pkgs])
+                                               best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
+                                               best_slot = best_pkgs[0][2]
+                                               myslots.add(best_slot)
+                               if len(myslots) > 1:
+                                       for myslot in myslots:
+                                               myslot_atom = "%s:%s" % (mykey, myslot)
+                                               available = False
+                                               if "--usepkgonly" not in self.myopts and \
+                                                       self.trees[self.target_root][
+                                                       "porttree"].dbapi.match(myslot_atom):
+                                                       available = True
+                                               elif "--usepkg" in self.myopts:
+                                                       mymatches = bindb.match(myslot_atom)
+                                                       if "--usepkgonly" not in self.myopts:
+                                                               mymatches = visible(mymatches)
+                                                       if mymatches:
+                                                               available = True
+                                               if available:
+                                                       newlist.append(myslot_atom)
+               mylist = newlist
+               
+               missing_atoms = []
+               for mydep in mylist:
+                       try:
+                               if not self.select_dep(
+                                       self.target_root, mydep, raise_on_missing=True, arg=mydep):
+                                       print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
+                                       return 0
+                       except ValueError:
+                               missing_atoms.append(mydep)
+
+               if not self.validate_blockers():
+                       return False
+
+               if world_problems:
+                       print >> sys.stderr, "\n!!! Problems have been detected with your world file"
+                       print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
+
+               if missing_atoms:
+                       print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
+                               " Ebuilds for the following packages are either all"
+                       print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
+                       print >> sys.stderr, " ".join(missing_atoms) + "\n"
+
+               return 1
+
+       def display(self,mylist,verbosity=None):
+               if verbosity is None:
+                       verbosity = ("--quiet" in self.myopts and 1 or \
+                               "--verbose" in self.myopts and 3 or 2)
+               changelogs=[]
+               p=[]
+
+               counters = PackageCounters()
+
+               if verbosity == 1 and "--verbose" not in self.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, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
+                               alphabetical=("--alphabetical" in self.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
+                                       if flag in enabled_flags:
+                                               isEnabled = True
+                                               if is_new or flag in old_use and all_flags:
+                                                       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:
+                                                       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:
+                                                       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
+
+               if verbosity == 3:
+                       # FIXME: account for the possibility of different overlays in
+                       # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
+                       overlays = self.settings["PORTDIR_OVERLAY"].split()
+                       overlays_real = [os.path.realpath(t) \
+                               for t in self.settings["PORTDIR_OVERLAY"].split()]
+
+               tree_nodes = []
+               node_depth = {}
+               i = 0
+               depth = 0
+               for x in mylist:
+                       if "blocks" == x[0]:
+                               continue
+                       graph_key = tuple(x)
+                       if "--tree" in self.myopts:
+                               depth = len(tree_nodes)
+                               while depth and graph_key not in \
+                                       self.digraph.child_nodes(tree_nodes[depth-1]):
+                                               depth -= 1
+                               tree_nodes = tree_nodes[:depth]
+                               tree_nodes.append(graph_key)
+                       node_depth[graph_key] = depth
+
+               last_merge_depth = 0
+               for i in xrange(len(mylist)-1,-1,-1):
+                       if "blocks" == mylist[i][0]:
+                               continue
+                       graph_key = tuple(mylist[i])
+                       if mylist[i][-1] != "nomerge":
+                               last_merge_depth = node_depth[graph_key]
+                               continue
+                       if node_depth[graph_key] >= last_merge_depth or \
+                               i < len(mylist) - 1 and \
+                               node_depth[graph_key] >= node_depth[tuple(mylist[i+1])]:
+                                       del mylist[i]
+                                       del node_depth[graph_key]
+               del tree_nodes
+
+               display_overlays=False
+               # files to fetch list - avoids counting a same file twice
+               # in size display (verbose mode)
+               myfetchlist=[]
+               for x in mylist:
+                       pkg_type = x[0]
+                       myroot = x[1]
+                       pkg_key = x[2]
+                       portdb = self.trees[myroot]["porttree"].dbapi
+                       bindb  = self.trees[myroot]["bintree"].dbapi
+                       vardb = self.trees[myroot]["vartree"].dbapi
+                       vartree = self.trees[myroot]["vartree"]
+                       pkgsettings = self.pkgsettings[myroot]
+
+                       fetch=" "
+
+                       if x[0]=="blocks":
+                               addl=""+red("B")+"  "+fetch+"  "
+                               counters.blocks += 1
+                               resolved = portage.key_expand(
+                                       pkg_key, mydb=vardb, settings=pkgsettings)
+                               if "--columns" in self.myopts and "--quiet" in self.myopts:
+                                       print addl,red(resolved),
+                               else:
+                                       print "["+x[0]+" "+addl+"]",red(resolved),
+                               block_parents = self.blocker_parents[tuple(x)]
+                               block_parents = set([pnode[2] for pnode in block_parents])
+                               block_parents = ", ".join(block_parents)
+                               if resolved!=x[2]:
+                                       print bad("(\"%s\" is blocking %s)") % \
+                                               (pkg_key, block_parents)
+                               else:
+                                       print bad("(is blocking %s)") % block_parents
+                       else:
+                               mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
+                               binary_package = True
+                               if "ebuild" == pkg_type:
+                                       if "merge" == x[3] or \
+                                               not vartree.dbapi.cpv_exists(pkg_key):
+                                               """An ebuild "merge" node or a --onlydeps "nomerge"
+                                               node."""
+                                               binary_package = False
+                                               pkgsettings.setcpv(pkg_key, mydb=portdb)
+                                               if pkg_key not in self.useFlags[myroot]:
+                                                       self.useFlags[myroot][pkg_key] = \
+                                                               pkgsettings["USE"].split()
+                                       else:
+                                               # An ebuild "nomerge" node, so USE come from the vardb.
+                                               mydbapi = vartree.dbapi
+                               if pkg_key not in self.useFlags[myroot]:
+                                       """If this is a --resume then the USE flags need to be
+                                       fetched from the appropriate locations here."""
+                                       self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
+                                               pkg_key, ["USE"])[0].split()
+
+                               if "ebuild" == pkg_type and x[3] != "nomerge" and \
+                                       "fetch" in portdb.aux_get(
+                                       x[2], ["RESTRICT"])[0].split():
+                                       fetch = red("F")
+                                       counters.restrict_fetch += 1
+                                       if portdb.fetch_check(
+                                               pkg_key, self.useFlags[myroot][pkg_key]):
+                                               fetch = green("f")
+                                               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=""
+                               if vardb.cpv_exists(pkg_key):
+                                       addl="  "+yellow("R")+fetch+"  "
+                                       if x[3] != "nomerge":
+                                               counters.reinst += 1
+                               elif vardb.match(portage.dep_getkey(pkg_key)):
+                                       mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
+                                       myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
+                                               portage.pkgsplit(x[2])[0])
+                                       myinslotlist = [inst_pkg for inst_pkg in myoldlist
+                                               if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
+                                       if myinslotlist:
+                                               myoldbest=portage.best(myinslotlist)
+                                               addl="   "+fetch
+                                               if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
+                                                       # Downgrade in slot
+                                                       addl+=turquoise("U")+blue("D")
+                                                       counters.downgrades += 1
+                                               else:
+                                                       # Update in slot
+                                                       addl+=turquoise("U")+" "
+                                                       counters.upgrades += 1
+                                       else:
+                                               # New slot, mark it new.
+                                               addl=" "+green("NS")+fetch+"  "
+                                               counters.newslot += 1
+
+                                       if "--changelog" in self.myopts:
+                                               slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
+                                                       mydbapi.aux_get(pkg_key, ["SLOT"])[0])
+                                               inst_matches = vardb.match(slot_atom)
+                                               if inst_matches:
+                                                       changelogs.extend(self.calc_changelog(
+                                                               portdb.findname(pkg_key),
+                                                               inst_matches[0], pkg_key))
+                               else:
+                                       addl=" "+green("N")+" "+fetch+"  "
+                                       counters.new += 1
+
+                               verboseadd=""
+                               
+                               if pkg_key in self.useFlags[myroot]:
+                                       # USE flag display
+                                       cur_iuse = list(filter_iuse_defaults(
+                                               mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
+
+                                       forced_flags = set()
+                                       if not binary_package:
+                                               forced_flags.update(pkgsettings.useforce)
+                                               forced_flags.update(pkgsettings.usemask)
+
+                                       cur_iuse = portage.unique_array(cur_iuse)
+                                       cur_iuse.sort()
+                                       cur_use = self.useFlags[myroot][pkg_key]
+                                       cur_use = [flag for flag in cur_use if flag in cur_iuse]
+
+                                       if myoldbest:
+                                               pkg = myoldbest
+                                       else:
+                                               pkg = x[2]
+                                       if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
+                                               old_iuse, old_use = \
+                                                       self.trees[x[1]]["vartree"].dbapi.aux_get(
+                                                               pkg, ["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):
+                                               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]
+                                               for exp in use_expand_hidden:
+                                                       if exp in ret:
+                                                               del ret[exp]
+                                               if forcedFlags:
+                                                       return ret, forced
+                                               return ret
+
+                                       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)
+
+                               if verbosity == 3:
+                                       # size verbose
+                                       mysize=0
+                                       if x[0] == "ebuild" and x[-1]!="nomerge":
+                                               try:
+                                                       myfilesdict = portdb.getfetchsizes(pkg_key,
+                                                               useflags=self.useFlags[myroot][pkg_key],
+                                                               debug=self.edebug)
+                                               except portage.exception.InvalidDependString, e:
+                                                       src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
+                                                       show_invalid_depstring_notice(x, src_uri, str(e))
+                                                       del e
+                                                       sys.exit(1)
+                                               if myfilesdict is None:
+                                                       myfilesdict="[empty/missing/bad digest]"
+                                               else:
+                                                       for myfetchfile in myfilesdict.keys():
+                                                               if myfetchfile not in myfetchlist:
+                                                                       mysize+=myfilesdict[myfetchfile]
+                                                                       myfetchlist.append(myfetchfile)
+                                                       counters.totalsize += mysize
+                                               verboseadd+=format_size(mysize)+" "
+
+                                       # overlay verbose
+                                       # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
+                                       # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
+                                       file_name = portdb.findname(pkg_key)
+                                       if file_name: # It might not exist in the tree
+                                               dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
+                                               if (overlays_real.count(dir_name)>0):
+                                                       verboseadd+=teal("["+str(overlays_real.index(
+                                                               os.path.normpath(dir_name))+1)+"]")+" "
+                                                       display_overlays=True
+                                       else:
+                                               verboseadd += "[No ebuild?]"
+
+                               xs=portage.pkgsplit(x[2])
+                               if xs[2]=="r0":
+                                       xs[2]=""
+                               else:
+                                       xs[2]="-"+xs[2]
+
+                               mywidth = 130
+                               if "COLUMNWIDTH" in self.settings:
+                                       try:
+                                               mywidth = int(self.settings["COLUMNWIDTH"])
+                                       except ValueError, e:
+                                               portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
+                                               portage.writemsg(
+                                                       "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
+                                                       self.settings["COLUMNWIDTH"], noiselevel=-1)
+                                               del e
+                               oldlp=mywidth-30
+                               newlp=oldlp-30
+
+                               indent = " " * node_depth[tuple(x)]
+
+                               if myoldbest:
+                                       myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
+                                       if myoldbest[-3:]=="-r0":
+                                               myoldbest=myoldbest[:-3]
+                                       myoldbest=blue("["+myoldbest+"]")
+
+                               if x[1]!="/":
+                                       if myoldbest:
+                                               myoldbest +=" "
+                                       if "--columns" in self.myopts:
+                                               if "--quiet" in self.myopts:
+                                                       myprint=addl+" "+indent+darkgreen(xs[0])
+                                                       myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
+                                                       myprint=myprint+myoldbest
+                                                       myprint=myprint+darkgreen("to "+x[1])
+                                               else:
+                                                       myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
+                                                       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=myprint+darkgreen("to "+x[1])+" "+verboseadd
+                                       else:
+                                               if x[3] == "nomerge":
+                                                       myprint = darkblue("[nomerge      ] ")
+                                               else:
+                                                       myprint = "[" + pkg_type + " " + addl + "] "
+                                               myprint += indent + darkgreen(pkg_key) + " " + \
+                                                       myoldbest + darkgreen("to " + myroot) + " " + \
+                                                       verboseadd
+                               else:
+                                       if "--columns" in self.myopts:
+                                               if "--quiet" in self.myopts:
+                                                       myprint=addl+" "+indent+darkgreen(xs[0])
+                                                       myprint=myprint+" "+green(xs[1]+xs[2])+" "
+                                                       myprint=myprint+myoldbest
+                                               else:
+                                                       myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
+                                                       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=myprint+myoldbest+"  "+verboseadd
+                                       else:
+                                               if x[3]=="nomerge":
+                                                       myprint=darkblue("[nomerge      ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
+                                               else:
+                                                       myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
+                               p.append(myprint)
+
+                       mysplit = portage.pkgsplit(x[2])
+                       if "--tree" not in self.myopts and mysplit and \
+                               len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
+                               x[1] == "/":
+
+                               if mysplit[2] == "r0":
+                                       myversion = mysplit[1]
+                               else:
+                                       myversion = "%s-%s" % (mysplit[1], mysplit[2])
+
+                               if myversion != portage.VERSION and "--quiet" not in self.myopts:
+                                       if mylist.index(x) < len(mylist) - 1 and \
+                                               "livecvsportage" not in self.settings.features:
+                                               p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
+                                               p.append(colorize("WARN", "    then resume the merge."))
+                                               print
+                       del mysplit
+
+               for x in p:
+                       print x
+
+               if verbosity == 3:
+                       print
+                       print counters
+                       if overlays and display_overlays:
+                               print "Portage overlays:"
+                               y=0
+                               for x in overlays:
+                                       y=y+1
+                                       print " "+teal("["+str(y)+"]"),x
+
+               if "--changelog" in self.myopts:
+                       print
+                       for revision,text in changelogs:
+                               print bold('*'+revision)
+                               sys.stdout.write(text)
+
+               if self._pprovided_args:
+                       msg = []
+                       msg.append(bad("\nWARNING: "))
+                       if len(self._pprovided_args) > 1:
+                               msg.append("Requested packages will not be " + \
+                                       "merged because they are listed in\n")
+                       else:
+                               msg.append("A requested package will not be " + \
+                                       "merged because it is listed in\n")
+                       msg.append("         package.provided:\n\n")
+                       for arg in self._pprovided_args:
+                               msg.append("             " + arg + "\n")
+                       msg.append("\n")
+                       sys.stderr.write("".join(msg))
+
+       def calc_changelog(self,ebuildpath,current,next):
+               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 = open(changelogpath).read()
+               except SystemExit, e:
+                       raise # Needed else can't exit
+               except:
+                       return []
+               divisions = self.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(self,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]
+
+       def outdated(self):
+               return self.outdatedpackages
+
+class PackageCounters(object):
+
+       def __init__(self):
+               self.upgrades   = 0
+               self.downgrades = 0
+               self.new        = 0
+               self.newslot    = 0
+               self.reinst     = 0
+               self.blocks     = 0
+               self.totalsize  = 0
+               self.restrict_fetch           = 0
+               self.restrict_fetch_satisfied = 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.blocks > 0:
+                       details.append("%s block" % self.blocks)
+                       if self.blocks > 1:
+                               details[-1] += "s"
+               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))
+               return "".join(myoutput)
+
+class MergeTask(object):
+
+       def __init__(self, settings, trees, myopts):
+               self.settings = settings
+               self.target_root = settings["ROOT"]
+               self.trees = trees
+               self.myopts = myopts
+               self.edebug = 0
+               if settings.get("PORTAGE_DEBUG", "") == "1":
+                       self.edebug = 1
+               self.pkgsettings = {}
+               self.pkgsettings[self.target_root] = portage.config(clone=settings)
+               if self.target_root != "/":
+                       self.pkgsettings["/"] = \
+                               portage.config(clone=trees["/"]["vartree"].settings)
+
+       def merge(self, mylist, favorites, mtimedb):
+               failed_fetches = []
+               mymergelist=[]
+               ldpath_mtimes = mtimedb["ldpath"]
+               xterm_titles = "notitles" not in self.settings.features
+
+               #check for blocking dependencies
+               if "--fetchonly" not in self.myopts and \
+                       "--buildpkgonly" not in self.myopts:
+                       for x in mylist:
+                               if x[0]=="blocks":
+                                       print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
+                                       print   "!!!        the two packages cannot be installed on the same system together."
+                                       print   "!!!        Please use 'emerge --pretend' to determine blockers."
+                                       if "--quiet" not in self.myopts:
+                                               show_blocker_docs_link()
+                                       if "--pretend" not in self.myopts:
+                                               try:
+                                                       del mtimedb["resume"]
+                                               except KeyError:
+                                                       pass
+                                               sys.exit(1)
+
+               #buildsyspkg: I need mysysdict also on resume (moved from the else block)
+               mysysdict = genericdict(getlist(self.settings, "system"))
+               if "--resume" in self.myopts:
+                       # We're resuming.
+                       print colorize("GOOD", "*** Resuming merge...")
+                       emergelog(xterm_titles, " *** Resuming merge...")
+                       mymergelist=mtimedb["resume"]["mergelist"][:]
+                       if "--skipfirst" in self.myopts and mymergelist:
+                               del mtimedb["resume"]["mergelist"][0]
+                               del mymergelist[0]
+                               mtimedb.commit()
+                       validate_merge_list(self.trees, mymergelist)
+               else:
+                       myfavs = portage.grabfile(
+                               os.path.join(self.target_root, portage.WORLD_FILE))
+                       myfavdict=genericdict(myfavs)
+                       for x in range(len(mylist)):
+                               if mylist[x][3]!="nomerge":
+                                       # Add to the mergelist
+                                       mymergelist.append(mylist[x])
+                               else:
+                                       myfavkey=portage.cpv_getkey(mylist[x][2])
+                                       if "--onlydeps" in self.myopts:
+                                               continue
+                                       # Add to the world file. Since we won't be able to later.
+                                       if "--fetchonly" not in self.myopts and \
+                                               myfavkey in favorites:
+                                               #don't record if already in system profile or already recorded
+                                               if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
+                                                       #we don't have a favorites entry for this package yet; add one
+                                                       myfavdict[myfavkey]=myfavkey
+                                                       print ">>> Recording",myfavkey,"in \"world\" favorites file..."
+                       if not ("--fetchonly" in self.myopts or \
+                               "--fetch-all-uri" in self.myopts or \
+                               "--pretend" in self.myopts):
+                               portage.write_atomic(
+                                       os.path.join(self.target_root, portage.WORLD_FILE),
+                                       "\n".join(myfavdict.values()))
+
+                       mtimedb["resume"]["mergelist"]=mymergelist[:]
+                       mtimedb.commit()
+
+               myfeat = self.settings.features[:]
+               bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
+                       "--resume"])
+               if "parallel-fetch" in myfeat and \
+                       not ("--pretend" in self.myopts or \
+                       "--fetch-all-uri" in self.myopts or \
+                       "--fetchonly" in self.myopts):
+                       if "distlocks" not in myfeat:
+                               print red("!!!")
+                               print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
+                               print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
+                               print red("!!!")
+                       elif len(mymergelist) > 1:
+                               print ">>> starting parallel fetching"
+                               fetch_log = "/var/log/emerge-fetch.log"
+                               logfile = open(fetch_log, "w")
+                               fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
+                               portage.util.apply_secpass_permissions(fetch_log,
+                                       uid=portage.portage_uid, gid=portage.portage_gid,
+                                       mode=0660)
+                               fetch_env = os.environ.copy()
+                               fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
+                               fetch_env["PORTAGE_NICENESS"] = "0"
+                               fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
+                               for myopt, myarg in self.myopts.iteritems():
+                                       if myopt not in bad_resume_opts:
+                                               if myarg is True:
+                                                       fetch_args.append(myopt)
+                                               else:
+                                                       fetch_args.append(myopt +"="+ myarg)
+                               portage.process.spawn(fetch_args, env=fetch_env,
+                                       fd_pipes=fd_pipes, returnpid=True)
+                               logfile.close() # belongs to the spawned process
+
+               mergecount=0
+               for x in mymergelist:
+                       mergecount+=1
+                       myroot=x[1]
+                       pkg_key = x[2]
+                       pkgindex=2
+                       portdb = self.trees[myroot]["porttree"].dbapi
+                       bindb  = self.trees[myroot]["bintree"].dbapi
+                       vartree = self.trees[myroot]["vartree"]
+                       pkgsettings = self.pkgsettings[myroot]
+                       if x[0]=="blocks":
+                               pkgindex=3
+                       y = portdb.findname(pkg_key)
+                       if "--pretend" not in self.myopts:
+                               print "\n>>> Emerging (" + \
+                                       colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
+                                       colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
+                                       colorize("GOOD", x[pkgindex]) + " to " + x[1]
+                               emergelog(xterm_titles, " >>> emerge ("+\
+                                       str(mergecount)+" of "+str(len(mymergelist))+\
+                                       ") "+x[pkgindex]+" to "+x[1])
+
+                       pkgsettings["EMERGE_FROM"] = x[0]
+                       pkgsettings.backup_changes("EMERGE_FROM")
+                       pkgsettings.reset()
+
+                       #buildsyspkg: Check if we need to _force_ binary package creation
+                       issyspkg = ("buildsyspkg" in myfeat) \
+                                       and x[0] != "blocks" \
+                                       and mysysdict.has_key(portage.cpv_getkey(x[2])) \
+                                       and "--buildpkg" not in self.myopts
+                       if x[0] in ["ebuild","blocks"]:
+                               if x[0] == "blocks" and "--fetchonly" not in self.myopts:
+                                       raise Exception, "Merging a blocker"
+                               elif "--fetchonly" in self.myopts or \
+                                       "--fetch-all-uri" in self.myopts:
+                                       if "--fetch-all-uri" in self.myopts:
+                                               retval = portage.doebuild(y, "fetch", myroot,
+                                                       pkgsettings, self.edebug,
+                                                       "--pretend" in self.myopts, fetchonly=1,
+                                                       fetchall=1, mydbapi=portdb, tree="porttree")
+                                       else:
+                                               retval = portage.doebuild(y, "fetch", myroot,
+                                                       pkgsettings, self.edebug,
+                                                       "--pretend" in self.myopts, fetchonly=1,
+                                                       mydbapi=portdb, tree="porttree")
+                                       if (retval is None) or retval:
+                                               print
+                                               print "!!! Fetch for",y,"failed, continuing..."
+                                               print
+                                               failed_fetches.append(pkg_key)
+                                       continue
+
+                               portage.doebuild_environment(y, "setup", myroot,
+                                       pkgsettings, self.edebug, 1, portdb)
+                               catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
+                               portage.util.ensure_dirs(os.path.dirname(catdir),
+                                       uid=portage.portage_uid, gid=portage.portage_gid,
+                                       mode=070, mask=0)
+                               builddir_lock = None
+                               catdir_lock = None
+                               try:
+                                       catdir_lock = portage.locks.lockdir(catdir)
+                                       portage.util.ensure_dirs(catdir,
+                                               uid=portage.portage_uid, gid=portage.portage_gid,
+                                               mode=070, mask=0)
+                                       builddir_lock = portage.locks.lockdir(
+                                               pkgsettings["PORTAGE_BUILDDIR"])
+                                       try:
+                                               portage.locks.unlockdir(catdir_lock)
+                                       finally:
+                                               catdir_lock = None
+                                       msg = " === (%s of %s) Cleaning (%s::%s)" % \
+                                               (mergecount, len(mymergelist), pkg_key, y)
+                                       short_msg = "emerge: (%s of %s) %s Clean" % \
+                                               (mergecount, len(mymergelist), pkg_key)
+                                       emergelog(xterm_titles, msg, short_msg=short_msg)
+                                       retval = portage.doebuild(y, "clean", myroot,
+                                               pkgsettings, self.edebug, cleanup=1,
+                                               mydbapi=portdb, tree="porttree")
+                                       if retval != os.EX_OK:
+                                               return retval
+                                       if "--buildpkg" in self.myopts or issyspkg:
+                                               if issyspkg:
+                                                       print ">>> This is a system package, " + \
+                                                               "let's pack a rescue tarball."
+                                               msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
+                                                       (mergecount, len(mymergelist), pkg_key, y)
+                                               short_msg = "emerge: (%s of %s) %s Compile" % \
+                                                       (mergecount, len(mymergelist), pkg_key)
+                                               emergelog(xterm_titles, msg, short_msg=short_msg)
+                                               self.trees[myroot]["bintree"].prevent_collision(pkg_key)
+                                               retval = portage.doebuild(y, "package", myroot,
+                                                       pkgsettings, self.edebug, mydbapi=portdb,
+                                                       tree="porttree")
+                                               if retval != os.EX_OK:
+                                                       return retval
+                                               if "--buildpkgonly" not in self.myopts:
+                                                       bintree = self.trees[myroot]["bintree"]
+                                                       bintree.inject(pkg_key)
+                                                       mytbz2 = bintree.getname(pkg_key)
+                                                       msg = " === (%s of %s) Merging (%s::%s)" % \
+                                                               (mergecount, len(mymergelist), pkg_key, y)
+                                                       short_msg = "emerge: (%s of %s) %s Merge" % \
+                                                               (mergecount, len(mymergelist), pkg_key)
+                                                       emergelog(xterm_titles, msg, short_msg=short_msg)
+                                                       retval = portage.merge(pkgsettings["CATEGORY"],
+                                                               pkgsettings["PF"], pkgsettings["D"],
+                                                               os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
+                                                               "build-info"), myroot, pkgsettings,
+                                                               myebuild=pkgsettings["EBUILD"],
+                                                               mytree="porttree", mydbapi=portdb,
+                                                               vartree=vartree, prev_mtimes=ldpath_mtimes)
+                                                       if retval != os.EX_OK:
+                                                               return retval
+                                               elif "noclean" not in pkgsettings.features:
+                                                       portage.doebuild(y, "clean", myroot,
+                                                               pkgsettings, self.edebug, mydbapi=portdb,
+                                                               tree="porttree")
+                                       else:
+                                               msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
+                                                       (mergecount, len(mymergelist), pkg_key, y)
+                                               short_msg = "emerge: (%s of %s) %s Compile" % \
+                                                       (mergecount, len(mymergelist), pkg_key)
+                                               emergelog(xterm_titles, msg, short_msg=short_msg)
+                                               retval = portage.doebuild(y, "merge", myroot,
+                                                       pkgsettings, self.edebug, vartree=vartree,
+                                                       mydbapi=portdb, tree="porttree",
+                                                       prev_mtimes=ldpath_mtimes)
+                                               if retval != os.EX_OK:
+                                                       return retval
+                               finally:
+                                       if builddir_lock:
+                                               portage.locks.unlockdir(builddir_lock)
+                                       try:
+                                               if not catdir_lock:
+                                                       # Lock catdir for removal if empty.
+                                                       catdir_lock = portage.locks.lockdir(catdir)
+                                       finally:
+                                               if catdir_lock:
+                                                       try:
+                                                               os.rmdir(catdir)
+                                                       except OSError, e:
+                                                               if e.errno not in (errno.ENOENT,
+                                                                       errno.ENOTEMPTY, errno.EEXIST):
+                                                                       raise
+                                                               del e
+                                                       portage.locks.unlockdir(catdir_lock)
+
+                       elif x[0]=="binary":
+                               #merge the tbz2
+                               mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
+                               if "--getbinpkg" in self.myopts:
+                                       tbz2_lock = None
+                                       try:
+                                               if "distlocks" in pkgsettings.features and \
+                                                       os.access(pkgsettings["PKGDIR"], os.W_OK):
+                                                       portage.util.ensure_dirs(os.path.dirname(mytbz2))
+                                                       tbz2_lock = portage.locks.lockfile(mytbz2,
+                                                               wantnewlockfile=1)
+                                               if self.trees[myroot]["bintree"].isremote(pkg_key):
+                                                       msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
+                                                               (mergecount, len(mymergelist), pkg_key, mytbz2)
+                                                       short_msg = "emerge: (%s of %s) %s Fetch" % \
+                                                               (mergecount, len(mymergelist), pkg_key)
+                                                       emergelog(xterm_titles, msg, short_msg=short_msg)
+                                                       if not self.trees[myroot]["bintree"].gettbz2(
+                                                               pkg_key):
+                                                               return 1
+                                       finally:
+                                               if tbz2_lock:
+                                                       portage.locks.unlockfile(tbz2_lock)
+
+                               if "--fetchonly" in self.myopts or \
+                                       "--fetch-all-uri" in self.myopts:
+                                       continue
+
+                               short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
+                               emergelog(xterm_titles, " === ("+str(mergecount)+\
+                                       " of "+str(len(mymergelist))+") Merging Binary ("+\
+                                       x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
+                               retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
+                                       mydbapi=bindb,
+                                       vartree=self.trees[myroot]["vartree"],
+                                       prev_mtimes=ldpath_mtimes)
+                               if retval != os.EX_OK:
+                                       return retval
+                               #need to check for errors
+                       if "--buildpkgonly" not in self.myopts:
+                               self.trees[x[1]]["vartree"].inject(x[2])
+                               myfavkey=portage.cpv_getkey(x[2])
+                               if "--fetchonly" not in self.myopts and \
+                                       "--fetch-all-uri" not in self.myopts and \
+                                       myfavkey in favorites:
+                                       myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
+                                       myfavdict=genericdict(myfavs)
+                                       #don't record if already in system profile or already recorded
+                                       if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
+                                               #we don't have a favorites entry for this package yet; add one
+                                               myfavdict[myfavkey]=myfavkey
+                                               print ">>> Recording",myfavkey,"in \"world\" favorites file..."
+                                               emergelog(xterm_titles, " === ("+\
+                                                       str(mergecount)+" of "+\
+                                                       str(len(mymergelist))+\
+                                                       ") Updating world file ("+x[pkgindex]+")")
+                                               portage.write_atomic(
+                                               os.path.join(myroot, portage.WORLD_FILE),
+                                               "\n".join(myfavdict.values()))
+
+                               if "--pretend" not in self.myopts and \
+                                       "--fetchonly" not in self.myopts and \
+                                       "--fetch-all-uri" not in self.myopts:
+                                       # Clean the old package that we have merged over top of it.
+                                       if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
+                                               xsplit=portage.pkgsplit(x[2])
+                                               emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
+                                               retval = unmerge(pkgsettings, self.myopts, vartree,
+                                                       "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
+                                               if not retval:
+                                                       emergelog(xterm_titles,
+                                                               " --- AUTOCLEAN: Nothing unmerged.")
+                                       else:
+                                               portage.writemsg_stdout(colorize("WARN", "WARNING:")
+                                                       + " AUTOCLEAN is disabled.  This can cause serious"
+                                                       + " problems due to overlapping packages.\n")
+
+                                       # Figure out if we need a restart.
+                                       mysplit=portage.pkgsplit(x[2])
+                                       if mysplit[0] == "sys-apps/portage" and x[1] == "/":
+                                               myver=mysplit[1]+"-"+mysplit[2]
+                                               if myver[-3:]=='-r0':
+                                                       myver=myver[:-3]
+                                               if (myver != portage.VERSION) and \
+                                                  "livecvsportage" not in self.settings.features:
+                                                       if len(mymergelist) > mergecount:
+                                                               emergelog(xterm_titles,
+                                                                       " ::: completed emerge ("+ \
+                                                                       str(mergecount)+" of "+ \
+                                                                       str(len(mymergelist))+") "+ \
+                                                                       x[2]+" to "+x[1])
+                                                               emergelog(xterm_titles, " *** RESTARTING " + \
+                                                                       "emerge via exec() after change of " + \
+                                                                       "portage version.")
+                                                               del mtimedb["resume"]["mergelist"][0]
+                                                               mtimedb.commit()
+                                                               portage.run_exitfuncs()
+                                                               mynewargv=[sys.argv[0],"--resume"]
+                                                               for myopt, myarg in self.myopts.iteritems():
+                                                                       if myopt not in bad_resume_opts:
+                                                                               if myarg is True:
+                                                                                       mynewargv.append(myopt)
+                                                                               else:
+                                                                                       mynewargv.append(myopt +"="+ myarg)
+                                                               # priority only needs to be adjusted on the first run
+                                                               os.environ["PORTAGE_NICENESS"] = "0"
+                                                               os.execv(mynewargv[0], mynewargv)
+
+                       if "--pretend" not in self.myopts and \
+                               "--fetchonly" not in self.myopts and \
+                               "--fetch-all-uri" not in self.myopts:
+                               if "noclean" not in self.settings.features:
+                                       short_msg = "emerge: (%s of %s) %s Clean Post" % \
+                                               (mergecount, len(mymergelist), x[pkgindex])
+                                       emergelog(xterm_titles, (" === (%s of %s) " + \
+                                               "Post-Build Cleaning (%s::%s)") % \
+                                               (mergecount, len(mymergelist), x[pkgindex], y),
+                                               short_msg=short_msg)
+                               emergelog(xterm_titles, " ::: completed emerge ("+\
+                                       str(mergecount)+" of "+str(len(mymergelist))+") "+\
+                                       x[2]+" to "+x[1])
+
+                       # Unsafe for parallel merges
+                       del mtimedb["resume"]["mergelist"][0]
+                       # Commit after each merge so that --resume may still work in
+                       # in the event that portage is not allowed to exit normally
+                       # due to power failure, SIGKILL, etc...
+                       mtimedb.commit()
+
+               if "--pretend" not in self.myopts:
+                       emergelog(xterm_titles, " *** Finished. Cleaning up...")
+
+               # We're out of the loop... We're done. Delete the resume data.
+               if mtimedb.has_key("resume"):
+                       del mtimedb["resume"]
+               mtimedb.commit()
+
+               #by doing an exit this way, --fetchonly can continue to try to
+               #fetch everything even if a particular download fails.
+               if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
+                       if failed_fetches:
+                               sys.stderr.write("\n\n!!! Some fetch errors were " + \
+                                       "encountered.  Please see above for details.\n\n")
+                               for cpv in failed_fetches:
+                                       sys.stderr.write("   ")
+                                       sys.stderr.write(cpv)
+                                       sys.stderr.write("\n")
+                               sys.stderr.write("\n")
+                               sys.exit(1)
+                       else:
+                               sys.exit(0)
+               return os.EX_OK
+
+def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
+       ldpath_mtimes, autoclean=0):
+       candidate_catpkgs=[]
+       global_unmerge=0
+       xterm_titles = "notitles" not in settings.features
+
+       vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
+       try:
+               # At least the parent needs to exist for the lock file.
+               portage.util.ensure_dirs(vdb_path)
+       except portage.exception.PortageException:
+               pass
+       vdb_lock = None
+       try:
+               if os.access(vdb_path, os.W_OK):
+                       vdb_lock = portage.locks.lockdir(vdb_path)
+               realsyslist = getlist(settings, "system")
+               syslist = []
+               for x in realsyslist:
+                       mycp = portage.dep_getkey(x)
+                       if mycp in settings.getvirtuals():
+                               providers = []
+                               for provider in settings.getvirtuals()[mycp]:
+                                       if vartree.dbapi.match(provider):
+                                               providers.append(provider)
+                               if len(providers) == 1:
+                                       syslist.extend(providers)
+                       else:
+                               syslist.append(mycp)
+       
+               mysettings = portage.config(clone=settings)
+       
+               if not unmerge_files or "world" in unmerge_files or \
+                       "system" in unmerge_files:
+                       if "unmerge"==unmerge_action:
+                               print
+                               print bold("emerge unmerge") + " can only be used with " + \
+                                       "specific package names, not with "+bold("world")+" or"
+                               print bold("system")+" targets."
+                               print
+                               return 0
+                       else:
+                               global_unmerge = 1
+       
+               localtree = vartree
+               # process all arguments and add all
+               # valid db entries to candidate_catpkgs
+               if global_unmerge:
+                       if not unmerge_files or "world" in unmerge_files:
+                               candidate_catpkgs.extend(vartree.dbapi.cp_all())
+                       elif "system" in unmerge_files:
+                               candidate_catpkgs.extend(getlist(settings, "system"))
+               else:
+                       #we've got command-line arguments
+                       if not unmerge_files:
+                               print "\nNo packages to unmerge have been provided.\n"
+                               return 0
+                       for x in unmerge_files:
+                               arg_parts = x.split('/')
+                               if x[0] not in [".","/"] and \
+                                       arg_parts[-1][-7:] != ".ebuild":
+                                       #possible cat/pkg or dep; treat as such
+                                       candidate_catpkgs.append(x)
+                               elif unmerge_action in ["prune","clean"]:
+                                       print "\n!!! Prune and clean do not accept individual" + \
+                                               " ebuilds as arguments;\n    skipping.\n"
+                                       continue
+                               else:
+                                       # it appears that the user is specifying an installed
+                                       # ebuild and we're in "unmerge" mode, so it's ok.
+                                       if not os.path.exists(x):
+                                               print "\n!!! The path '"+x+"' doesn't exist.\n"
+                                               return 0
+       
+                                       absx   = os.path.abspath(x)
+                                       sp_absx = absx.split("/")
+                                       if sp_absx[-1][-7:] == ".ebuild":
+                                               del sp_absx[-1]
+                                               absx = "/".join(sp_absx)
+       
+                                       sp_absx_len = len(sp_absx)
+       
+                                       vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
+                                       vdb_len  = len(vdb_path)
+       
+                                       sp_vdb     = vdb_path.split("/")
+                                       sp_vdb_len = len(sp_vdb)
+       
+                                       if not os.path.exists(absx+"/CONTENTS"):
+                                               print "!!! Not a valid db dir: "+str(absx)
+                                               return 0
+       
+                                       if sp_absx_len <= sp_vdb_len:
+                                               # The Path is shorter... so it can't be inside the vdb.
+                                               print sp_absx
+                                               print absx
+                                               print "\n!!!",x,"cannot be inside "+ \
+                                                       vdb_path+"; aborting.\n"
+                                               return 0
+       
+                                       for idx in range(0,sp_vdb_len):
+                                               if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
+                                                       print sp_absx
+                                                       print absx
+                                                       print "\n!!!", x, "is not inside "+\
+                                                               vdb_path+"; aborting.\n"
+                                                       return 0
+       
+                                       print "="+"/".join(sp_absx[sp_vdb_len:])
+                                       candidate_catpkgs.append(
+                                               "="+"/".join(sp_absx[sp_vdb_len:]))
+       
+               newline=""
+               if (not "--quiet" in myopts):
+                       newline="\n"
+               if settings["ROOT"] != "/":
+                       print darkgreen(newline+ \
+                               ">>> Using system located in ROOT tree "+settings["ROOT"])
+               if (("--pretend" in myopts) or ("--ask" in myopts)) and \
+                       not ("--quiet" in myopts):
+                       print darkgreen(newline+\
+                               ">>> These are the packages that would be unmerged:")
+       
+               pkgmap={}
+               numselected=0
+               for x in candidate_catpkgs:
+                       # cycle through all our candidate deps and determine
+                       # what will and will not get unmerged
+                       try:
+                               mymatch=localtree.dep_match(x)
+                       except KeyError:
+                               mymatch=None
+                       except ValueError, errpkgs:
+                               print "\n\n!!! The short ebuild name \"" + \
+                                       x + "\" is ambiguous.  Please specify"
+                               print "!!! one of the following fully-qualified " + \
+                                       "ebuild names instead:\n"
+                               for i in errpkgs[0]:
+                                       print "    " + green(i)
+                               print
+                               sys.exit(1)
+       
+                       if not mymatch and x[0] not in "<>=~":
+                               #add a "=" if missing
+                               mymatch=localtree.dep_match("="+x)
+                       if not mymatch:
+                               portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
+                                       (x, unmerge_action), noiselevel=-1)
+                               continue
+                       mykey = portage.key_expand(
+                               portage.dep_getkey(
+                                       mymatch[0]), mydb=vartree.dbapi, settings=settings)
+                       if not pkgmap.has_key(mykey):
+                               pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
+                       if unmerge_action=="unmerge":
+                                       for y in mymatch:
+                                               if y not in pkgmap[mykey]["selected"]:
+                                                       pkgmap[mykey]["selected"].append(y)
+                                                       numselected=numselected+len(mymatch)
+       
+                       else:
+                               #unmerge_action in ["prune", clean"]
+                               slotmap={}
+                               for mypkg in mymatch:
+                                       if unmerge_action=="clean":
+                                               myslot=localtree.getslot(mypkg)
+                                       else:
+                                               # since we're pruning, we don't care about slots
+                                               # and put all the pkgs in together
+                                               myslot=0
+                                       if not slotmap.has_key(myslot):
+                                               slotmap[myslot]={}
+                                       slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
+                               for myslot in slotmap.keys():
+                                       counterkeys=slotmap[myslot].keys()
+                                       counterkeys.sort()
+                                       if not counterkeys:
+                                               continue
+                                       counterkeys.sort()
+                                       pkgmap[mykey]["protected"].append(
+                                               slotmap[myslot][counterkeys[-1]])
+                                       del counterkeys[-1]
+                                       #be pretty and get them in order of merge:
+                                       for ckey in counterkeys:
+                                               pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
+                                               numselected=numselected+1
+                                       # ok, now the last-merged package
+                                       # is protected, and the rest are selected
+               if global_unmerge and not numselected:
+                       print "\n>>> No outdated packages were found on your system.\n"
+                       return 0
+       
+               if not numselected:
+                       portage.writemsg_stdout(
+                               "\n>>> No packages selected for removal by " + \
+                               unmerge_action + "\n")
+                       return 0
+       finally:
+               if vdb_lock:
+                       portage.locks.unlockdir(vdb_lock)
+       for x in pkgmap.keys():
+               for y in localtree.dep_match(x):
+                       if y not in pkgmap[x]["omitted"] and \
+                          y not in pkgmap[x]["selected"] and \
+                          y not in pkgmap[x]["protected"]:
+                               pkgmap[x]["omitted"].append(y)
+               if global_unmerge and not pkgmap[x]["selected"]:
+                       #avoid cluttering the preview printout with stuff that isn't getting unmerged
+                       continue
+               if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
+                       print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
+                       print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
+                       if "--pretend" not in myopts and "--ask" not in myopts:
+                               countdown(int(settings["EMERGE_WARNING_DELAY"]),
+                                       colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
+               print "\n "+white(x)
+               for mytype in ["selected","protected","omitted"]:
+                       portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
+                       if pkgmap[x][mytype]:
+                               for mypkg in pkgmap[x][mytype]:
+                                       mysplit=portage.catpkgsplit(mypkg)
+                                       if mysplit[3]=="r0":
+                                               myversion=mysplit[2]
+                                       else:
+                                               myversion=mysplit[2]+"-"+mysplit[3]
+                                       if mytype=="selected":
+                                               portage.writemsg_stdout(
+                                                       colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
+                                       else:
+                                               portage.writemsg_stdout(
+                                                       colorize("GOOD", myversion + " "), noiselevel=-1)
+                       else:
+                               portage.writemsg_stdout("none", noiselevel=-1)
+                       portage.writemsg_stdout("\n", noiselevel=-1)
+
+       portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
+               " packages are slated for removal.\n")
+       portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
+                       " and " + colorize("GOOD", "'omitted'") + \
+                       " packages will not be removed.\n\n")
+
+       if "--pretend" in myopts:
+               #we're done... return
+               return 0
+       if "--ask" in myopts:
+               if userquery("Would you like to unmerge these packages?")=="No":
+                       # enter pretend mode for correct formatting of results
+                       myopts["--pretend"] = True
+                       print
+                       print "Quitting."
+                       print
+                       return 0
+       #the real unmerging begins, after a short delay....
+       if not autoclean:
+               countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
+
+       for x in pkgmap.keys():
+               for y in pkgmap[x]["selected"]:
+                       print ">>> Unmerging "+y+"..."
+                       emergelog(xterm_titles, "=== Unmerging... ("+y+")")
+                       mysplit=y.split("/")
+                       #unmerge...
+                       retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
+                               mysettings, unmerge_action not in ["clean","prune"],
+                               vartree=vartree, ldpath_mtimes=ldpath_mtimes)
+                       if retval != os.EX_OK:
+                               emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
+                               ebuild = vartree.dbapi.findname(y)
+                               show_unmerge_failure_message(y, ebuild, retval)
+                               sys.exit(retval)
+                       else:
+                               clean_world(vartree.dbapi, y)
+                               emergelog(xterm_titles, " >>> unmerge success: "+y)
+       return 1
+
+def show_unmerge_failure_message(pkg, ebuild, retval):
+
+       from formatter import AbstractFormatter, DumbWriter
+       f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
+
+       msg = []
+       msg.append("A removal phase of the '%s' package " % pkg)
+       msg.append("has failed with exit value %s.  " % retval)
+       msg.append("The problem occurred while executing ")
+       msg.append("the ebuild located at '%s'.  " % ebuild)
+       msg.append("If necessary, manually remove the ebuild " )
+       msg.append("in order to skip the execution of removal phases.")
+
+       f.end_paragraph(1)
+       for x in msg:
+               f.add_flowing_data(x)
+       f.end_paragraph(1)
+       f.writer.flush()
+
+def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
+
+       print
+       if os.path.exists("/usr/bin/install-info"):
+               regen_infodirs=[]
+               for z in infodirs:
+                       if z=='':
+                               continue
+                       inforoot=normpath(root+z)
+                       if os.path.isdir(inforoot):
+                               infomtime = long(os.stat(inforoot).st_mtime)
+                               if inforoot not in prev_mtimes or \
+                                       prev_mtimes[inforoot] != infomtime:
+                                               regen_infodirs.append(inforoot)
+
+               if not regen_infodirs:
+                       print " "+green("*")+" GNU info directory index is up-to-date."
+               else:
+                       print " "+green("*")+" Regenerating GNU info directory index..."
+
+                       icount=0
+                       badcount=0
+                       for inforoot in regen_infodirs:
+                               if inforoot=='':
+                                       continue
+                               for filename in ("dir", "dir.gz", "dir.bz2"):
+                                       file_path = os.path.join(inforoot, filename)
+                                       try:
+                                               os.rename(file_path, file_path + ".old")
+                                       except OSError, e:
+                                               if e.errno != errno.ENOENT:
+                                                       raise
+                                               del e
+
+                               if not os.path.isdir(inforoot):
+                                       continue
+                               errmsg = ""
+                               file_list = os.listdir(inforoot)
+                               file_list.sort()
+                               for x in file_list:
+                                       if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
+                                               continue
+                                       myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
+                                       existsstr="already exists, for file `"
+                                       if myso!="":
+                                               if re.search(existsstr,myso):
+                                                       # Already exists... Don't increment the count for this.
+                                                       pass
+                                               elif myso[:44]=="install-info: warning: no info dir entry in ":
+                                                       # This info file doesn't contain a DIR-header: install-info produces this
+                                                       # (harmless) warning (the --quiet switch doesn't seem to work).
+                                                       # Don't increment the count for this.
+                                                       pass
+                                               else:
+                                                       badcount=badcount+1
+                                                       errmsg += myso + "\n"
+                                       icount=icount+1
+
+                               #update mtime so we can potentially avoid regenerating.
+                               prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
+
+                       if badcount:
+                               print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
+                               print errmsg
+                       else:
+                               print " "+green("*")+" Processed",icount,"info files."
+
+
+def post_emerge(settings, mtimedb, retval):
+       """
+       Misc. things to run at the end of a merge session.
+       
+       Update Info Files
+       Update Config Files
+       Update News Items
+       Commit mtimeDB
+       Exit Emerge
+       
+       @param settings: Configuration settings (typically portage.settings)
+       @type settings: portage.config()
+       @param mtimedb: The mtimeDB to store data needed across merge invocations
+       @type mtimedb: MtimeDB class instance
+       @param retval: Emerge's return value
+       @type retval: Int
+       @rype: None
+       @returns:
+       1.  Calls sys.exit(retval)
+       """
+       target_root = settings["ROOT"]
+       info_mtimes = mtimedb["info"]
+
+       # Load the most current variables from ${ROOT}/etc/profile.env
+       settings.unlock()
+       settings.regenerate()
+       settings.lock()
+
+       config_protect = settings.get("CONFIG_PROTECT","").split()
+       infodirs = settings.get("INFOPATH","").split(":") + \
+               settings.get("INFODIR","").split(":")
+
+       os.chdir("/")
+
+       emergelog("notitles" not in settings.features,
+               " *** exiting successfully.")
+
+       if "noinfo" not in settings.features:
+               chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
+
+       chk_updated_cfg_files(target_root, config_protect)
+       
+       NEWS_PATH = os.path.join( "metadata", "news" )
+       UNREAD_PATH = os.path.join( target_root, NEWS_LIB_PATH, 'news')
+       porttree = portdbapi( porttree_root = settings["PORTDIR"], mysettings = settings )
+       newsReaderDisplay = False
+       
+       for repo in porttree.getRepositories():
+               unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
+               if unreadItems:
+                       print colorize("WARN", " * IMPORTANT:"),
+                       print "%s news items need reading for repository '%s'." % (unreadItems, repo)
+                       newsReaderDisplay = True
+       
+       if newsReaderDisplay:
+               print colorize("WARN", " *"),
+               print "Use " + colorize("GOOD", "eselect news") + " to read news items."
+       
+       mtimedb.commit()
+       sys.exit(retval)
+
+
+def chk_updated_cfg_files(target_root, config_protect):
+       if config_protect:
+               #number of directories with some protect files in them
+               procount=0
+               for x in config_protect:
+                       x = os.path.join(target_root, x.lstrip(os.path.sep))
+                       try:
+                               mymode = os.lstat(x).st_mode
+                       except OSError:
+                               continue
+                       if stat.S_ISDIR(mymode):
+                               mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
+                       else:
+                               mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
+                                       os.path.split(x.rstrip(os.path.sep))
+                       a = commands.getstatusoutput(mycommand + \
+                               " ! -iname '.*~' ! -iname '.*.bak'")
+                       if a[0] != 0:
+                               print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
+                       else:
+                               files = a[1].split()
+                               if files:
+                                       procount += 1
+                                       print colorize("WARN", " * IMPORTANT:"),
+                                       if stat.S_ISDIR(mymode):
+                                                print "%d config files in '%s' need updating." % \
+                                                       (len(files), x)
+                                       else:
+                                                print "config file '%s' needs updating." % x
+
+               if procount:
+                       #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
+                       print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
+
+def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
+       """
+       Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
+       Returns the number of unread (yet relevent) items.
+       
+       @param root:
+       @type root:
+       @param NEWS_PATH:
+       @type NEWS_PATH:
+       @param UNREAD_PATH:
+       @type UNREAD_PATH:
+       @param repo_id:
+       @type repo_id:
+       @rtype: Integer
+       @returns:
+       1.  The number of unread but relevant news items.
+       
+       """
+       from portage.news import NewsManager
+       manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
+       return manager.getUnreadItems( repo_id, update=True )
+
+def is_valid_package_atom(x):
+       try:
+               testkey = portage.dep_getkey(x)
+       except portage.exception.InvalidData:
+               return False
+       if testkey.startswith("null/"):
+               testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
+       elif "/" not in x:
+               testatom = "cat/"+x
+       else:
+               testatom = x
+       return portage.isvalidatom(testatom)
+
+def validate_merge_list(trees, mergelist):
+       """Validate the list to make sure all the packages are still available.
+       This is needed for --resume."""
+       for (pkg_type, myroot, pkg_key, action) in mergelist:
+               if pkg_type == "binary" and \
+                       not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
+                       pkg_type == "ebuild" and \
+                       not trees[myroot]["porttree"].dbapi.xmatch(
+                       "match-all", "="+pkg_key):
+                       print red("!!! Error: The resume list contains packages that are no longer")
+                       print red("!!!        available to be emerged. Please restart/continue")
+                       print red("!!!        the merge operation manually.")
+                       sys.exit(1)
+
+def show_blocker_docs_link():
+       print
+       print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
+       print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
+       print
+       print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
+       print
+
+def action_sync(settings, trees, mtimedb, myopts, myaction):
+       xterm_titles = "notitles" not in settings.features
+       emergelog(xterm_titles, " === sync")
+       myportdir = settings.get("PORTDIR", None)
+       if not myportdir:
+               sys.stderr.write("!!! PORTDIR is undefined.  Is /etc/make.globals missing?\n")
+               sys.exit(1)
+       if myportdir[-1]=="/":
+               myportdir=myportdir[:-1]
+       if not os.path.exists(myportdir):
+               print ">>>",myportdir,"not found, creating it."
+               os.makedirs(myportdir,0755)
+       syncuri=settings["SYNC"].rstrip()
+       os.umask(0022)
+       updatecache_flg = False
+       if myaction == "metadata":
+               print "skipping sync"
+               updatecache_flg = True
+               tmpservertimestampfile = None
+       elif syncuri[:8]=="rsync://":
+               if not os.path.exists("/usr/bin/rsync"):
+                       print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
+                       print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
+                       sys.exit(1)
+               mytimeout=180
+
+               rsync_opts = []
+
+               if settings["PORTAGE_RSYNC_OPTS"] == "":
+                       portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
+                       rsync_opts.extend([
+                               "--recursive",    # Recurse directories
+                               "--links",        # Consider symlinks
+                               "--safe-links",   # Ignore links outside of tree
+                               "--perms",        # Preserve permissions
+                               "--times",        # Preserive mod times
+                               "--compress",     # Compress the data transmitted
+                               "--force",        # Force deletion on non-empty dirs
+                               "--whole-file",   # Don't do block transfers, only entire files
+                               "--delete",       # Delete files that aren't in the master tree
+                               "--delete-after", # Delete only after everything else is done
+                               "--stats",        # Show final statistics about what was transfered
+                               "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
+                               "--exclude='/distfiles'",   # Exclude distfiles from consideration
+                               "--exclude='/local'",       # Exclude local     from consideration
+                               "--exclude='/packages'",    # Exclude packages  from consideration
+                       ])
+
+               else:
+                       # The below validation is not needed when using the above hardcoded
+                       # defaults.
+
+                       portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
+                       rsync_opts.extend(settings["PORTAGE_RSYNC_OPTS"].split())
+
+                       for opt in ("--recursive", "--times"):
+                               if opt not in rsync_opts:
+                                       portage.writemsg(yellow("WARNING:") + " adding required option " + \
+                                       "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
+                                       rsync_opts.append(opt)
+       
+                       for exclude in ("distfiles", "local", "packages"):
+                               opt = "--exclude=/%s" % exclude
+                               if opt not in rsync_opts:
+                                       portage.writemsg(yellow("WARNING:") + \
+                                       " adding required option %s not included in "  % opt + \
+                                       "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
+                                       rsync_opts.append(opt)
+       
+                       if settings["RSYNC_TIMEOUT"] != "":
+                               portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
+                               "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
+                               try:
+                                       mytimeout = int(settings["RSYNC_TIMEOUT"])
+                                       rsync_opts.append("--timeout=%d" % mytimeout)
+                               except ValueError, e:
+                                       portage.writemsg("!!! %s\n" % str(e))
+       
+                       # TODO: determine options required for official servers
+                       if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
+
+                               def rsync_opt_startswith(opt_prefix):
+                                       for x in rsync_opts:
+                                               if x.startswith(opt_prefix):
+                                                       return True
+                                       return False
+
+                               if not rsync_opt_startswith("--timeout="):
+                                       rsync_opts.append("--timeout=%d" % mytimeout)
+
+                               for opt in ("--compress", "--whole-file"):
+                                       if opt not in rsync_opts:
+                                               portage.writemsg(yellow("WARNING:") + " adding required option " + \
+                                               "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
+                                               rsync_opts.append(opt)
+
+               if "--quiet" in myopts:
+                       rsync_opts.append("--quiet")    # Shut up a lot
+               else:
+                       rsync_opts.append("--verbose")  # Print filelist
+
+               if "--verbose" in myopts:
+                       rsync_opts.append("--progress")  # Progress meter for each file
+
+               if "--debug" in myopts:
+                       rsync_opts.append("--checksum") # Force checksum on all files
+
+               if settings["RSYNC_EXCLUDEFROM"] != "":
+                       portage.writemsg(yellow("WARNING:") + \
+                       " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
+                       "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
+                       if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
+                               rsync_opts.append("--exclude-from=%s" % \
+                               settings["RSYNC_EXCLUDEFROM"])
+                       else:
+                               portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
+                               " but file does not exist.\n")
+
+               if settings["RSYNC_RATELIMIT"] != "":
+                       portage.writemsg(yellow("WARNING:") + \
+                       " usage of RSYNC_RATELIMIT is deprecated, use " + \
+                       "PORTAGE_RSYNC_EXTRA_OPTS instead")
+                       rsync_opts.append("--bwlimit=%s" % \
+                       settings["RSYNC_RATELIMIT"])
+
+               # Real local timestamp file.
+               servertimestampfile = os.path.join(
+                       myportdir, "metadata", "timestamp.chk")
+               # Temporary file for remote server timestamp comparison.
+               tmpservertimestampfile = os.path.join(
+                       settings["PORTAGE_TMPDIR"], "timestamp.chk")
+
+               content = portage.util.grabfile(servertimestampfile)
+               mytimestamp = 0
+               if content:
+                       try:
+                               mytimestamp = time.mktime(time.strptime(content[0],
+                                       "%a, %d %b %Y %H:%M:%S +0000"))
+                       except OverflowError, ValueError:
+                               pass
+               del content
+
+               try:
+                       if settings.has_key("RSYNC_RETRIES"):
+                               print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
+                               maxretries=int(settings["RSYNC_RETRIES"])                               
+                       else:
+                               maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
+               except SystemExit, e:
+                       raise # Needed else can't exit
+               except:
+                       maxretries=3 #default number of retries
+
+               retries=0
+               user_name, hostname, port = re.split(
+                       "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
+               if port is None:
+                       port=""
+               if user_name is None:
+                       user_name=""
+               updatecache_flg=True
+               all_rsync_opts = set(rsync_opts)
+               all_rsync_opts.update(
+                       settings.get("PORTAGE_RSYNC_EXTRA_OPTS","").split())
+               family = socket.AF_UNSPEC
+               if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
+                       family = socket.AF_INET
+               elif socket.has_ipv6 and \
+                       ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
+                       family = socket.AF_INET6
+               ips=[]
+               while (1):
+                       if ips:
+                               del ips[0]
+                       if ips==[]:
+                               try:
+                                       for addrinfo in socket.getaddrinfo(
+                                               hostname, None, family, socket.SOCK_STREAM):
+                                               if addrinfo[0] == socket.AF_INET6:
+                                                       # IPv6 addresses need to be enclosed in square brackets
+                                                       ips.append("[%s]" % addrinfo[4][0])
+                                               else:
+                                                       ips.append(addrinfo[4][0])
+                                       from random import shuffle
+                                       shuffle(ips)
+                               except SystemExit, e:
+                                       raise # Needed else can't exit
+                               except Exception, e:
+                                       print "Notice:",str(e)
+                                       dosyncuri=syncuri
+
+                       if ips:
+                               try:
+                                       dosyncuri = syncuri.replace(
+                                               "//" + user_name + hostname + port + "/",
+                                               "//" + user_name + ips[0] + port + "/", 1)
+                               except SystemExit, e:
+                                       raise # Needed else can't exit
+                               except Exception, e:
+                                       print "Notice:",str(e)
+                                       dosyncuri=syncuri
+
+                       if (retries==0):
+                               if "--ask" in myopts:
+                                       if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
+                                               print
+                                               print "Quitting."
+                                               print
+                                               sys.exit(0)
+                               emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
+                               if "--quiet" not in myopts:
+                                       print ">>> Starting rsync with "+dosyncuri+"..."
+                       else:
+                               emergelog(xterm_titles,
+                                       ">>> Starting retry %d of %d with %s" % \
+                                               (retries,maxretries,dosyncuri))
+                               print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
+
+                       if mytimestamp != 0 and "--quiet" not in myopts:
+                               print ">>> Checking server timestamp ..."
+
+                       rsynccommand = " ".join(["/usr/bin/rsync", " ".join(rsync_opts),
+                               settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")])
+
+                       if "--debug" in myopts:
+                               print rsynccommand
+
+                       exitcode = os.EX_OK
+                       servertimestamp = 0
+                       if mytimestamp != 0:
+                               mycommand = rsynccommand.split()
+                               mycommand.append(dosyncuri.rstrip("/") + \
+                                       "/metadata/timestamp.chk")
+                               mycommand.append(tmpservertimestampfile)
+                               try:
+                                       exitcode = portage.process.spawn(
+                                               mycommand, env=settings.environ())
+                                       content = portage.grabfile(tmpservertimestampfile)
+                                       if content:
+                                               try:
+                                                       servertimestamp = time.mktime(time.strptime(
+                                                               content[0], "%a, %d %b %Y %H:%M:%S +0000"))
+                                               except OverflowError, ValueError:
+                                                       pass
+                                       del content
+                               finally:
+                                       try:
+                                               os.unlink(tmpservertimestampfile)
+                                       except OSError:
+                                               pass
+                               del mycommand
+                       if exitcode == os.EX_OK:
+                               if (servertimestamp != 0) and (servertimestamp == mytimestamp):
+                                       emergelog(xterm_titles,
+                                               ">>> Cancelling sync -- Already current.")
+                                       print
+                                       print ">>>"
+                                       print ">>> Timestamps on the server and in the local repository are the same."
+                                       print ">>> Cancelling all further sync action. You are already up to date."
+                                       print ">>>"
+                                       print ">>> In order to force sync, remove '%s'." % servertimestampfile
+                                       print ">>>"
+                                       print
+                                       sys.exit(0)
+                               elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
+                                       emergelog(xterm_titles,
+                                               ">>> Server out of date: %s" % dosyncuri)
+                                       print
+                                       print ">>>"
+                                       print ">>> SERVER OUT OF DATE: %s" % dosyncuri
+                                       print ">>>"
+                                       print ">>> In order to force sync, remove '%s'." % servertimestampfile
+                                       print ">>>"
+                                       print
+                               elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
+                                       # actual sync
+                                       mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir
+                                       exitcode=portage.spawn(mycommand,settings,free=1)
+                                       if exitcode in [0,1,2,3,4,11,14,20,21]:
+                                               break
+                       elif exitcode in [0,1,2,3,4,11,14,20,21]:
+                               break
+
+                       retries=retries+1
+
+                       if retries<=maxretries:
+                               print ">>> Retrying..."
+                               time.sleep(11)
+                       else:
+                               # over retries
+                               # exit loop
+                               updatecache_flg=False
+                               break
+
+               if (exitcode==0):
+                       emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
+               elif (exitcode>0):
+                       print
+                       if exitcode==1:
+                               print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
+                               print darkred("!!!")+green(" that your SYNC statement is proper.")
+                               print darkred("!!!")+green(" SYNC="+settings["SYNC"])
+                       elif exitcode==11:
+                               print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
+                               print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
+                               print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
+                               print darkred("!!!")+green(" and try again after the problem has been fixed.")
+                               print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
+                       elif exitcode==20:
+                               print darkred("!!!")+green(" Rsync was killed before it finished.")
+                       else:
+                               print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
+                               print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
+                               print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
+                               print darkred("!!!")+green(" temporary problem unless complications exist with your network")
+                               print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
+                       print
+                       sys.exit(exitcode)
+       elif syncuri[:6]=="cvs://":
+               if not os.path.exists("/usr/bin/cvs"):
+                       print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
+                       print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
+                       sys.exit(1)
+               cvsroot=syncuri[6:]
+               cvsdir=os.path.dirname(myportdir)
+               if not os.path.exists(myportdir+"/CVS"):
+                       #initial checkout
+                       print ">>> Starting initial cvs checkout with "+syncuri+"..."
+                       if os.path.exists(cvsdir+"/gentoo-x86"):
+                               print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
+                               sys.exit(1)
+                       try:
+                               os.rmdir(myportdir)
+                       except OSError, e:
+                               if e.errno != errno.ENOENT:
+                                       sys.stderr.write(
+                                               "!!! existing '%s' directory; exiting.\n" % myportdir)
+                                       sys.exit(1)
+                               del e
+                       if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
+                               print "!!! cvs checkout error; exiting."
+                               sys.exit(1)
+                       os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
+               else:
+                       #cvs update
+                       print ">>> Starting cvs update with "+syncuri+"..."
+                       retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
+                               myportdir, settings, free=1)
+                       if retval != os.EX_OK:
+                               sys.exit(retval)
+               dosyncuri = syncuri
+       else:
+               print "!!! rsync setting: ",syncuri,"not recognized; exiting."
+               sys.exit(1)
+
+       if updatecache_flg and  \
+               myaction != "metadata" and \
+               "metadata-transfer" not in settings.features:
+               updatecache_flg = False
+
+       # Reload the whole config from scratch.
+       settings, trees, mtimedb = load_emerge_config(trees=trees)
+       portdb = trees[settings["ROOT"]]["porttree"].dbapi
+
+       if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
+               action_metadata(settings, portdb, myopts)
+
+       if portage.global_updates(settings, trees, mtimedb["updates"]):
+               mtimedb.commit()
+               # Reload the whole config from scratch.
+               settings, trees, mtimedb = load_emerge_config(trees=trees)
+               portdb = trees[settings["ROOT"]]["porttree"].dbapi
+
+       mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
+       mypvs = portage.best(
+               trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
+
+       chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
+
+       if myaction != "metadata":
+               if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
+                       retval = portage.process.spawn(
+                               [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
+                               dosyncuri], env=settings.environ())
+                       if retval != os.EX_OK:
+                               print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
+
+       if(mybestpv != mypvs) and not "--quiet" in myopts:
+               print
+               print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
+               print red(" * ")+"that you update portage now, before any other packages are updated."
+               print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
+               print red(" * ")+"configuration files."
+               print red(" * ")+"To update portage, run 'emerge portage'."
+               print
+
+def action_metadata(settings, portdb, myopts):
+       portage.writemsg_stdout("\n>>> Updating Portage cache:      ")
+       old_umask = os.umask(0002)
+       cachedir = os.path.normpath(settings.depcachedir)
+       if cachedir in ["/",    "/bin", "/dev",  "/etc",  "/home",
+                                       "/lib", "/opt", "/proc", "/root", "/sbin",
+                                       "/sys", "/tmp", "/usr",  "/var"]:
+               print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
+                       "ROOT DIRECTORY ON YOUR SYSTEM."
+               print >> sys.stderr, \
+                       "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
+               sys.exit(73)
+       if not os.path.exists(cachedir):
+               os.mkdir(cachedir)
+
+       ec = portage.eclass_cache.cache(portdb.porttree_root)
+       myportdir = os.path.realpath(settings["PORTDIR"])
+       cm = settings.load_best_module("portdbapi.metadbmodule")(
+               myportdir, "metadata/cache", portage.auxdbkeys[:])
+
+       from portage.cache import util
+
+       class percentage_noise_maker(util.quiet_mirroring):
+               def __init__(self, dbapi):
+                       self.dbapi = dbapi
+                       self.cp_all = dbapi.cp_all()
+                       l = len(self.cp_all)
+                       self.call_update_min = 100000000
+                       self.min_cp_all = l/100.0
+                       self.count = 1
+                       self.pstr = ''
+
+               def __iter__(self):
+                       for x in self.cp_all:
+                               self.count += 1
+                               if self.count > self.min_cp_all:
+                                       self.call_update_min = 0
+                                       self.count = 0
+                               for y in self.dbapi.cp_list(x):
+                                       yield y
+                       self.call_update_mine = 0
+
+               def update(self, *arg):
+                       try:                            self.pstr = int(self.pstr) + 1
+                       except ValueError:      self.pstr = 1
+                       sys.stdout.write("%s%i%%" % \
+                               ("\b" * (len(str(self.pstr))+1), self.pstr))
+                       sys.stdout.flush()
+                       self.call_update_min = 10000000
+
+               def finish(self, *arg):
+                       sys.stdout.write("\b\b\b\b100%\n")
+                       sys.stdout.flush()
+
+       if "--quiet" in myopts:
+               def quicky_cpv_generator(cp_all_list):
+                       for x in cp_all_list:
+                               for y in portdb.cp_list(x):
+                                       yield y
+               source = quicky_cpv_generator(portdb.cp_all())
+               noise_maker = portage.cache.util.quiet_mirroring()
+       else:
+               noise_maker = source = percentage_noise_maker(portdb)
+       portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
+               eclass_cache=ec, verbose_instance=noise_maker)
+
+       sys.stdout.flush()
+       os.umask(old_umask)
+
+def action_regen(settings, portdb):
+       xterm_titles = "notitles" not in settings.features
+       emergelog(xterm_titles, " === regen")
+       #regenerate cache entries
+       print "Regenerating cache entries... "
+       try:
+               os.close(sys.stdin.fileno())
+       except SystemExit, e:
+               raise # Needed else can't exit
+       except:
+               pass
+       sys.stdout.flush()
+       mynodes = portdb.cp_all()
+       from portage.cache.cache_errors import CacheError
+       dead_nodes = {}
+       for mytree in portdb.porttrees:
+               try:
+                       dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
+               except CacheError, e:
+                       print "\n  error listing cache entries for " + \
+                               "'%s': %s, continuing..." % (mytree, e)
+                       del e
+                       dead_nodes = None
+                       break
+       for x in mynodes:
+               mymatches = portdb.xmatch("match-all",x)
+               portage.writemsg_stdout("processing %s\n" % x)
+               for y in mymatches:
+                       try:
+                               foo = portdb.aux_get(y,["DEPEND"])
+                       except SystemExit, e:
+                               # sys.exit is an exception... And consequently, we can't catch it.
+                               raise
+                       except Exception, e:
+                               print "\n  error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
+                       if dead_nodes:
+                               for mytree in portdb.porttrees:
+                                       if portdb.findname2(y, mytree=mytree)[0]:
+                                               dead_nodes[mytree].discard(y)
+       if dead_nodes:
+               for mytree, nodes in dead_nodes.iteritems():
+                       auxdb = portdb.auxdb[mytree]
+                       for y in nodes:
+                               try:
+                                       del auxdb[y]
+                               except KeyError, CacheError:
+                                       pass
+       print "done!"
+
+def action_config(settings, trees, myopts, myfiles):
+       if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
+               print red("!!! config can only take a single package atom at this time\n")
+               sys.exit(1)
+       if not is_valid_package_atom(myfiles[0]):
+               portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
+                       noiselevel=-1)
+               portage.writemsg("!!! Please check ebuild(5) for full details.\n")
+               portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
+               sys.exit(1)
+       print
+       try:
+               pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
+       except ValueError, e:
+               # Multiple matches thrown from cpv_expand
+               pkgs = e.args[0]
+       if len(pkgs) == 0:
+               print "No packages found.\n"
+               sys.exit(0)
+       elif len(pkgs) > 1:
+               if "--ask" in myopts:
+                       options = []
+                       print "Please select a package to configure:"
+                       idx = 0
+                       for pkg in pkgs:
+                               idx += 1
+                               options.append(str(idx))
+                               print options[-1]+") "+pkg
+                       print "X) Cancel"
+                       options.append("X")
+                       idx = userquery("Selection?", options)
+                       if idx == "X":
+                               sys.exit(0)
+                       pkg = pkgs[int(idx)-1]
+               else:
+                       print "The following packages available:"
+                       for pkg in pkgs:
+                               print "* "+pkg
+                       print "\nPlease use a specific atom or the --ask option."
+                       sys.exit(1)
+       else:
+               pkg = pkgs[0]
+
+       print
+       if "--ask" in myopts:
+               if userquery("Ready to configure "+pkg+"?") == "No":
+                       sys.exit(0)
+       else:
+               print "Configuring pkg..."
+       print
+       ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
+       mysettings = portage.config(clone=settings)
+       portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
+               debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
+               mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
+       print
+
+def action_info(settings, trees, myopts, myfiles):
+       unameout=commands.getstatusoutput("uname -mrp")[1]
+       print getportageversion(settings["PORTDIR"], settings["ROOT"],
+               settings.profile_path, settings["CHOST"],
+               trees[settings["ROOT"]]["vartree"].dbapi)
+       header_width = 65
+       header_title = "System Settings"
+       if myfiles:
+               print header_width * "="
+               print header_title.rjust(int(header_width/2 + len(header_title)/2))
+       print header_width * "="
+       print "System uname: "+unameout
+       gentoo_release = portage.grabfile(os.path.join(
+               settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
+       if gentoo_release:
+               print gentoo_release[0]
+       else:
+               print "Unknown Host Operating System"
+       lastSync = portage.grabfile(os.path.join(
+               settings["PORTDIR"], "metadata", "timestamp.chk"))
+       print "Timestamp of tree:",
+       if lastSync:
+               print lastSync[0]
+       else:
+               print "Unknown"
+
+       output=commands.getstatusoutput("distcc --version")
+       if not output[0]:
+               print str(output[1].split("\n",1)[0]),
+               if "distcc" in settings.features:
+                       print "[enabled]"
+               else:
+                       print "[disabled]"
+
+       output=commands.getstatusoutput("ccache -V")
+       if not output[0]:
+               print str(output[1].split("\n",1)[0]),
+               if "ccache" in settings.features:
+                       print "[enabled]"
+               else:
+                       print "[disabled]"
+
+       myvars  = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
+                  "sys-devel/binutils", "sys-devel/libtool",  "dev-lang/python"]
+       myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
+       myvars  = portage.util.unique_array(myvars)
+       myvars.sort()
+
+       for x in myvars:
+               if portage.isvalidatom(x):
+                       pkg_matches = trees["/"]["vartree"].dbapi.match(x)
+                       pkgs = []
+                       for y in pkg_matches:
+                               mycpv   = portage.catpkgsplit(y)
+                               if(mycpv[3] != "r0"):
+                                       pkgs += [mycpv[2] + "-" + mycpv[3]]
+                               else:
+                                       pkgs += [mycpv[2]]
+                       if pkgs:
+                               pkgs = ", ".join(sorted_versions(pkgs))
+                               print "%-20s %s" % (x+":", pkgs)
+               else:
+                       print "%-20s %s" % (x+":", "[NOT VALID]")
+
+       libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
+
+       if "--verbose" in myopts:
+               myvars=settings.keys()
+       else:
+               myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
+                         'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
+                         'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
+                         'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
+
+               myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
+
+       myvars = portage.util.unique_array(myvars)
+       unset_vars = []
+       myvars.sort()
+       for x in myvars:
+               if x in settings:
+                       if x != "USE":
+                               print '%s="%s"' % (x, settings[x])
+                       else:
+                               use = set(settings["USE"].split())
+                               use_expand = settings["USE_EXPAND"].split()
+                               use_expand.sort()
+                               for varname in use_expand:
+                                       flag_prefix = varname.lower() + "_"
+                                       for f in list(use):
+                                               if f.startswith(flag_prefix):
+                                                       use.remove(f)
+                               use = list(use)
+                               use.sort()
+                               print 'USE="%s"' % " ".join(use),
+                               for varname in use_expand:
+                                       myval = settings.get(varname)
+                                       if myval:
+                                               print '%s="%s"' % (varname, myval),
+                               print
+               else:
+                       unset_vars.append(x)
+       if unset_vars:
+               print "Unset:  "+", ".join(unset_vars)
+       print
+
+       if "--debug" in myopts:
+               for x in dir(portage):
+                       module = getattr(portage, x)
+                       if "cvs_id_string" in dir(module):
+                               print "%s: %s" % (str(x), str(module.cvs_id_string))
+
+       # See if we can find any packages installed matching the strings
+       # passed on the command line
+       mypkgs = []
+       vardb = trees[settings["ROOT"]]["vartree"].dbapi
+       portdb = trees[settings["ROOT"]]["porttree"].dbapi
+       for x in myfiles:
+               mypkgs.extend(vardb.match(x))
+
+       # If some packages were found...
+       if mypkgs:
+               # Get our global settings (we only print stuff if it varies from
+               # the current config)
+               mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
+               auxkeys = mydesiredvars + [ "USE", "IUSE"]
+               global_vals = {}
+               pkgsettings = portage.config(clone=settings)
+
+               for myvar in mydesiredvars:
+                       global_vals[myvar] = set(settings.get(myvar, "").split())
+
+               # Loop through each package
+               # Only print settings if they differ from global settings
+               header_printed = False
+               for pkg in mypkgs:
+                       # Get all package specific variables
+                       auxvalues = vardb.aux_get(pkg, auxkeys)
+                       valuesmap = {}
+                       for i in xrange(len(auxkeys)):
+                               valuesmap[auxkeys[i]] = set(auxvalues[i].split())
+                       diff_values = {}
+                       for myvar in mydesiredvars:
+                               # If the package variable doesn't match the
+                               # current global variable, something has changed
+                               # so set diff_found so we know to print
+                               if valuesmap[myvar] != global_vals[myvar]:
+                                       diff_values[myvar] = valuesmap[myvar]
+                       valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
+                       valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
+                       pkgsettings.reset()
+                       # If a matching ebuild is no longer available in the tree, maybe it
+                       # would make sense to compare against the flags for the best
+                       # available version with the same slot?
+                       mydb = None
+                       if portdb.cpv_exists(pkg):
+                               mydb = portdb
+                       pkgsettings.setcpv(pkg, mydb=mydb)
+                       if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
+                               valuesmap["USE"]:
+                               diff_values["USE"] = valuesmap["USE"]
+                       # If a difference was found, print the info for
+                       # this package.
+                       if diff_values:
+
+                               # If we have not yet printed the header, 
+                               # print it now
+                               if not header_printed:
+                                       header_title = "Package Settings"
+                                       print header_width * "="
+                                       print header_title.rjust(int(header_width/2 + len(header_title)/2))
+                                       print header_width * "="
+                                       header_printed = True
+
+                               # Print package info
+                               print "%s was built with the following:" % pkg
+                               for myvar in mydesiredvars + ["USE"]:
+                                       if myvar in diff_values:
+                                               mylist = list(diff_values[myvar])
+                                               mylist.sort()
+                                               print "%s=\"%s\"" % (myvar, " ".join(mylist))
+                               print
+
+def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
+       if not myfiles:
+               print "emerge: no search terms provided."
+       else:
+               searchinstance = search(settings, portdb,
+                       vartree, spinner, "--searchdesc" in myopts,
+                       "--quiet" not in myopts)
+               for mysearch in myfiles:
+                       try:
+                               searchinstance.execute(mysearch)
+                       except re.error, comment:
+                               print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
+                               sys.exit(1)
+                       searchinstance.output()
+
+def action_depclean(settings, trees, ldpath_mtimes,
+       myopts, spinner):
+       # Kill packages that aren't explicitly merged or are required as a
+       # dependency of another package. World file is explicit.
+
+       warn_prefix = colorize("BAD", "*** WARNING ***  ")
+       print
+       print warn_prefix + "Depclean may break link level dependencies.  Thus, it is"
+       print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
+       print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
+       print warn_prefix
+       print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
+       print warn_prefix + "mistakes. Packages that are part of the world set will always"
+       print warn_prefix + "be kept.  They can be manually added to this set with"
+       print warn_prefix + good("`emerge --noreplace <atom>`") + ".  Packages that are listed in"
+       print warn_prefix + "package.provided (see portage(5)) will be removed by"
+       print warn_prefix + "depclean, even if they are part of the world set."
+       print warn_prefix
+       print warn_prefix + "As a safety measure, depclean will not remove any packages"
+       print warn_prefix + "unless *all* required dependencies have been resolved.  As a"
+       print warn_prefix + "consequence, it is often necessary to run "
+       print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
+
+       xterm_titles = "notitles" not in settings.features
+       myroot = settings["ROOT"]
+       dep_check_trees = {}
+       dep_check_trees[myroot] = {}
+       dep_check_trees[myroot]["vartree"] = \
+               FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
+       vardb = dep_check_trees[myroot]["vartree"].dbapi
+       # Constrain dependency selection to the installed packages.
+       dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
+       syslist = getlist(settings, "system")
+       worldlist = getlist(settings, "world")
+       fakedb = portage.fakedbapi(settings=settings)
+       myvarlist = vardb.cpv_all()
+
+       if not syslist:
+               print "\n!!! You have no system list.",
+       if not worldlist:
+               print "\n!!! You have no world file.",
+       if not myvarlist:
+               print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
+
+       if not (syslist and worldlist and myvarlist):
+               print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
+               print " break your installation.\n"
+               if "--pretend" not in myopts:
+                       countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
+
+       if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
+               emergelog(xterm_titles, " >>> depclean")
+
+       if "--quiet" not in myopts:
+               print "\nCalculating dependencies  ",
+
+       soft = 0
+       hard = 1
+       remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
+       remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
+       unresolveable = {}
+       aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
+
+       while remaining_atoms:
+               atom, parent, priority = remaining_atoms.pop()
+               pkgs = vardb.match(atom)
+               if not pkgs:
+                       if not atom.startswith("!") and priority == hard:
+                               unresolveable.setdefault(atom, []).append(parent)
+                       continue
+               # Could put slot checking here to ensure that there aren't two
+               # packages with the same slot...
+               for pkg in pkgs:
+                       if fakedb.cpv_exists(pkg):
+                               continue
+                       spinner.update()
+                       fakedb.cpv_inject(pkg)
+                       myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
+                       mydeps = []
+                       if myopts.get("--with-bdeps", "y") == "y":
+                               mydeps.append((myaux["DEPEND"], soft))
+                       del myaux["DEPEND"]
+                       mydeps.append((" ".join(myaux.values()), hard))
+                       usedef = vardb.aux_get(pkg, ["USE"])[0].split()
+                       for depstr, priority in mydeps:
+
+                               if not depstr:
+                                       continue
+
+                               if "--debug" in myopts:
+                                       print
+                                       print "Parent:   ", pkg
+                                       print "Depstring:", depstr
+                                       print "Priority:",
+                                       if priority == soft:
+                                               print "soft"
+                                       else:
+                                               print "hard"
+
+                               try:
+                                       portage.dep._dep_check_strict = False
+                                       success, atoms = portage.dep_check(depstr, None, settings,
+                                               myuse=usedef, trees=dep_check_trees, myroot=myroot)
+                               finally:
+                                       portage.dep._dep_check_strict = True
+                               if not success:
+                                       show_invalid_depstring_notice(
+                                               ("installed", myroot, pkg, "nomerge"),
+                                               depstr, atoms)
+                                       return
+
+                               if "--debug" in myopts:
+                                       print "Candidates:", atoms
+
+                               for atom in atoms:
+                                       remaining_atoms.append((atom, pkg, priority))
+
+       if "--quiet" not in myopts:
+               print "\b\b... done!\n"
+
+       if unresolveable:
+               print "Dependencies could not be completely resolved due to"
+               print "the following required packages not being installed:"
+               print
+               for atom in unresolveable:
+                       print atom, "required by", " ".join(unresolveable[atom])
+               print
+               print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
+               print "depclean?  It may also be necessary to manually uninstalled packages that no"
+               print "longer exist in the portage tree since it may not be possible to satisfy their"
+               print "dependencies."
+               print
+               return
+
+       cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
+
+       if len(cleanlist):
+               unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
+                       "unmerge", cleanlist, ldpath_mtimes)
+
+       print "Packages installed:   "+str(len(myvarlist))
+       print "Packages in world:    "+str(len(worldlist))
+       print "Packages in system:   "+str(len(syslist))
+       print "Unique package names: "+str(len(myvarlist))
+       print "Required packages:    "+str(len(fakedb.cpv_all()))
+       if "--pretend" in myopts:
+               print "Number to remove:     "+str(len(cleanlist))
+       else:
+               print "Number removed:       "+str(len(cleanlist))
+
+def action_build(settings, trees, mtimedb,
+       myopts, myaction, myfiles, spinner):
+       ldpath_mtimes = mtimedb["ldpath"]
+       favorites=[]
+       if ("--ask" in myopts or "--pretend" in myopts) and not "--quiet" in myopts:
+               action = ""
+               if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
+                       action = "fetched"
+               else:
+                       action = "merged"
+               if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
+                       print
+                       print darkgreen("These are the packages that would be %s, in reverse order:") % action
+                       print
+               else:
+                       print
+                       print darkgreen("These are the packages that would be %s, in order:") % action
+                       print
+
+       # validate the state of the resume data
+       # so that we can make assumptions later.
+       for k in ("resume", "resume_backup"):
+               if k in mtimedb:
+                       if "mergelist" in mtimedb[k]:
+                               if not mtimedb[k]["mergelist"]:
+                                       del mtimedb[k]
+                       else:
+                               del mtimedb[k]
+
+       if "--resume" in myopts and \
+               ("resume" in mtimedb or
+               "resume_backup" in mtimedb):
+               if "resume" not in mtimedb:
+                       mtimedb["resume"] = mtimedb["resume_backup"]
+                       del mtimedb["resume_backup"]
+                       mtimedb.commit()
+               # XXX: "myopts" is a list for backward compatibility.
+               myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
+
+               for opt in ("--skipfirst", "--ask", "--tree"):
+                       myresumeopts.pop(opt, None)
+
+               for myopt, myarg in myopts.iteritems():
+                       if myopt not in myresumeopts:
+                               myresumeopts[myopt] = myarg
+               myopts=myresumeopts
+               myparams = create_depgraph_params(myopts, myaction)
+               if not "--quiet" in myopts:
+                       print "Calculating dependencies  ",
+               mydepgraph = depgraph(settings, trees,
+                       myopts, myparams, spinner)
+               if not "--quiet" in myopts:
+                       print "\b\b... done!"
+       else:
+               if ("--resume" in myopts):
+                       print darkgreen("emerge: It seems we have nothing to resume...")
+                       sys.exit(0)
+
+               myparams = create_depgraph_params(myopts, myaction)
+               if myaction in ["system","world"]:
+                       if not ("--quiet" in myopts):
+                               print "Calculating",myaction,"dependencies  ",
+                               sys.stdout.flush()
+                       mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
+                       if not mydepgraph.xcreate(myaction):
+                               print "!!! Depgraph creation failed."
+                               sys.exit(1)
+                       if not ("--quiet" in myopts):
+                               print "\b\b... done!"
+               else:
+                       if not ("--quiet" in myopts):
+                               print "Calculating dependencies  ",
+                               sys.stdout.flush()
+                       mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
+                       try:
+                               retval, favorites = mydepgraph.select_files(myfiles)
+                       except portage.exception.PackageNotFound, e:
+                               portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
+                               sys.exit(1)
+                       if not retval:
+                               sys.exit(1)
+                       if not ("--quiet" in myopts):
+                               print "\b\b... done!"
+
+                       if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
+                               sys.stderr.write(red("The following binaries are not available for merging...\n"))
+
+               if mydepgraph.missingbins:
+                       for x in mydepgraph.missingbins:
+                               sys.stderr.write("   "+str(x)+"\n")
+                       sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
+                       sys.exit(1)
+
+       if "--ask" in myopts:
+               if "--resume" in myopts:
+                       validate_merge_list(trees, mtimedb["resume"]["mergelist"])
+                       mymergelist = mtimedb["resume"]["mergelist"]
+                       if "--skipfirst" in myopts:
+                               mymergelist = mymergelist[1:]
+                       if len(mymergelist) == 0:
+                               print colorize("INFORM", "emerge: It seems we have nothing to resume...")
+                               sys.exit(0)
+                       mydepgraph.display(mymergelist)
+                       prompt="Would you like to resume merging these packages?"
+               else:
+                       mydepgraph.display(
+                               mydepgraph.altlist(reversed=("--tree" in myopts)))
+                       mergecount=0
+                       for x in mydepgraph.altlist():
+                               if x[0] != "blocks" and x[3] != "nomerge":
+                                       mergecount+=1
+                               #check for blocking dependencies
+                               if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
+                                       print "\n!!! Error: The above package list contains packages which cannot be installed"
+                                       print   "!!!        at the same time on the same system."
+                                       if "--quiet" not in myopts:
+                                               show_blocker_docs_link()
+                                       sys.exit(1)
+                       if mergecount==0:
+                               if "--noreplace" in myopts and favorites:
+                                       print
+                                       for x in favorites:
+                                               print " %s %s" % (good("*"), x)
+                                       prompt="Would you like to add these packages to your world favorites?"
+                               elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
+                                       prompt="Nothing to merge; would you like to auto-clean packages?"
+                               else:
+                                       print
+                                       print "Nothing to merge; quitting."
+                                       print
+                                       sys.exit(0)
+                       elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
+                               prompt="Would you like to fetch the source files for these packages?"
+                       else:
+                               prompt="Would you like to merge these packages?"
+               print
+               if userquery(prompt)=="No":
+                       print
+                       print "Quitting."
+                       print
+                       sys.exit(0)
+               # Don't ask again (e.g. when auto-cleaning packages after merge)
+               del myopts["--ask"]
+
+       if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
+               if ("--resume" in myopts):
+                       validate_merge_list(trees, mtimedb["resume"]["mergelist"])
+                       mymergelist = mtimedb["resume"]["mergelist"]
+                       if "--skipfirst" in myopts:
+                               mymergelist = mymergelist[1:]
+                       if len(mymergelist) == 0:
+                               print colorize("INFORM", "emerge: It seems we have nothing to resume...")
+                               sys.exit(0)
+                       mydepgraph.display(mymergelist)
+               else:
+                       mydepgraph.display(
+                               mydepgraph.altlist(reversed=("--tree" in myopts)))
+       else:
+               if ("--buildpkgonly" in myopts):
+                       if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
+                               print "\n!!! --buildpkgonly requires all dependencies to be merged."
+                               print "!!! Cannot merge requested packages. Merge deps and try again.\n"
+                               sys.exit(1)
+
+               if ("--resume" in myopts):
+                       favorites=mtimedb["resume"]["favorites"]
+                       mergetask = MergeTask(settings, trees, myopts)
+                       if "--fetchonly" in myopts:
+                               """ parallel-fetch uses --resume --fetchonly and we don't want
+                               it to write the mtimedb"""
+                               mtimedb.filename = None
+                               time.sleep(3) # allow the parent to have first fetch
+                       del mydepgraph
+                       retval = mergetask.merge(
+                               mtimedb["resume"]["mergelist"], favorites, mtimedb)
+                       if retval != os.EX_OK:
+                               sys.exit(retval)
+               else:
+                       if "resume" in mtimedb and \
+                       "mergelist" in mtimedb["resume"] and \
+                       len(mtimedb["resume"]["mergelist"]) > 1:
+                               mtimedb["resume_backup"] = mtimedb["resume"]
+                               del mtimedb["resume"]
+                               mtimedb.commit()
+                       mtimedb["resume"]={}
+                       # XXX: Stored as a list for backward compatibility.
+                       mtimedb["resume"]["myopts"] = \
+                               [k for k in myopts if myopts[k] is True]
+                       mtimedb["resume"]["favorites"]=favorites
+                       if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
+                               for pkgline in mydepgraph.altlist():
+                                       if pkgline[0]=="ebuild" and pkgline[3]=="merge":
+                                               y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
+                                               tmpsettings = portage.config(clone=settings)
+                                               edebug = 0
+                                               if settings.get("PORTAGE_DEBUG", "") == "1":
+                                                       edebug = 1
+                                               retval = portage.doebuild(
+                                                       y, "digest", settings["ROOT"], tmpsettings, edebug,
+                                                       ("--pretend" in myopts),
+                                                       mydbapi=trees[pkgline[1]]["porttree"].dbapi,
+                                                       tree="porttree")
+                       if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
+                               pkglist = []
+                               for pkg in mydepgraph.altlist():
+                                       if pkg[0] != "blocks":
+                                               pkglist.append(pkg)
+                       else:
+                               pkglist = mydepgraph.altlist()
+                       del mydepgraph
+                       mergetask = MergeTask(settings, trees, myopts)
+                       retval = mergetask.merge(pkglist, favorites, mtimedb)
+                       if retval != os.EX_OK:
+                               sys.exit(retval)
+
+               if mtimedb.has_key("resume"):
+                       del mtimedb["resume"]
+               if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
+                       print ">>> Auto-cleaning packages..."
+                       vartree = trees[settings["ROOT"]]["vartree"]
+                       unmerge(settings, myopts, vartree, "clean", ["world"],
+                               ldpath_mtimes, autoclean=1)
+               else:
+                       portage.writemsg_stdout(colorize("WARN", "WARNING:")
+                               + " AUTOCLEAN is disabled.  This can cause serious"
+                               + " problems due to overlapping packages.\n")
+
+def multiple_actions(action1, action2):
+       sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
+       sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
+       sys.exit(1)
+
+def parse_opts(tmpcmdline, silent=False):
+       myaction=None
+       myopts = {}
+       myfiles=[]
+
+       global actions, options, shortmapping
+
+       longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
+       argument_options = {
+               "--config-root": {
+                       "help":"specify the location for portage configuration files",
+                       "action":"store"
+               },
+               "--color": {
+                       "help":"enable or disable color output",
+                       "type":"choice",
+                       "choices":("y", "n")
+               },
+               "--with-bdeps": {
+                       "help":"include unnecessary build time dependencies",
+                       "type":"choice",
+                       "choices":("y", "n")
+               }
+       }
+
+       from optparse import OptionParser
+       parser = OptionParser()
+       if parser.has_option("--help"):
+               parser.remove_option("--help")
+
+       for action_opt in actions:
+               parser.add_option("--" + action_opt, action="store_true",
+                       dest=action_opt.replace("-", "_"), default=False)
+       for myopt in options:
+               parser.add_option(myopt, action="store_true",
+                       dest=myopt.lstrip("--").replace("-", "_"), default=False)
+       for shortopt, longopt in shortmapping.iteritems():
+               parser.add_option("-" + shortopt, action="store_true",
+                       dest=longopt.lstrip("--").replace("-", "_"), default=False)
+       for myalias, myopt in longopt_aliases.iteritems():
+               parser.add_option(myalias, action="store_true",
+                       dest=myopt.lstrip("--").replace("-", "_"), default=False)
+
+       for myopt, kwargs in argument_options.iteritems():
+               parser.add_option(myopt,
+                       dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
+
+       myoptions, myargs = parser.parse_args(args=tmpcmdline)
+
+       for myopt in options:
+               v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
+               if v:
+                       myopts[myopt] = True
+
+       for myopt in argument_options:
+               v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
+               if v is not None:
+                       myopts[myopt] = v
+
+       for action_opt in actions:
+               v = getattr(myoptions, action_opt.replace("-", "_"))
+               if v:
+                       if myaction:
+                               multiple_actions(myaction, action_opt)
+                               sys.exit(1)
+                       myaction = action_opt
+
+       for x in myargs:
+               if x in actions and myaction != "search":
+                       if not silent and x not in ["system", "world"]:
+                               print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
+                       # special case "search" so people can search for action terms, e.g. emerge -s sync
+                       if myaction:
+                               multiple_actions(myaction, x)
+                               sys.exit(1)
+                       myaction = x
+               else:
+                       myfiles.append(x)
+
+       if "--nocolor" in myopts:
+               if not silent:
+                       sys.stderr.write("*** Deprecated use of '--nocolor', " + \
+                               "use '--color=n' instead.\n")
+               del myopts["--nocolor"]
+               myopts["--color"] = "n"
+
+       return myaction, myopts, myfiles
+
+def validate_ebuild_environment(trees):
+       for myroot in trees:
+               mysettings = trees[myroot]["vartree"].settings
+               if not mysettings.get("ARCH", None):
+                       print >> sys.stderr, bad("\a!!! ARCH is not set... " + \
+                               "Are you missing the '%setc/make.profile' symlink?" % \
+                               mysettings["PORTAGE_CONFIGROOT"])
+                       print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
+                               "Is your portage tree complete?\n")
+                       sys.exit(9)
+               del myroot, mysettings
+
+def load_emerge_config(trees=None):
+       kwargs = {}
+       for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
+               kwargs[k] = os.environ.get(envvar, None)
+       trees = portage.create_trees(trees=trees, **kwargs)
+
+       settings = trees["/"]["vartree"].settings
+
+       for myroot in trees:
+               if myroot != "/":
+                       settings = trees[myroot]["vartree"].settings
+                       break
+
+       mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
+       mtimedb = portage.MtimeDB(mtimedbfile)
+       return settings, trees, mtimedb
+
+def adjust_config(myopts, settings):
+       """Make emerge specific adjustments to the config."""
+
+       # To enhance usability, make some vars case insensitive by forcing them to
+       # lower case.
+       for myvar in ("AUTOCLEAN", "NOCOLOR"):
+               if myvar in settings:
+                       settings[myvar] = settings[myvar].lower()
+                       settings.backup_changes(myvar)
+       del myvar
+
+       # Kill noauto as it will break merges otherwise.
+       if "noauto" in settings.features:
+               while "noauto" in settings.features:
+                       settings.features.remove("noauto")
+               settings["FEATURES"] = " ".join(settings.features)
+               settings.backup_changes("FEATURES")
+
+       CLEAN_DELAY = 5
+       try:
+               CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
+       except ValueError, e:
+               portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
+               portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
+                       settings["CLEAN_DELAY"], noiselevel=-1)
+       settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
+       settings.backup_changes("CLEAN_DELAY")
+
+       EMERGE_WARNING_DELAY = 10
+       try:
+               EMERGE_WARNING_DELAY = int(settings.get(
+                       "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
+       except ValueError, e:
+               portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
+               portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
+                       settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
+       settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
+       settings.backup_changes("EMERGE_WARNING_DELAY")
+
+       if "--quiet" in myopts:
+               settings["PORTAGE_QUIET"]="1"
+               settings.backup_changes("PORTAGE_QUIET")
+
+       # Set so that configs will be merged regardless of remembered status
+       if ("--noconfmem" in myopts):
+               settings["NOCONFMEM"]="1"
+               settings.backup_changes("NOCONFMEM")
+
+       # Set various debug markers... They should be merged somehow.
+       PORTAGE_DEBUG = 0
+       try:
+               PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
+               if PORTAGE_DEBUG not in (0, 1):
+                       portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
+                               PORTAGE_DEBUG, noiselevel=-1)
+                       portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
+                               noiselevel=-1)
+                       PORTAGE_DEBUG = 0
+       except ValueError, e:
+               portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
+               portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
+                       settings["PORTAGE_DEBUG"], noiselevel=-1)
+               del e
+       if "--debug" in myopts:
+               PORTAGE_DEBUG = 1
+       settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
+       settings.backup_changes("PORTAGE_DEBUG")
+
+       if settings.get("NOCOLOR") not in ("yes","true"):
+               portage.output.havecolor = 1
+
+       """The explicit --color < y | n > option overrides the NOCOLOR environment
+       variable and stdout auto-detection."""
+       if "--color" in myopts:
+               if "y" == myopts["--color"]:
+                       portage.output.havecolor = 1
+                       settings["NOCOLOR"] = "false"
+               else:
+                       portage.output.havecolor = 0
+                       settings["NOCOLOR"] = "true"
+               settings.backup_changes("NOCOLOR")
+       elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
+               portage.output.havecolor = 0
+               settings["NOCOLOR"] = "true"
+               settings.backup_changes("NOCOLOR")
+
+def emerge_main():
+       global portage  # NFC why this is necessary now - genone
+       # Disable color until we're sure that it should be enabled (after
+       # EMERGE_DEFAULT_OPTS has been parsed).
+       portage.output.havecolor = 0
+       # This first pass is just for options that need to be known as early as
+       # possible, such as --config-root.  They will be parsed again later,
+       # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
+       # the value of --config-root).
+       myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
+       if "--debug" in myopts:
+               os.environ["PORTAGE_DEBUG"] = "1"
+       if "--config-root" in myopts:
+               os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
+
+       # Portage needs to ensure a sane umask for the files it creates.
+       os.umask(022)
+       settings, trees, mtimedb = load_emerge_config()
+       portdb = trees[settings["ROOT"]]["porttree"].dbapi
+
+       try:
+               os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
+       except (OSError, ValueError), e:
+               portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
+                       settings["PORTAGE_NICENESS"])
+               portage.writemsg("!!! %s\n" % str(e))
+               del e
+
+       if portage.global_updates(settings, trees, mtimedb["updates"]):
+               mtimedb.commit()
+               # Reload the whole config from scratch.
+               settings, trees, mtimedb = load_emerge_config(trees=trees)
+               portdb = trees[settings["ROOT"]]["porttree"].dbapi
+
+       xterm_titles = "notitles" not in settings.features
+
+       tmpcmdline = []
+       if "--ignore-default-opts" not in sys.argv:
+               tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
+       tmpcmdline.extend(sys.argv[1:])
+       myaction, myopts, myfiles = parse_opts(tmpcmdline)
+
+       if "--digest" in myopts:
+               os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
+               # Reload the whole config from scratch so that the portdbapi internal
+               # config is updated with new FEATURES.
+               settings, trees, mtimedb = load_emerge_config(trees=trees)
+               portdb = trees[settings["ROOT"]]["porttree"].dbapi
+
+       for myroot in trees:
+               mysettings =  trees[myroot]["vartree"].settings
+               mysettings.unlock()
+               adjust_config(myopts, mysettings)
+               mysettings.lock()
+               del myroot, mysettings
+
+       spinner = stdout_spinner()
+       if "candy" in settings.features:
+               spinner.update = spinner.update_scroll
+
+       portage.deprecated_profile_check()
+
+       #Freeze the portdbapi for enhanced performance:
+       for myroot in trees:
+               trees[myroot]["porttree"].dbapi.freeze()
+               del myroot
+
+       if "moo" in myfiles:
+               print """
+
+  Larry loves Gentoo (""" + os.uname()[0] + """)
+
+ _______________________
+< Have you mooed today? >
+ -----------------------
+        \   ^__^
+         \  (oo)\_______
+            (__)\       )\/\ 
+                ||----w |
+                ||     ||
+
+"""
+
+       if (myaction in ["world", "system"]) and myfiles:
+               print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
+               sys.exit(1)
+
+       for x in myfiles:
+               ext = os.path.splitext(x)[1]
+               if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
+                       print "emerging by path implies --oneshot... adding --oneshot to options."
+                       print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
+                       break
+
+       if ("--tree" in myopts) and ("--columns" in myopts):
+               print "emerge: can't specify both of \"--tree\" and \"--columns\"."
+               sys.exit(1)
+
+       if ("--quiet" in myopts):
+               spinner.update = spinner.update_quiet
+               portage.util.noiselimit = -1
+
+       # Always create packages if FEATURES=buildpkg
+       # Imply --buildpkg if --buildpkgonly
+       if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
+               if "--buildpkg" not in myopts:
+                       myopts["--buildpkg"] = True
+
+       # Also allow -S to invoke search action (-sS)
+       if ("--searchdesc" in myopts):
+               if myaction and myaction != "search":
+                       myfiles.append(myaction)
+               if "--search" not in myopts:
+                       myopts["--search"] = True
+               myaction = "search"
+
+       # Always try and fetch binary packages if FEATURES=getbinpkg
+       if ("getbinpkg" in settings.features):
+               myopts["--getbinpkg"] = True
+
+       if "--skipfirst" in myopts and "--resume" not in myopts:
+               myopts["--resume"] = True
+
+       if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
+               myopts["--usepkgonly"] = True
+
+       if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
+               myopts["--getbinpkg"] = True
+
+       if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
+               myopts["--usepkg"] = True
+
+       # Also allow -K to apply --usepkg/-k
+       if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
+               myopts["--usepkg"] = True
+
+       # Allow -p to remove --ask
+       if ("--pretend" in myopts) and ("--ask" in myopts):
+               print ">>> --pretend disables --ask... removing --ask from options."
+               del myopts["--ask"]
+
+       # forbid --ask when not in a terminal
+       # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
+       if ("--ask" in myopts) and (not sys.stdin.isatty()):
+               portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
+                       noiselevel=-1)
+               sys.exit(1)
+
+       if settings.get("PORTAGE_DEBUG", "") == "1":
+               spinner.update = spinner.update_quiet
+               portage.debug=1
+               if "python-trace" in settings.features:
+                       import portage.debug
+                       portage.debug.set_trace(True)
+
+       if ("--resume" in myopts):
+               if "--tree" in myopts:
+                       print "* --tree is currently broken with --resume. Disabling..."
+                       del myopts["--tree"]
+
+       if not ("--quiet" in myopts):
+               if not sys.stdout.isatty() or ("--nospinner" in myopts):
+                       spinner.update = spinner.update_basic
+
+       if "--version" in myopts:
+               print getportageversion(settings["PORTDIR"], settings["ROOT"],
+                       settings.profile_path, settings["CHOST"],
+                       trees[settings["ROOT"]]["vartree"].dbapi)
+               sys.exit(0)
+       elif "--help" in myopts:
+               emerge.help.help(myaction, myopts, portage.output.havecolor)
+               sys.exit(0)
+
+       if portage.wheelgid == portage.portage_gid:
+               print "emerge: wheel group use is being deprecated. Please update group and passwd to"
+               print "        include the portage user as noted above, and then use group portage."
+
+       if "--debug" in myopts:
+               print "myaction", myaction
+               print "myopts", myopts
+
+       if not myaction and not myfiles and "--resume" not in myopts:
+               emerge.help.help(myaction, myopts, portage.output.havecolor)
+               sys.exit(1)
+
+       # check if root user is the current user for the actions where emerge needs this
+       if portage.secpass < 2:
+               # We've already allowed "--version" and "--help" above.
+               if "--pretend" not in myopts and \
+               myaction not in ("search","info"):
+                       need_superuser = not \
+                               ("--fetchonly" in myopts or \
+                               "--fetch-all-uri" in myopts or \
+                               myaction in ("metadata", "regen"))
+                       if portage.secpass < 1 or \
+                               need_superuser:
+                               if need_superuser:
+                                       access_desc = "superuser"
+                               else:
+                                       access_desc = "portage group"
+                               # Always show portage_group_warning() when only portage group
+                               # access is required but the user is not in the portage group.
+                               from portage.data import portage_group_warning
+                               if "--ask" in myopts:
+                                       myopts["--pretend"] = True
+                                       del myopts["--ask"]
+                                       print ("%s access would be required... " + \
+                                               "adding --pretend to options.\n") % access_desc
+                                       if portage.secpass < 1 and not need_superuser:
+                                               portage_group_warning()
+                               else:
+                                       sys.stderr.write(("emerge: %s access would be " + \
+                                               "required.\n\n") % access_desc)
+                                       if portage.secpass < 1 and not need_superuser:
+                                               portage_group_warning()
+                                       return 1
+
+       disable_emergelog = False
+       for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
+               if x in myopts:
+                       disable_emergelog = True
+                       break
+       if myaction in ("search", "info"):
+               disable_emergelog = True
+       if disable_emergelog:
+               """ Disable emergelog for everything except build or unmerge
+               operations.  This helps minimize parallel emerge.log entries that can
+               confuse log parsers.  We especially want it disabled during
+               parallel-fetch, which uses --resume --fetchonly."""
+               global emergelog
+               def emergelog(*pargs, **kargs):
+                       pass
+
+       if not "--pretend" in myopts:
+               emergelog(xterm_titles, "Started emerge on: "+\
+                       time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
+               myelogstr=""
+               if myopts:
+                       myelogstr=" ".join(myopts)
+               if myaction:
+                       myelogstr+=" "+myaction
+               if myfiles:
+                       myelogstr+=" "+" ".join(myfiles)
+               emergelog(xterm_titles, " *** emerge " + myelogstr)
+
+       def emergeexitsig(signum, frame):
+               signal.signal(signal.SIGINT, signal.SIG_IGN)
+               signal.signal(signal.SIGTERM, signal.SIG_IGN)
+               portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
+               sys.exit(100+signum)
+       signal.signal(signal.SIGINT, emergeexitsig)
+       signal.signal(signal.SIGTERM, emergeexitsig)
+
+       def emergeexit():
+               """This gets out final log message in before we quit."""
+               if "--pretend" not in myopts:
+                       emergelog(xterm_titles, " *** terminating.")
+               if "notitles" not in settings.features:
+                       xtermTitleReset()
+       portage.atexit_register(emergeexit)
+
+       if myaction in ("config", "metadata", "regen", "sync"):
+               if "--pretend" in myopts:
+                       sys.stderr.write(("emerge: The '%s' action does " + \
+                               "not support '--pretend'.\n") % myaction)
+                       return 1
+       if "sync" == myaction:
+               action_sync(settings, trees, mtimedb, myopts, myaction)
+       elif "metadata" == myaction:
+               action_metadata(settings, portdb, myopts)
+       elif myaction=="regen":
+               validate_ebuild_environment(trees)
+               action_regen(settings, portdb)
+       # HELP action
+       elif "config"==myaction:
+               validate_ebuild_environment(trees)
+               action_config(settings, trees, myopts, myfiles)
+       
+       # INFO action
+       elif "info"==myaction:
+               action_info(settings, trees, myopts, myfiles)
+
+       # SEARCH action
+       elif "search"==myaction:
+               validate_ebuild_environment(trees)
+               action_search(settings, portdb, trees["/"]["vartree"],
+                       myopts, myfiles, spinner)
+       elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
+               validate_ebuild_environment(trees)
+               vartree = trees[settings["ROOT"]]["vartree"]
+               if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
+                       mtimedb["ldpath"]):
+                       if "--pretend" not in myopts:
+                               post_emerge(settings, mtimedb, 0)
+
+       elif "depclean"==myaction:
+               validate_ebuild_environment(trees)
+               action_depclean(settings, trees, mtimedb["ldpath"],
+                       myopts, spinner)
+               if "--pretend" not in myopts:
+                       post_emerge(settings, mtimedb, 0)
+       # "update", "system", or just process files:
+       else:
+               validate_ebuild_environment(trees)
+               action_build(settings, trees, mtimedb,
+                       myopts, myaction, myfiles, spinner)
+               if "--pretend" not in myopts:
+                       post_emerge(settings, mtimedb, 0)
+
+if __name__ == "__main__":
+       retval = emerge_main()
+       sys.exit(retval)