summaryrefslogtreecommitdiffstats
path: root/pym/emerge
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2007-10-16 06:15:01 +0000
committerZac Medico <zmedico@gentoo.org>2007-10-16 06:15:01 +0000
commiteedc9cefc37526a6d1f224458fe3b1aef81e0de3 (patch)
tree70f0b8ba35af4014bb71bf75216c6366a37686fe /pym/emerge
parent95a6a1859d46c193980b4bcb46d5cea23ee1e068 (diff)
downloadportage-eedc9cefc37526a6d1f224458fe3b1aef81e0de3.tar.gz
portage-eedc9cefc37526a6d1f224458fe3b1aef81e0de3.tar.bz2
portage-eedc9cefc37526a6d1f224458fe3b1aef81e0de3.zip
Move the emerge module to _emerge to make it private
since it's mostly unsuitable for api consumers at this time. svn path=/main/trunk/; revision=8142
Diffstat (limited to 'pym/emerge')
-rw-r--r--pym/emerge/__init__.py6844
-rw-r--r--pym/emerge/help.py394
2 files changed, 0 insertions, 7238 deletions
diff --git a/pym/emerge/__init__.py b/pym/emerge/__init__.py
deleted file mode 100644
index e1fa5e4b6..000000000
--- a/pym/emerge/__init__.py
+++ /dev/null
@@ -1,6844 +0,0 @@
-#!/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, CACHE_PATH, PRIVATE_PATH, USER_CONFIG_PATH, GLOBAL_CONFIG_PATH
-
-import emerge.help
-import portage.xpak, commands, errno, re, socket, time, types
-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")
-# white looks bad on terminals with white background
-from portage.output import bold as white
-
-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
-from portage.util import writemsg
-from portage.sets import InternalPackageSet, SetConfig, make_default_config
-from portage.sets.profiles import PackagesSystemSet as SystemSet
-from portage.sets.files import WorldSet
-
-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 = ["Yes", "No"]
- colours = [
- create_color_func("PROMPT_CHOICE_DEFAULT"),
- create_color_func("PROMPT_CHOICE_OTHER")
- ]
- 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)
-
-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:
- 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 = set(["recurse"])
- if "--update" in myopts or \
- "--newuse" in myopts or \
- "--reinstall" in myopts or \
- "--noreplace" in myopts or \
- myaction in ("system", "world"):
- myparams.add("selective")
- if "--emptytree" in myopts:
- myparams.add("empty")
- myparams.discard("selective")
- if "--nodeps" in myopts:
- myparams.discard("recurse")
- if "--deep" in myopts:
- myparams.add("deep")
- return myparams
-
-# search functionality
-class search(object):
-
- #
- # class constants
- #
- VERSION_SHORT=1
- VERSION_RELEASE=2
-
- #
- # public interface
- #
- def __init__(self, settings, portdb, vartree, spinner, searchdesc,
- verbose, setconfig):
- """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
- self.setconfig = setconfig
-
- 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":[], "set":[]}
- else:
- self.searchdesc=0
- self.matches = {"pkg":[], "set":[]}
- print "Searching... ",
-
- regexsearch = False
- if self.searchkey.startswith('%'):
- regexsearch = True
- self.searchkey = self.searchkey[1:]
- if self.searchkey.startswith('@'):
- 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.sdict = self.setconfig.getSets()[0]
- for setname in self.sdict:
- self.spinner.update()
- if match_category:
- match_string = setname
- else:
- match_string = setname.split("/")[-1]
-
- if self.searchre.search(match_string):
- self.matches["set"].append([setname, False])
- elif self.searchdesc:
- if self.searchre.search(sdict[setname].getMetadata("DESCRIPTION")):
- self.matches["set"].append([setname, False])
-
- self.mlen=0
- for mtype in self.matches:
- 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:
- for match,masked in self.matches[mtype]:
- full_package = None
- 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))
- elif mtype == "desc":
- full_package = match
- match = portage.pkgsplit(match)[0]
- elif mtype == "set":
- print green("*")+" "+white(match)
- print " ", darkgreen("Description:")+" ", self.sdict[match].getMetadata("DESCRIPTION")
- print
- 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_set = WorldSet(vardb.settings["ROOT"])
- world_set.lock()
- worldlist = list(world_set) # loads latest from disk
- 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)
-
- world_set.replace(newworldlist)
- world_set.unlock()
-
-
-class RootConfig(object):
- """This is used internally by depgraph to track information about a
- particular $ROOT."""
- def __init__(self, trees):
- self.trees = trees
- self.settings = trees["vartree"].settings
- self.root = self.settings["ROOT"]
- self.sets = {}
- world_set = WorldSet(self.root)
- self.sets["world"] = world_set
- system_set = SystemSet(self.settings.profiles)
- self.sets["system"] = system_set
-
-def create_world_atom(pkg_key, metadata, args_set, root_config):
- """Create a new atom for the world file if one does not exist. If the
- argument atom is precise enough to identify a specific slot then a slot
- atom will be returned. Atoms that are in the system set may also be stored
- in world since system atoms can only match one slot while world atoms can
- be greedy with respect to slots. Unslotted system packages will not be
- stored in world."""
- arg_atom = args_set.findAtomForPackage(pkg_key, metadata)
- cp = portage.dep_getkey(arg_atom)
- new_world_atom = cp
- sets = root_config.sets
- portdb = root_config.trees["porttree"].dbapi
- vardb = root_config.trees["vartree"].dbapi
- available_slots = set(portdb.aux_get(cpv, ["SLOT"])[0] \
- for cpv in portdb.match(cp))
- slotted = len(available_slots) > 1 or \
- (len(available_slots) == 1 and "0" not in available_slots)
- if not slotted:
- # check the vdb in case this is multislot
- available_slots = set(vardb.aux_get(cpv, ["SLOT"])[0] \
- for cpv in vardb.match(cp))
- slotted = len(available_slots) > 1 or \
- (len(available_slots) == 1 and "0" not in available_slots)
- if slotted and arg_atom != cp:
- # If the user gave a specific atom, store it as a
- # slot atom in the world file.
- slot_atom = "%s:%s" % (cp, metadata["SLOT"])
- # First verify the slot is in the portage tree to avoid
- # adding a bogus slot like that produced by multislot.
- if portdb.match(slot_atom):
- # Now verify that the argument is precise enough to identify a
- # specific slot.
- matches = portdb.match(arg_atom)
- matched_slots = set()
- for cpv in matches:
- matched_slots.add(portdb.aux_get(cpv, ["SLOT"])[0])
- if len(matched_slots) == 1:
- new_world_atom = slot_atom
- if new_world_atom == sets["world"].findAtomForPackage(pkg_key, metadata):
- # Both atoms would be identical, so there's nothing to add.
- return None
- if not slotted:
- # Unlike world atoms, system atoms are not greedy for slots, so they
- # can't be safely excluded from world if they are slotted.
- system_atom = sets["system"].findAtomForPackage(pkg_key, metadata)
- if system_atom:
- if not portage.dep_getkey(system_atom).startswith("virtual/"):
- return None
- # System virtuals aren't safe to exclude from world since they can
- # match multiple old-style virtuals but only one of them will be
- # pulled in by update or depclean.
- providers = portdb.mysettings.getvirtuals().get(
- portage.dep_getkey(system_atom))
- if providers and len(providers) == 1 and providers[0] == cp:
- return None
- return new_world_atom
-
-def filter_iuse_defaults(iuse):
- for flag in iuse:
- if flag.startswith("+") or 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.
- MEDIUM_SOFT The upper boundary for medium-soft dependencies.
- SOFT The upper boundary for soft dependencies.
- MIN The lower boundary for soft dependencies.
- """
- __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime", "runtime_post", "rebuild")
- MEDIUM = -1
- MEDIUM_SOFT = -2
- SOFT = -3
- MIN = -6
- 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.runtime_post:
- return -2
- if self.buildtime:
- if self.rebuild:
- return -3
- return -4
- if self.runtime:
- return -5
- if self.runtime_post:
- return -6
- return -6
- 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.MEDIUM_SOFT:
- return "medium"
- if myvalue > self.SOFT:
- return "medium-soft"
- 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, db_keys):
- self.root = real_vartree.root
- self.settings = real_vartree.settings
- mykeys = db_keys[:]
- for required_key in ("COUNTER", "SLOT"):
- if required_key not in mykeys:
- mykeys.append(required_key)
- 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)
- 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)
-
-def cpv_sort_descending(cpv_list):
- """Sort in place, returns None."""
- if len(cpv_list) <= 1:
- return
- first_split = portage.catpkgsplit(cpv_list[0])
- cat = first_split[0]
- cpv_list[0] = first_split[1:]
- for i in xrange(1, len(cpv_list)):
- cpv_list[i] = portage.catpkgsplit(cpv_list[i])[1:]
- cpv_list.sort(portage.pkgcmp, reverse=True)
- for i, (pn, ver, rev) in enumerate(cpv_list):
- if rev == "r0":
- cpv = cat + "/" + pn + "-" + ver
- else:
- cpv = cat + "/" + pn + "-" + ver + "-" + rev
- cpv_list[i] = cpv
-
-def visible(pkgsettings, cpv, metadata, built=False, installed=False):
- """
- Check if a package is visible. This can raise an InvalidDependString
- exception if LICENSE is invalid.
- TODO: optionally generate a list of masking reasons
- @rtype: Boolean
- @returns: True if the package is visible, False otherwise.
- """
- if built and not installed and \
- metadata["CHOST"] != pkgsettings["CHOST"]:
- return False
- if not portage.eapi_is_supported(metadata["EAPI"]):
- return False
- if pkgsettings.getMissingKeywords(cpv, metadata):
- return False
- if pkgsettings.getMaskAtom(cpv, metadata):
- return False
- if pkgsettings.getProfileMaskAtom(cpv, metadata):
- return False
- if pkgsettings.getMissingLicenses(cpv, metadata):
- return False
- return True
-
-def iter_atoms(deps):
- """Take a dependency structure as returned by paren_reduce or use_reduce
- and iterate over all the atoms."""
- i = iter(deps)
- for x in i:
- if isinstance(x, basestring):
- if x == '||' or x.endswith('?'):
- for x in iter_atoms(i.next()):
- yield x
- else:
- yield x
- else:
- for x in iter_atoms(x):
- yield x
-
-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 keys(self):
- """This needs to be implemented so that self.__repr__() doesn't raise
- an AttributeError."""
- if self._cache_data and "blockers" in self._cache_data:
- return self._cache_data["blockers"].keys()
- return []
-
-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(object):
-
- pkg_tree_map = {
- "ebuild":"porttree",
- "binary":"bintree",
- "installed":"vartree"}
-
- _mydbapi_keys = [
- "CHOST", "DEPEND", "EAPI", "IUSE", "KEYWORDS",
- "LICENSE", "PDEPEND", "PROVIDE", "RDEPEND",
- "repository", "RESTRICT", "SLOT", "USE"]
-
- _dep_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
-
- 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 = {}
- # Maps nodes to the reasons they were selected for reinstallation.
- self._reinstall_nodes = {}
- self.mydbapi = {}
- self.trees = {}
- self.roots = {}
- # Contains a filtered view of preferred packages that are selected
- # from available repositories.
- self._filtered_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._mydbapi_keys)
- 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
- self.roots[myroot] = RootConfig(self.trees[myroot])
- # 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._filtered_trees[myroot] = {}
- self._filtered_trees[myroot]["vartree"] = self.trees[myroot]["vartree"]
- def filtered_tree():
- pass
- filtered_tree.dbapi = portage.fakedbapi(
- settings=self.pkgsettings[myroot], exclusive_slots=False)
- self._filtered_trees[myroot]["porttree"] = filtered_tree
- self._filtered_trees[myroot]["atoms"] = set()
- dbs = []
- portdb = self.trees[myroot]["porttree"].dbapi
- bindb = self.trees[myroot]["bintree"].dbapi
- vardb = self.trees[myroot]["vartree"].dbapi
- # (db, pkg_type, built, installed, db_keys)
- if "--usepkgonly" not in self.myopts:
- db_keys = list(portdb._aux_cache_keys)
- dbs.append((portdb, "ebuild", False, False, db_keys))
- if "--usepkg" in self.myopts:
- db_keys = list(bindb._aux_cache_keys)
- dbs.append((bindb, "binary", True, False, db_keys))
- db_keys = self._mydbapi_keys
- dbs.append((vardb, "installed", True, True, db_keys))
- self._filtered_trees[myroot]["dbs"] = dbs
- 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=[]
- # contains all sets added to the graph
- self._sets = {}
- # contains atoms given as arguments
- self._sets["args"] = InternalPackageSet()
- # contains all atoms from all sets added to the graph, including
- # atoms given as arguments
- self._set_atoms = InternalPackageSet()
- # contains all nodes pulled in by self._set_atoms
- self._set_nodes = set()
- self.blocker_digraph = digraph()
- self.blocker_parents = {}
- self._unresolved_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 _reinstall_for_flags(self, forced_flags,
- orig_use, orig_iuse, cur_use, cur_iuse):
- """Return a set of flags that trigger reinstallation, or None if there
- are no such flags."""
- if "--newuse" in self.myopts:
- flags = orig_iuse.symmetric_difference(
- cur_iuse).difference(forced_flags)
- flags.update(orig_iuse.intersection(orig_use).symmetric_difference(
- cur_iuse.intersection(cur_use)))
- if flags:
- return flags
- elif "changed-use" == self.myopts.get("--reinstall"):
- flags = orig_iuse.intersection(orig_use).symmetric_difference(
- cur_iuse.intersection(cur_use))
- if flags:
- return flags
- return None
-
- def create(self, mybigkey, myparent=None, addme=1, metadata=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
- """
-
- # unused parameters
- rev_dep = False
-
- mytype, myroot, mykey = mybigkey
-
- # 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 metadata is None:
- metadata = dict(izip(self._mydbapi_keys,
- mydbapi.aux_get(mykey, self._mydbapi_keys)))
- if mytype == "ebuild":
- pkgsettings.setcpv(mykey, mydb=portdb)
- metadata["USE"] = pkgsettings["USE"]
- myuse = metadata["USE"].split()
-
- if not arg and myroot == self.target_root:
- try:
- arg = self._set_atoms.findAtomForPackage(mykey, metadata)
- except portage.exception.InvalidDependString, e:
- if mytype != "installed":
- show_invalid_depstring_notice(tuple(mybigkey+["merge"]),
- metadata["PROVIDE"], str(e))
- return 0
- del e
-
- if "--nodeps" not in self.myopts:
- self.spinner.update()
-
- merging = mytype != "installed"
-
- if addme and mytype != "installed":
- mybigkey.append("merge")
- else:
- mybigkey.append("nomerge")
- jbigkey = tuple(mybigkey)
-
- if addme:
- slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
- if merging and \
- "empty" not in self.myparams and \
- vardbapi.match(slot_atom):
- # Increase the priority of dependencies on packages that
- # are being rebuilt. This optimizes merge order so that
- # dependencies are rebuilt/updated as soon as possible,
- # which is needed especially when emerge is called by
- # revdep-rebuild since dependencies may be affected by ABI
- # breakage that has rendered them useless. Don't adjust
- # priority here when in "empty" mode since all packages
- # are being merged in that case.
- priority.rebuild = True
-
- 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.
- if existing_node != myparent:
- # Refuse to make a node depend on itself so that
- # we don't create a bogus circular dependency
- # in self.altlist().
- self._parent_child_digraph.add(existing_node, myparent)
- self.digraph.addnode(existing_node, myparent,
- priority=priority)
- return 1
- else:
- if jbigkey in self._slot_collision_nodes:
- return 1
- # 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)
- # 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
-
- if rev_dep and myparent:
- self.digraph.addnode(myparent, jbigkey,
- priority=priority)
- else:
- self.digraph.addnode(jbigkey, myparent,
- priority=priority)
-
- if arg:
- self._set_nodes.add(jbigkey)
-
- # 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"]
- for k in depkeys:
- edepend[k] = metadata[k]
-
- if mytype == "ebuild":
- if "--buildpkgonly" in self.myopts:
- edepend["RDEPEND"] = ""
- edepend["PDEPEND"] = ""
- bdeps_satisfied = False
- if mytype in ("installed", "binary"):
- if self.myopts.get("--with-bdeps", "n") == "y":
- # Pull in build time deps as requested, but marked them as
- # "satisfied" since they are not strictly required. This allows
- # more freedom in the merge order calculation for solving
- # circular dependencies. Don't convert to PDEPEND since that
- # could make --with-bdeps=y less effective if it is used to
- # adjust merge order to prevent built_with_use() calls from
- # failing.
- bdeps_satisfied = True
- else:
- # built packages do not have build time dependencies.
- 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,
- satisfied=bdeps_satisfied),
- 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(runtime_post=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
- dbs = self._filtered_trees[myroot]["dbs"]
- filtered_db = self._filtered_trees[myroot]["porttree"].dbapi
- vardb = self.trees[myroot]["vartree"].dbapi
- portdb = self.trees[myroot]["porttree"].dbapi
- bindb = self.trees[myroot]["bintree"].dbapi
- pkgsettings = self.pkgsettings[myroot]
- arg_atoms = []
- 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"
- return 0, myfavorites
- 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")
- return 0, myfavorites
- if not self.create(["binary", myroot, mykey],
- addme=("--onlydeps" not in self.myopts), arg=x):
- return (0,myfavorites)
- arg_atoms.append((x, "="+mykey))
- elif ext==".ebuild":
- ebuild_path = portage.util.normalize_path(os.path.abspath(x))
- pkgdir = os.path.dirname(ebuild_path)
- tree_root = os.path.dirname(os.path.dirname(pkgdir))
- cp = pkgdir[len(tree_root)+1:]
- e = portage.exception.PackageNotFound(
- ("%s is not in a valid portage tree " + \
- "hierarchy or does not exist") % x)
- if not portage.isvalidatom(cp):
- raise e
- cat = portage.catsplit(cp)[0]
- mykey = cat + "/" + os.path.basename(ebuild_path[:-7])
- if not portage.isvalidatom("="+mykey):
- raise e
- ebuild_path = portdb.findname(mykey)
- if ebuild_path:
- if ebuild_path != os.path.join(os.path.realpath(tree_root),
- cp, os.path.basename(ebuild_path)):
- print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
- return 0, myfavorites
- 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, arg=x):
- return (0,myfavorites)
- arg_atoms.append((x, "="+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:
- try:
- for db, pkg_type, built, installed, db_keys in dbs:
- mykey = portage.dep_expand(x,
- mydb=db, settings=pkgsettings)
- if portage.dep_getkey(mykey).startswith("null/"):
- continue
- break
- except ValueError, e:
- if not e.args or not isinstance(e.args[0], list) or \
- len(e.args[0]) < 2:
- raise
- mykey = portage.dep_expand(x,
- mydb=vardb, settings=pkgsettings)
- cp = portage.dep_getkey(mykey)
- if cp.startswith("null/") or \
- cp not in e[0]:
- raise
- del e
- arg_atoms.append((x, mykey))
- except ValueError, errpkgs:
- if not e.args or not isinstance(e.args[0], list) or \
- len(e.args[0]) < 2:
- raise
- 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
- return False, myfavorites
-
- 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."""
- greedy_atoms = []
- for myarg, atom in arg_atoms:
- greedy_atoms.append((myarg, atom))
- mykey = portage.dep_getkey(atom)
- myslots = set()
- for cpv in vardb.match(mykey):
- myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
- if myslots:
- if not self._populate_filtered_repo(myroot, atom,
- exclude_installed=True):
- return False, myfavorites
- mymatches = filtered_db.match(atom)
- best_pkg = portage.best(mymatches)
- if best_pkg:
- best_slot = filtered_db.aux_get(best_pkg, ["SLOT"])[0]
- myslots.add(best_slot)
- if len(myslots) > 1:
- for myslot in myslots:
- myslot_atom = "%s:%s" % (mykey, myslot)
- if not self._populate_filtered_repo(
- myroot, myslot_atom,
- exclude_installed=True):
- return False, myfavorites
- if filtered_db.match(myslot_atom):
- greedy_atoms.append((myarg, myslot_atom))
- arg_atoms = greedy_atoms
-
- # Since populate_filtered_repo() was called with the
- # exclude_installed flag, these atoms will need to be processed
- # again in case installed packages are required to satisfy
- # dependencies.
- self._filtered_trees[myroot]["atoms"].clear()
-
- oneshot = "--oneshot" in self.myopts or \
- "--onlydeps" in self.myopts
- """ These are used inside self.create() in order to ensure packages
- that happen to match arguments are not incorrectly marked as nomerge."""
- args_set = self._sets["args"]
- for myarg, myatom in arg_atoms:
- if myatom in args_set:
- continue
- args_set.add(myatom)
- self._set_atoms.add(myatom)
- if not oneshot:
- myfavorites.append(myatom)
- 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)
-
- 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 _populate_filtered_repo(self, myroot, depstring,
- myparent=None, myuse=None, exclude_installed=False):
- """Extract all of the atoms from the depstring, select preferred
- packages from appropriate repositories, and use them to populate
- the filtered repository."""
-
- filtered_db = self._filtered_trees[myroot]["porttree"].dbapi
- pkgsettings = self.pkgsettings[myroot]
- usepkgonly = "--usepkgonly" in self.myopts
- if myparent:
- p_type, p_root, p_key, p_status = myparent
-
- from portage.dep import paren_reduce, use_reduce
- try:
- if myparent and p_type == "installed":
- portage.dep._dep_check_strict = False
- try:
- atoms = paren_reduce(depstring)
- atoms = use_reduce(atoms, uselist=myuse)
- atoms = list(iter_atoms(atoms))
- for x in atoms:
- if portage.dep._dep_check_strict and \
- not portage.isvalidatom(x, allow_blockers=True):
- raise portage.exception.InvalidDependString(
- "Invalid atom: %s" % x)
- except portage.exception.InvalidDependString, e:
- if myparent:
- show_invalid_depstring_notice(
- myparent, depstring, str(e))
- else:
- sys.stderr.write("\n%s\n%s\n" % (depstring, str(e)))
- return 0
- finally:
- portage.dep._dep_check_strict = True
-
- filtered_atoms = self._filtered_trees[myroot]["atoms"]
- dbs = self._filtered_trees[myroot]["dbs"]
- old_virts = pkgsettings.getvirtuals()
- while atoms:
- x = atoms.pop()
- if x.startswith("!"):
- continue
- if x in filtered_atoms:
- continue
- filtered_atoms.add(x)
- cp = portage.dep_getkey(x)
- cat = portage.catsplit(cp)[0]
- slot = portage.dep.dep_getslot(x)
- is_virt = cp.startswith("virtual/")
- atom_populated = False
- for db, pkg_type, built, installed, db_keys in dbs:
- if installed and \
- (exclude_installed or not usepkgonly):
- continue
- cpv_list = db.cp_list(cp)
- if not cpv_list:
- if is_virt:
- # old-style virtual
- # Create a transformed atom for each choice
- # and add it to the stack for processing.
- for choice in old_virts.get(cp, []):
- atoms.append(x.replace(cp, choice))
- # Maybe a new-style virtual exists in another db, so
- # we have to try all of them to prevent the old-style
- # virtuals from overriding available new-styles.
- continue
- cpv_sort_descending(cpv_list)
- for cpv in cpv_list:
- if filtered_db.cpv_exists(cpv):
- continue
- if not portage.match_from_list(x, [cpv]):
- continue
- if is_virt:
- mykeys = db_keys[:]
- mykeys.extend(self._dep_keys)
- else:
- mykeys = db_keys
- try:
- metadata = dict(izip(mykeys,
- db.aux_get(cpv, mykeys)))
- except KeyError:
- # masked by corruption
- continue
- if slot is not None:
- if slot != metadata["SLOT"]:
- continue
- if not built:
- if (is_virt or "?" in metadata["LICENSE"]):
- pkgsettings.setcpv(cpv, mydb=metadata)
- metadata["USE"] = pkgsettings["USE"]
- else:
- metadata["USE"] = ""
-
- try:
- if not visible(pkgsettings, cpv, metadata,
- built=built, installed=installed):
- continue
- except portage.exception.InvalidDependString:
- # masked by corruption
- continue
-
- filtered_db.cpv_inject(cpv, metadata=metadata)
- if not is_virt:
- # break here since we only want the best version
- # for now (eventually will be configurable).
- atom_populated = True
- break
- # For new-style virtuals, we explore all available
- # versions and recurse on their deps. This is a
- # preparation for the lookahead that happens when
- # new-style virtuals are expanded by dep_check().
- virtual_deps = " ".join(metadata[k] \
- for k in self._dep_keys)
- try:
- if installed:
- portage.dep._dep_check_strict = False
- try:
- deps = paren_reduce(virtual_deps)
- deps = use_reduce(deps,
- uselist=metadata["USE"].split())
- for y in iter_atoms(deps):
- if portage.dep._dep_check_strict and \
- not portage.isvalidatom(y,
- allow_blockers=True):
- raise portage.exception.InvalidDependString(
- "Invalid atom: %s" % y)
- atoms.append(y)
- except portage.exception.InvalidDependString, e:
- show_invalid_depstring_notice(
- (pkg_type, myroot, cpv, "nomerge"),
- virtual_deps, str(e))
- return 0
- finally:
- portage.dep._dep_check_strict = True
- if atom_populated:
- break
- return 1
-
- 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
- """
-
- if not depstring:
- return 1 # nothing to do
-
- filtered_db = self._filtered_trees[myroot]["porttree"].dbapi
- dbs = self._filtered_trees[myroot]["dbs"]
- 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
-
- if not self._populate_filtered_repo(
- myroot, depstring, myparent=myparent, myuse=myuse):
- return 0
-
- #processing dependencies
- """ Call portage.dep_check to evaluate the use? conditionals and make sure all
- dependencies are satisfiable. """
- if arg:
- mymerge = [depstring]
- pprovided = pkgsettings.pprovideddict.get(
- portage.dep_getkey(depstring))
- if pprovided and portage.match_from_list(depstring, pprovided):
- mymerge = []
- else:
- try:
- if myparent and p_type == "installed":
- portage.dep._dep_check_strict = False
- mycheck = portage.dep_check(depstring, None,
- pkgsettings, myuse=myuse,
- myroot=myroot, trees=self._filtered_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:
- # A provided package has been specified on the command line. The
- # package will not be merged and a warning will be displayed.
- if depstring in self._set_atoms:
- self._pprovided_args.append((arg, depstring))
-
- 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.
- p_db = self.mydbapi[p_root] # contains cached metadata
- if myparent in self._slot_collision_nodes:
- # The metadata isn't cached due to the slot collision.
- p_db = self.trees[p_root][self.pkg_tree_map[p_type]].dbapi
- try:
- self.pkgsettings[p_root].setinst(p_key, p_db)
- # For consistency, also update the global virtuals.
- settings = self.roots[p_root].settings
- settings.unlock()
- settings.setinst(p_key, p_db)
- settings.lock()
- except portage.exception.InvalidDependString, e:
- provide = p_db.aux_get(p_key, ["PROVIDE"])[0]
- show_invalid_depstring_notice(myparent, provide, str(e))
- del e
- return 0
-
- if "--debug" in self.myopts:
- print "Candidates:",mymerge
- for x in mymerge:
- selected_pkg = None
- if x.startswith("!"):
- if "--buildpkgonly" not in self.myopts and \
- "--nodeps" not in self.myopts and \
- myparent not in self._slot_collision_nodes:
- p_type, p_root, p_key, p_status = myparent
- if p_type != "installed" and p_status != "merge":
- # It's safe to ignore blockers from --onlydeps nodes.
- continue
- self.blocker_parents.setdefault(
- ("blocks", p_root, x[1:]), set()).add(myparent)
- continue
- else:
- # List of acceptable packages, ordered by type preference.
- matched_packages = []
- existing_node = None
- myeb = None
- usepkgonly = "--usepkgonly" in self.myopts
- empty = "empty" in self.myparams
- selective = "selective" in self.myparams
- for find_existing_node in True, False:
- if existing_node:
- break
- for db, pkg_type, built, installed, db_keys in dbs:
- if existing_node:
- break
- if installed and not find_existing_node and \
- (matched_packages or empty):
- # We only need to select an installed package here
- # if there is no other choice.
- continue
- if hasattr(db, "xmatch"):
- cpv_list = db.xmatch("match-all", x)
- else:
- cpv_list = db.match(x)
- cpv_sort_descending(cpv_list)
- for cpv in cpv_list:
- reinstall_for_flags = None
- try:
- metadata = dict(izip(db_keys,
- db.aux_get(cpv, db_keys)))
- except KeyError:
- continue
- if not built:
- if "?" in metadata["LICENSE"]:
- pkgsettings.setcpv(cpv, mydb=metadata)
- metadata["USE"] = pkgsettings.get("USE","")
- else:
- metadata["USE"] = ""
- if not installed:
- try:
- if not visible(pkgsettings, cpv, metadata,
- built=built, installed=installed):
- continue
- except portage.exception.InvalidDependString:
- # masked by corruption
- continue
- # At this point, we've found the highest visible
- # match from the current repo. Any lower versions
- # from this repo are ignored, so this so the loop
- # will always end with a break statement below
- # this point.
- if find_existing_node:
- slot_atom = "%s:%s" % (
- portage.cpv_getkey(cpv), metadata["SLOT"])
- existing_node = self._slot_node_map[myroot].get(
- slot_atom)
- if not existing_node:
- break
- e_type, myroot, e_cpv, e_status = existing_node
- metadata = dict(izip(self._mydbapi_keys,
- self.mydbapi[myroot].aux_get(
- e_cpv, self._mydbapi_keys)))
- cpv_slot = "%s:%s" % (e_cpv, metadata["SLOT"])
- if portage.dep.match_from_list(x, [cpv_slot]):
- matched_packages.append(
- ([e_type, myroot, e_cpv], metadata))
- else:
- existing_node = None
- break
- # Compare built package to current config and
- # reject the built package if necessary.
- if built and not installed and \
- ("--newuse" in self.myopts or \
- "--reinstall" in self.myopts):
- iuses = set(filter_iuse_defaults(
- metadata["IUSE"].split()))
- old_use = metadata["USE"].split()
- mydb = metadata
- if myeb and not usepkgonly:
- mydb = portdb
- if myeb:
- pkgsettings.setcpv(myeb, mydb=mydb)
- else:
- pkgsettings.setcpv(cpv, mydb=mydb)
- now_use = pkgsettings["USE"].split()
- forced_flags = set()
- forced_flags.update(pkgsettings.useforce)
- forced_flags.update(pkgsettings.usemask)
- cur_iuse = iuses
- if myeb and not usepkgonly:
- cur_iuse = set(filter_iuse_defaults(
- portdb.aux_get(myeb,
- ["IUSE"])[0].split()))
- if self._reinstall_for_flags(forced_flags,
- old_use, iuses,
- now_use, cur_iuse):
- break
- # Compare current config to installed package
- # and do not reinstall if possible.
- if not installed and \
- ("--newuse" in self.myopts or \
- "--reinstall" in self.myopts) and \
- vardb.cpv_exists(cpv):
- pkgsettings.setcpv(cpv, mydb=metadata)
- forced_flags = set()
- forced_flags.update(pkgsettings.useforce)
- forced_flags.update(pkgsettings.usemask)
- old_use = vardb.aux_get(cpv, ["USE"])[0].split()
- old_iuse = set(filter_iuse_defaults(
- vardb.aux_get(cpv, ["IUSE"])[0].split()))
- cur_use = pkgsettings["USE"].split()
- cur_iuse = set(filter_iuse_defaults(metadata["IUSE"].split()))
- reinstall_for_flags = \
- self._reinstall_for_flags(
- forced_flags, old_use, old_iuse,
- cur_use, cur_iuse)
- myarg = arg
- if not myarg and \
- myroot == self.target_root:
- try:
- myarg = self._set_atoms.findAtomForPackage(
- cpv, metadata)
- except portage.exception.InvalidDependString, e:
- if mytype != "installed":
- pkg_node = (pkg_type, myroot, cpv, "merge")
- show_invalid_depstring_notice(pkg_node,
- metadata["PROVIDE"], str(e))
- return 0
- del e
- if not installed and not reinstall_for_flags and \
- ("selective" in self.myparams or \
- not myarg) and \
- "empty" not in self.myparams and \
- vardb.cpv_exists(cpv):
- break
- if installed and not (selective or not myarg):
- break
- # Metadata accessed above is cached internally by
- # each db in order to optimize visibility checks.
- # Now that all possible checks visibility checks
- # are complete, it's time to pull the rest of the
- # metadata (including *DEPEND). This part is more
- # expensive, so avoid it whenever possible.
- metadata.update(izip(self._mydbapi_keys,
- db.aux_get(cpv, self._mydbapi_keys)))
- if not built:
- pkgsettings.setcpv(cpv, mydb=metadata)
- metadata["USE"] = pkgsettings.get("USE","")
- myeb = cpv
- matched_packages.append(
- ([pkg_type, myroot, cpv], metadata))
- if reinstall_for_flags:
- pkg_node = (pkg_type, myroot, cpv, "merge")
- self._reinstall_nodes[pkg_node] = \
- reinstall_for_flags
- break
-
- if not matched_packages:
- if raise_on_missing:
- raise portage.exception.PackageNotFound(x)
- if not arg:
- xinfo='"'+x+'"'
- else:
- xinfo='"'+arg+'"'
- if myparent:
- xfrom = '(dependency required by '+ \
- green('"%s"' % myparent[2]) + \
- red(' [%s]' % myparent[0]) + ')'
- masked_packages = []
- missing_licenses = []
- dbs = self._filtered_trees[myroot]["dbs"]
- for db, pkg_type, built, installed, db_keys in dbs:
- match = db.match
- if hasattr(db, "xmatch"):
- def match(atom):
- return db.xmatch("match-all", atom)
- cpv_list = match(x)
- cpv_sort_descending(cpv_list)
- for cpv in cpv_list:
- try:
- metadata = dict(izip(db_keys,
- db.aux_get(cpv, db_keys)))
- except KeyError:
- mreasons = ["corruption"]
- metadata = None
- if metadata and not built:
- if "?" in metadata["LICENSE"]:
- pkgsettings.setcpv(p, mydb=portdb)
- metadata["USE"] = pkgsettings.get("USE", "")
- else:
- metadata["USE"] = ""
- mreasons = portage.getmaskingstatus(
- cpv, metadata=metadata,
- settings=pkgsettings, portdb=portdb)
- comment, filename = None, None
- if "package.mask" in mreasons:
- comment, filename = \
- portage.getmaskingreason(
- cpv, metadata=metadata,
- settings=pkgsettings, portdb=portdb,
- return_location=True)
- if built and \
- metadata["CHOST"] != pkgsettings["CHOST"]:
- mreasons.append("CHOST: %s" % \
- metadata["CHOST"])
- missing_licenses = []
- if metadata:
- try:
- missing_licenses = \
- pkgsettings.getMissingLicenses(
- cpv, metadata)
- except portage.exception.InvalidDependString:
- # This will have already been reported
- # above via mreasons.
- pass
- masked_packages.append((cpv, mreasons,
- comment, filename, missing_licenses))
- if masked_packages:
- 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:"
- shown_licenses = set()
- shown_comments = set()
- # Maybe there is both an ebuild and a binary. Only
- # show one of them to avoid redundant appearance.
- shown_cpvs = set()
- for cpv, mreasons, comment, filename, missing_licenses in masked_packages:
- if cpv in shown_cpvs:
- continue
- shown_cpvs.add(cpv)
- print "- "+cpv+" (masked by: "+", ".join(mreasons)+")"
- if comment and comment not in shown_comments:
- print filename+":"
- print comment
- shown_comments.add(comment)
- for l in missing_licenses:
- l_path = portdb.findLicensePath(l)
- if l in shown_licenses:
- continue
- msg = ("A copy of the '%s' license" + \
- " is located at '%s'.") % (l, l_path)
- print msg
- print
- shown_licenses.add(l)
- print
- print "For more information, see MASKED PACKAGES section in the emerge man page or "
- print "refer to the Gentoo Handbook."
- 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, metadata in matched_packages:
- print (pkg[0] + ":").rjust(10), pkg[2]
-
- if len(matched_packages) > 1:
- bestmatch = portage.best(
- [pkg[2] for pkg, metadata in matched_packages])
- matched_packages = [pkg for pkg in matched_packages \
- if pkg[0][2] == bestmatch]
-
- # ordered by type preference ("ebuild" type is the last resort)
- selected_pkg = matched_packages[-1]
-
- # In some cases, dep_check will return deps that shouldn't
- # be proccessed any further, so they are identified and
- # discarded here. Try to discard as few as possible since
- # discarded dependencies reduce the amount of information
- # available for optimization of merge order.
- if myparent and not arg and vardb.match(x) and \
- not existing_node and \
- "empty" not in self.myparams and \
- "deep" not in self.myparams and \
- not ("--update" in self.myopts and parent_arg):
- (mytype, myroot, mykey), metadata = selected_pkg
- myarg = None
- if myroot == self.target_root:
- try:
- myarg = self._set_atoms.findAtomForPackage(
- mykey, metadata)
- except portage.exception.InvalidDependString:
- # This is already handled inside
- # self.create() when necessary.
- pass
- if not myarg:
- continue
-
- 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], myparent=myparent,
- metadata=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], myparent=myparent,
- addme=("--onlydeps" not in self.myopts),
- metadata=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])
- 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:
- # TODO: Support blocks within slots in cases where it
- # might make sense. For example, a new version might
- # require that the old version be uninstalled at build
- # time.
- 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 in modified_slots[myroot]:
- replacement = final_db.match(slot_atom)
- if replacement:
- if not portage.match_from_list(mydep, replacement):
- # Apparently a replacement may be able to
- # invalidate this block.
- replacement_node = \
- self.pkg_node_map[proot][replacement[0]]
- depends_on_order.add((replacement_node, parent))
- 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:
- # TODO: Support blocks within slots.
- 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 not parent_static and pstatus == "nomerge" and \
- slot_atom in modified_slots[myroot]:
- replacement = final_db.match(pslot_atom)
- if replacement:
- replacement_node = \
- self.pkg_node_map[proot][replacement[0]]
- if replacement_node not in \
- self.blocker_parents[blocker]:
- # Apparently a replacement may be able to
- # invalidate this block.
- blocked_node = self.pkg_node_map[proot][cpv]
- depends_on_order.add(
- (replacement_node, blocked_node))
- 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, pnode in depends_on_order:
- # Enforce correct merge order with a hard dep.
- self.digraph.addnode(node, pnode,
- 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 unresolved_blocks:
- self._unresolved_blocker_parents.setdefault(
- blocker, set()).add(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 _merge_order_bias(self, mygraph):
- """Order nodes from highest to lowest overall reference count for
- optimal leaf node selection."""
- node_info = {}
- for node in mygraph.order:
- node_info[node] = len(mygraph.parent_nodes(node))
- def cmp_merge_preference(node1, node2):
- return node_info[node2] - node_info[node1]
- mygraph.order.sort(cmp_merge_preference)
-
- 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()
- self._merge_order_bias(mygraph)
- myblockers = self.blocker_digraph.copy()
- retlist=[]
- circular_blocks = False
- blocker_deps = None
- asap_nodes = []
- portage_node = None
- 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]:
- portage_node = node
- asap_nodes.append(node)
- break
- ignore_priority_soft_range = [None]
- ignore_priority_soft_range.extend(
- xrange(DepPriority.MIN, DepPriority.SOFT + 1))
- tree_mode = "--tree" in self.myopts
- # Tracks whether or not the current iteration should prefer asap_nodes
- # if available. This is set to False when the previous iteration
- # failed to select any nodes. It is reset whenever nodes are
- # successfully selected.
- prefer_asap = True
-
- # By default, try to avoid selecting root nodes whenever possible. This
- # helps ensure that the maximimum possible number of soft dependencies
- # have been removed from the graph before their parent nodes have
- # selected. This is especially important when those dependencies are
- # going to be rebuilt by revdep-rebuild or `emerge -e system` after the
- # CHOST has been changed (like when building a stage3 from a stage2).
- accept_root_node = False
-
- # State of prefer_asap and accept_root_node flags for successive
- # iterations that loosen the criteria for node selection.
- #
- # iteration prefer_asap accept_root_node
- # 1 True False
- # 2 False False
- # 3 False True
- #
- # If no nodes are selected on the 3rd iteration, it is due to
- # unresolved blockers or circular dependencies.
-
- while not mygraph.empty():
- selected_nodes = None
- if prefer_asap and asap_nodes:
- """ASAP nodes are merged before their soft deps."""
- asap_nodes = [node for node in asap_nodes \
- if mygraph.contains(node)]
- for node in asap_nodes:
- if not mygraph.child_nodes(node,
- ignore_priority=DepPriority.SOFT):
- selected_nodes = [node]
- asap_nodes.remove(node)
- break
- if not selected_nodes and \
- not (prefer_asap and asap_nodes):
- for ignore_priority in ignore_priority_soft_range:
- nodes = get_nodes(ignore_priority=ignore_priority)
- if nodes:
- break
- if nodes:
- 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:
- # For optimal merge order:
- # * Only pop one node.
- # * Removing a root node (node without a parent)
- # will not produce a leaf node, so avoid it.
- for node in nodes:
- if mygraph.parent_nodes(node):
- # found a non-root node
- selected_nodes = [node]
- break
- if not selected_nodes and \
- (accept_root_node or ignore_priority is None):
- # settle for a root node
- selected_nodes = [nodes[0]]
- if not selected_nodes:
- nodes = get_nodes(ignore_priority=DepPriority.MEDIUM)
- if nodes:
- """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(ignore_priority,
- mergeable_nodes, selected_nodes, node):
- if node in selected_nodes:
- return True
- if node not in mergeable_nodes:
- return False
- if node == portage_node and mygraph.child_nodes(node,
- ignore_priority=DepPriority.MEDIUM_SOFT):
- # Make sure that portage always has all of it's
- # RDEPENDs installed first.
- return False
- selected_nodes.add(node)
- for child in mygraph.child_nodes(node,
- ignore_priority=ignore_priority):
- if not gather_deps(ignore_priority,
- mergeable_nodes, selected_nodes, child):
- return False
- return True
- mergeable_nodes = set(nodes)
- if prefer_asap and asap_nodes:
- nodes = asap_nodes
- for ignore_priority in xrange(DepPriority.SOFT,
- DepPriority.MEDIUM_SOFT + 1):
- for node in nodes:
- if nodes is not asap_nodes and \
- not accept_root_node and \
- not mygraph.parent_nodes(node):
- continue
- selected_nodes = set()
- if gather_deps(ignore_priority,
- mergeable_nodes, selected_nodes, node):
- break
- else:
- selected_nodes = None
- if selected_nodes:
- break
-
- if prefer_asap and asap_nodes and not selected_nodes:
- # We failed to find any asap nodes to merge, so ignore
- # them for the next iteration.
- prefer_asap = False
- continue
-
- if not selected_nodes and not accept_root_node:
- # Maybe there are only root nodes left, so accept them
- # for the next iteration.
- accept_root_node = True
- continue
-
- if selected_nodes and ignore_priority > DepPriority.SOFT:
- # Try to merge ignored medium deps as soon as possible.
- for node in selected_nodes:
- children = set(mygraph.child_nodes(node))
- soft = children.difference(
- mygraph.child_nodes(node,
- ignore_priority=DepPriority.SOFT))
- medium_soft = children.difference(
- mygraph.child_nodes(node,
- ignore_priority=DepPriority.MEDIUM_SOFT))
- medium_soft.difference_update(soft)
- for child in medium_soft:
- if child in selected_nodes:
- continue
- if child in asap_nodes:
- continue
- # TODO: Try harder to make these nodes get
- # merged absolutely as soon as possible.
- asap_nodes.append(child)
-
- 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()
- while blocker_deps:
- # Some of these nodes might have already been selected
- # by the normal node selection process after the
- # circular_blocks flag has been set. Therefore, we
- # have to verify that they're still in the graph so
- # that they're not selected more than once.
- node = blocker_deps.pop()
- if mygraph.contains(node):
- selected_nodes = [node]
- break
-
- if not selected_nodes:
- # No leaf nodes are available, so we have a circular
- # dependency panic situation. Reduce the noise level to a
- # minimum via repeated elimination of root nodes since they
- # have no parents and thus can not be part of a cycle.
- while True:
- root_nodes = mygraph.root_nodes(
- ignore_priority=DepPriority.SOFT)
- if not root_nodes:
- break
- for node in root_nodes:
- mygraph.remove(node)
- # Display the USE flags that are enabled on nodes that are part
- # of dependency cycles in case that helps the user decide to
- # disable some of them.
- display_order = []
- tempgraph = mygraph.copy()
- while not tempgraph.empty():
- nodes = tempgraph.leaf_nodes()
- if not nodes:
- node = tempgraph.order[0]
- else:
- node = nodes[0]
- display_order.append(list(node))
- tempgraph.remove(node)
- display_order.reverse()
- self.myopts.pop("--quiet", None)
- self.myopts.pop("--verbose", None)
- self.myopts["--tree"] = True
- self.display(display_order)
- print "!!! Error: circular dependencies:"
- print
- mygraph.debug_print()
- print
- print "!!! Note that circular dependencies can often be avoided by temporarily"
- print "!!! disabling USE flags that trigger optional dependencies."
- sys.exit(1)
-
- # At this point, we've succeeded in selecting one or more nodes, so
- # it's now safe to reset the prefer_asap and accept_root_node flags
- # to their default states.
- prefer_asap = True
- accept_root_node = False
-
- for node in selected_nodes:
- if node[-1] != "nomerge":
- 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)
- unresolved = \
- self._unresolved_blocker_parents.get(blocker)
- if unresolved:
- self.blocker_parents[blocker] = unresolved
- else:
- 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
- filtered_db = self._filtered_trees[self.target_root]["porttree"].dbapi
- world_problems = False
-
- root_config = self.roots[self.target_root]
- world_set = root_config.sets["world"]
- system_set = root_config.sets["system"]
- mylist = list(system_set)
- self._sets["system"] = system_set
- if mode == "world":
- self._sets["world"] = world_set
- for x in world_set:
- if not portage.isvalidatom(x):
- world_problems = True
- continue
- elif not vardb.match(x):
- world_problems = True
- if not self._populate_filtered_repo(self.target_root, x,
- exclude_installed=True):
- return 0
- if not filtered_db.match(x):
- continue
- mylist.append(x)
-
- newlist = []
- for atom in mylist:
- mykey = portage.dep_getkey(atom)
- if True:
- newlist.append(atom)
- if mode == "system" or atom not in world_set:
- # only world is greedy for slots, not system
- continue
- # 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:
- if not self._populate_filtered_repo(self.target_root, atom,
- exclude_installed=True):
- return 0
- mymatches = filtered_db.match(atom)
- best_pkg = portage.best(mymatches)
- if best_pkg:
- best_slot = filtered_db.aux_get(best_pkg, ["SLOT"])[0]
- myslots.add(best_slot)
- if len(myslots) > 1:
- for myslot in myslots:
- myslot_atom = "%s:%s" % (mykey, myslot)
- if not self._populate_filtered_repo(
- self.target_root, myslot_atom,
- exclude_installed=True):
- return 0
- if filtered_db.match(myslot_atom):
- newlist.append(myslot_atom)
- mylist = newlist
-
- for myatom in mylist:
- self._set_atoms.add(myatom)
-
- # Since populate_filtered_repo() was called with the exclude_installed
- # flag, these atoms will need to be processed again in case installed
- # packages are required to satisfy dependencies.
- self._filtered_trees[self.target_root]["atoms"].clear()
-
- 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 portage.exception.PackageNotFound:
- 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, favorites=[], verbosity=None):
- if verbosity is None:
- verbosity = ("--quiet" in self.myopts and 1 or \
- "--verbose" in self.myopts and 3 or 2)
- favorites_set = InternalPackageSet(favorites)
- changelogs=[]
- p=[]
- blockers = []
-
- 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, reinst_flags,
- 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
- reinst_flag = reinst_flags and flag in reinst_flags
- if flag in enabled_flags:
- isEnabled = True
- if is_new or flag in old_use and \
- (all_flags or reinst_flag):
- flag_str = red(flag)
- elif flag not in old_iuse:
- flag_str = yellow(flag) + "%*"
- elif flag not in old_use:
- flag_str = green(flag) + "*"
- elif flag in removed_iuse:
- if all_flags or reinst_flag:
- flag_str = yellow("-" + flag) + "%"
- if flag in old_use:
- flag_str += "*"
- flag_str = "(" + flag_str + ")"
- removed.append(flag_str)
- continue
- else:
- if is_new or flag in old_iuse and \
- flag not in old_use and \
- (all_flags or reinst_flag):
- flag_str = blue("-" + flag)
- elif flag not in old_iuse:
- flag_str = yellow("-" + flag)
- if flag not in iuse_forced:
- flag_str += "%"
- elif flag in old_use:
- flag_str = green("-" + flag) + "*"
- if flag_str:
- if flag in iuse_forced:
- flag_str = "(" + flag_str + ")"
- if isEnabled:
- enabled.append(flag_str)
- else:
- disabled.append(flag_str)
-
- if alphabetical:
- ret = " ".join(enabled)
- else:
- ret = " ".join(enabled + disabled + removed)
- if ret:
- ret = '%s="%s" ' % (name, ret)
- return ret
-
- repo_display = RepoDisplay(self.roots)
- show_repos = False
-
- tree_nodes = []
- display_list = []
- mygraph = self._parent_child_digraph
- i = 0
- depth = 0
- shown_edges = set()
- for x in mylist:
- if "blocks" == x[0]:
- display_list.append((x, 0, True))
- continue
- graph_key = tuple(x)
- if "--tree" in self.myopts:
- depth = len(tree_nodes)
- while depth and graph_key not in \
- mygraph.child_nodes(tree_nodes[depth-1]):
- depth -= 1
- if depth:
- tree_nodes = tree_nodes[:depth]
- tree_nodes.append(graph_key)
- display_list.append((x, depth, True))
- shown_edges.add((graph_key, tree_nodes[depth-1]))
- else:
- traversed_nodes = set() # prevent endless circles
- traversed_nodes.add(graph_key)
- def add_parents(current_node, ordered):
- parent_nodes = None
- # Do not traverse to parents if this node is an
- # an argument or a direct member of a set that has
- # been specified as an argument (system or world).
- if current_node not in self._set_nodes:
- parent_nodes = mygraph.parent_nodes(current_node)
- if parent_nodes:
- child_nodes = set(mygraph.child_nodes(current_node))
- selected_parent = None
- # First, try to avoid a direct cycle.
- for node in parent_nodes:
- if node not in traversed_nodes and \
- node not in child_nodes:
- edge = (current_node, node)
- if edge in shown_edges:
- continue
- selected_parent = node
- break
- if not selected_parent:
- # A direct cycle is unavoidable.
- for node in parent_nodes:
- if node not in traversed_nodes:
- edge = (current_node, node)
- if edge in shown_edges:
- continue
- selected_parent = node
- break
- if selected_parent:
- shown_edges.add((current_node, selected_parent))
- traversed_nodes.add(selected_parent)
- add_parents(selected_parent, False)
- display_list.append((list(current_node),
- len(tree_nodes), ordered))
- tree_nodes.append(current_node)
- tree_nodes = []
- add_parents(graph_key, True)
- else:
- display_list.append((x, depth, True))
- mylist = display_list
-
- last_merge_depth = 0
- for i in xrange(len(mylist)-1,-1,-1):
- graph_key, depth, ordered = mylist[i]
- if not ordered and depth == 0 and i > 0 \
- and graph_key == mylist[i-1][0] and \
- mylist[i-1][1] == 0:
- # An ordered node got a consecutive duplicate when the tree was
- # being filled in.
- del mylist[i]
- continue
- if "blocks" == graph_key[0]:
- continue
- if ordered and graph_key[-1] != "nomerge":
- last_merge_depth = depth
- continue
- if depth >= last_merge_depth or \
- i < len(mylist) - 1 and \
- depth >= mylist[i+1][1]:
- del mylist[i]
-
- from portage import flatten
- from portage.dep import use_reduce, paren_reduce
- # files to fetch list - avoids counting a same file twice
- # in size display (verbose mode)
- myfetchlist=[]
-
- for mylist_index in xrange(len(mylist)):
- x, depth, ordered = mylist[mylist_index]
- pkg_node = tuple(x)
- 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+" "
- if ordered:
- counters.blocks += 1
- resolved = portage.key_expand(
- pkg_key, mydb=vardb, settings=pkgsettings)
- if "--columns" in self.myopts and "--quiet" in self.myopts:
- addl = addl + " " + red(resolved)
- else:
- addl = "[blocks " + 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]:
- addl += bad(" (\"%s\" is blocking %s)") % \
- (pkg_key, block_parents)
- else:
- addl += bad(" (is blocking %s)") % block_parents
- blockers.append(addl)
- else:
- pkg_status = x[3]
- pkg_merge = ordered and pkg_status != "nomerge"
- if pkg_node in self._slot_collision_nodes or \
- (pkg_status == "nomerge" and pkg_type != "installed"):
- # The metadata isn't cached due to a slot collision or
- # --onlydeps.
- mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
- else:
- mydbapi = self.mydbapi[myroot] # contains cached metadata
- metadata = dict(izip(self._mydbapi_keys,
- mydbapi.aux_get(pkg_key, self._mydbapi_keys)))
- ebuild_path = None
- repo_name = metadata["repository"]
- if pkg_type == "ebuild":
- ebuild_path = portdb.findname(pkg_key)
- if not ebuild_path: # shouldn't happen
- raise portage.exception.PackageNotFound(pkg_key)
- repo_path_real = os.path.dirname(os.path.dirname(
- os.path.dirname(ebuild_path)))
- pkgsettings.setcpv(pkg_key, mydb=mydbapi)
- metadata["USE"] = pkgsettings["USE"]
- else:
- repo_path_real = portdb.getRepositoryPath(repo_name)
- pkg_use = metadata["USE"].split()
- try:
- restrict = flatten(use_reduce(paren_reduce(
- mydbapi.aux_get(pkg_key, ["RESTRICT"])[0]),
- uselist=pkg_use))
- except portage.exception.InvalidDependString, e:
- if pkg_status != "nomerge":
- restrict = mydbapi.aux_get(pkg_key, ["RESTRICT"])[0]
- show_invalid_depstring_notice(x, restrict, str(e))
- del e
- return 1
- restrict = []
- if "ebuild" == pkg_type and x[3] != "nomerge" and \
- "fetch" in restrict:
- fetch = red("F")
- if ordered:
- counters.restrict_fetch += 1
- if portdb.fetch_check(pkg_key, pkg_use):
- fetch = green("f")
- if ordered:
- counters.restrict_fetch_satisfied += 1
-
- #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
- #param is used for -u, where you still *do* want to see when something is being upgraded.
- myoldbest=""
- installed_versions = vardb.match(portage.cpv_getkey(pkg_key))
- if vardb.cpv_exists(pkg_key):
- addl=" "+yellow("R")+fetch+" "
- if x[3] != "nomerge":
- if ordered:
- counters.reinst += 1
- # filter out old-style virtual matches
- elif installed_versions and \
- portage.cpv_getkey(installed_versions[0]) == \
- portage.cpv_getkey(pkg_key):
- mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
- slot_atom = "%s:%s" % \
- (portage.cpv_getkey(pkg_key), mynewslot)
- myinslotlist = vardb.match(slot_atom)
- # If this is the first install of a new-style virtual, we
- # need to filter out old-style virtual matches.
- if myinslotlist and \
- portage.cpv_getkey(myinslotlist[0]) != \
- portage.cpv_getkey(pkg_key):
- myinslotlist = None
- if myinslotlist:
- myoldbest=portage.best(myinslotlist)
- addl=" "+fetch
- if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
- # Downgrade in slot
- addl+=turquoise("U")+blue("D")
- if ordered:
- counters.downgrades += 1
- else:
- # Update in slot
- addl+=turquoise("U")+" "
- if ordered:
- counters.upgrades += 1
- else:
- # New slot, mark it new.
- addl=" "+green("NS")+fetch+" "
- if ordered:
- 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+" "
- if ordered:
- counters.new += 1
-
- verboseadd=""
-
- if True:
- # USE flag display
- cur_iuse = list(filter_iuse_defaults(
- mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
-
- forced_flags = set()
- pkgsettings.setcpv(pkg_key, mydb=mydbapi) # for package.use.{mask,force}
- forced_flags.update(pkgsettings.useforce)
- forced_flags.update(pkgsettings.usemask)
-
- cur_iuse = portage.unique_array(cur_iuse)
- cur_iuse.sort()
- cur_use = pkg_use
- 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,
- removeHidden=True):
- ret = {}
- forced = {}
- for exp in use_expand:
- ret[exp] = []
- forced[exp] = set()
- for val in myvals[:]:
- if val.startswith(exp.lower()+"_"):
- if val in forced_flags:
- forced[exp].add(val[len(exp)+1:])
- ret[exp].append(val[len(exp)+1:])
- myvals.remove(val)
- ret["USE"] = myvals
- forced["USE"] = [val for val in myvals \
- if val in forced_flags]
- if removeHidden:
- for exp in use_expand_hidden:
- ret.pop(exp, None)
- if forcedFlags:
- return ret, forced
- return ret
-
- # Prevent USE_EXPAND_HIDDEN flags from being hidden if they
- # are the only thing that triggered reinstallation.
- reinst_flags_map = {}
- reinstall_for_flags = self._reinstall_nodes.get(pkg_node)
- reinst_expand_map = None
- if reinstall_for_flags:
- reinst_flags_map = map_to_use_expand(
- list(reinstall_for_flags), removeHidden=False)
- for k in list(reinst_flags_map):
- if not reinst_flags_map[k]:
- del reinst_flags_map[k]
- if not reinst_flags_map.get("USE"):
- reinst_expand_map = reinst_flags_map.copy()
- reinst_expand_map.pop("USE", None)
- if reinst_expand_map and \
- not set(reinst_expand_map).difference(
- use_expand_hidden):
- use_expand_hidden = \
- set(use_expand_hidden).difference(
- reinst_expand_map)
-
- cur_iuse_map, iuse_forced = \
- map_to_use_expand(cur_iuse, forcedFlags=True)
- cur_use_map = map_to_use_expand(cur_use)
- old_iuse_map = map_to_use_expand(old_iuse)
- old_use_map = map_to_use_expand(old_use)
-
- use_expand.sort()
- use_expand.insert(0, "USE")
-
- for key in use_expand:
- if key in use_expand_hidden:
- continue
- verboseadd += create_use_string(key.upper(),
- cur_iuse_map[key], iuse_forced[key],
- cur_use_map[key], old_iuse_map[key],
- old_use_map[key], is_new,
- reinst_flags_map.get(key))
-
- if verbosity == 3:
- # size verbose
- mysize=0
- if pkg_type == "ebuild" and pkg_merge:
- try:
- myfilesdict = portdb.getfetchsizes(pkg_key,
- useflags=pkg_use, debug=self.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
- return 1
- if myfilesdict is None:
- myfilesdict="[empty/missing/bad digest]"
- else:
- for myfetchfile in myfilesdict:
- if myfetchfile not in myfetchlist:
- mysize+=myfilesdict[myfetchfile]
- myfetchlist.append(myfetchfile)
- counters.totalsize += mysize
- verboseadd+=format_size(mysize)+" "
-
- # overlay verbose
- # assign index for a previous version in the same slot
- has_previous = False
- repo_name_prev = None
- slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
- metadata["SLOT"])
- slot_matches = vardb.match(slot_atom)
- if slot_matches:
- has_previous = True
- repo_name_prev = vardb.aux_get(slot_matches[0],
- ["repository"])[0]
-
- # now use the data to generate output
- repoadd = None
- if pkg_status == "nomerge" or not has_previous:
- repoadd = repo_display.repoStr(repo_path_real)
- else:
- repo_path_prev = None
- if repo_name_prev:
- repo_path_prev = portdb.getRepositoryPath(
- repo_name_prev)
- # To avoid spam during the transition period, don't
- # show ? if the installed package is missing a
- # repository label.
- if not repo_path_prev or \
- repo_path_prev == repo_path_real:
- repoadd = repo_display.repoStr(repo_path_real)
- else:
- repoadd = "%s=>%s" % (
- repo_display.repoStr(repo_path_prev),
- repo_display.repoStr(repo_path_real))
- if repoadd and repoadd != "0":
- show_repos = True
- verboseadd += teal("[%s]" % repoadd)
-
- xs = list(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 = " " * depth
-
- if myoldbest:
- myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
- if myoldbest[-3:]=="-r0":
- myoldbest=myoldbest[:-3]
- myoldbest=blue("["+myoldbest+"]")
-
- pkg_cp = xs[0]
- root_config = self.roots[myroot]
- system_set = root_config.sets["system"]
- world_set = root_config.sets["world"]
-
- pkg_system = False
- pkg_world = False
- try:
- pkg_system = system_set.findAtomForPackage(pkg_key, metadata)
- pkg_world = world_set.findAtomForPackage(pkg_key, metadata)
- if not pkg_world and myroot == self.target_root and \
- favorites_set.findAtomForPackage(pkg_key, metadata):
- # Maybe it will be added to world now.
- if create_world_atom(pkg_key, metadata,
- favorites_set, root_config):
- pkg_world = True
- except portage.exception.InvalidDependString:
- # This is reported elsewhere if relevant.
- pass
-
- def pkgprint(pkg):
- if pkg_merge:
- if pkg_system:
- return colorize("PKG_MERGE_SYSTEM", pkg)
- elif pkg_world:
- return colorize("PKG_MERGE_WORLD", pkg)
- else:
- return colorize("PKG_MERGE", pkg)
- else:
- if pkg_system:
- return colorize("PKG_NOMERGE_SYSTEM", pkg)
- elif pkg_world:
- return colorize("PKG_NOMERGE_WORLD", pkg)
- else:
- return colorize("PKG_NOMERGE", pkg)
-
- if x[1]!="/":
- if myoldbest:
- myoldbest +=" "
- if "--columns" in self.myopts:
- if "--quiet" in self.myopts:
- myprint=addl+" "+indent+pkgprint(pkg_cp)
- myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
- myprint=myprint+myoldbest
- myprint=myprint+darkgreen("to "+x[1])
- else:
- myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_cp)
- if (newlp-nc_len(myprint)) > 0:
- myprint=myprint+(" "*(newlp-nc_len(myprint)))
- myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
- if (oldlp-nc_len(myprint)) > 0:
- myprint=myprint+" "*(oldlp-nc_len(myprint))
- myprint=myprint+myoldbest
- myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
- else:
- if not pkg_merge:
- myprint = "[%s ] " % pkgprint("nomerge")
- else:
- myprint = "[" + pkg_type + " " + addl + "] "
- myprint += indent + pkgprint(pkg_key) + " " + \
- myoldbest + darkgreen("to " + myroot) + " " + \
- verboseadd
- else:
- if "--columns" in self.myopts:
- if "--quiet" in self.myopts:
- myprint=addl+" "+indent+pkgprint(pkg_cp)
- myprint=myprint+" "+green(xs[1]+xs[2])+" "
- myprint=myprint+myoldbest
- else:
- myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_cp)
- if (newlp-nc_len(myprint)) > 0:
- myprint=myprint+(" "*(newlp-nc_len(myprint)))
- myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
- if (oldlp-nc_len(myprint)) > 0:
- myprint=myprint+(" "*(oldlp-nc_len(myprint)))
- myprint=myprint+myoldbest+" "+verboseadd
- else:
- if not pkg_merge:
- myprint="["+pkgprint("nomerge")+" ] "+indent+pkgprint(pkg_key)+" "+myoldbest+" "+verboseadd
- else:
- myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_key)+" "+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 < 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
- for x in blockers:
- print x
-
- if verbosity == 3:
- print
- print counters
- if show_repos:
- sys.stdout.write(str(repo_display))
-
- if "--changelog" in self.myopts:
- print
- for revision,text in changelogs:
- print bold('*'+revision)
- sys.stdout.write(text)
-
- if self._pprovided_args:
- arg_refs = {}
- for arg_atom in self._pprovided_args:
- arg, atom = arg_atom
- arg_refs[arg_atom] = []
- cp = portage.dep_getkey(atom)
- for set_name, atom_set in self._sets.iteritems():
- if atom in atom_set:
- arg_refs[arg_atom].append(set_name)
- 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")
- problems_sets = set()
- for (arg, atom), refs in arg_refs.iteritems():
- ref_string = ""
- if refs:
- problems_sets.update(refs)
- refs.sort()
- ref_string = ", ".join(["'%s'" % name for name in refs])
- ref_string = " pulled in by " + ref_string
- msg.append(" %s%s\n" % (colorize("INFORM", arg), ref_string))
- msg.append("\n")
- if "world" in problems_sets:
- msg.append("This problem can be solved in one of the following ways:\n\n")
- msg.append(" A) Use emaint to clean offending packages from world (if not installed).\n")
- msg.append(" B) Uninstall offending packages (cleans them from world).\n")
- msg.append(" C) Remove offending entries from package.provided.\n\n")
- msg.append("The best course of action depends on the reason that an offending\n")
- msg.append("package.provided entry exists.\n\n")
- sys.stderr.write("".join(msg))
- return os.EX_OK
-
- def calc_changelog(self,ebuildpath,current,next):
- if ebuildpath == None or not os.path.exists(ebuildpath):
- return []
- current = '-'.join(portage.catpkgsplit(current)[1:])
- if current.endswith('-r0'):
- current = current[:-3]
- next = '-'.join(portage.catpkgsplit(next)[1:])
- if next.endswith('-r0'):
- next = next[:-3]
- changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
- try:
- changelog = 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 saveNomergeFavorites(self):
- """Find atoms in favorites that are not in the mergelist and add them
- to the world file if necessary."""
- for x in ("--fetchonly", "--fetch-all-uri",
- "--oneshot", "--onlydeps", "--pretend"):
- if x in self.myopts:
- return
- root_config = self.roots[self.target_root]
- world_set = root_config.sets["world"]
- world_set.lock()
- world_set.load() # maybe it's changed on disk
- args_set = self._sets["args"]
- portdb = self.trees[self.target_root]["porttree"].dbapi
- added_favorites = set()
- for x in self._set_nodes:
- pkg_type, root, pkg_key, pkg_status = x
- if pkg_status != "nomerge":
- continue
- metadata = dict(izip(self._mydbapi_keys,
- self.mydbapi[root].aux_get(pkg_key, self._mydbapi_keys)))
- try:
- myfavkey = create_world_atom(pkg_key, metadata,
- args_set, root_config)
- if myfavkey:
- if myfavkey in added_favorites:
- continue
- added_favorites.add(myfavkey)
- world_set.add(myfavkey)
- print ">>> Recording",myfavkey,"in \"world\" favorites file..."
- except portage.exception.InvalidDependString, e:
- writemsg("\n\n!!! '%s' has invalid PROVIDE: %s\n" % \
- (pkg_key, str(e)), noiselevel=-1)
- writemsg("!!! see '%s'\n\n" % os.path.join(
- root, portage.VDB_PATH, pkg_key, "PROVIDE"), noiselevel=-1)
- del e
- world_set.unlock()
-
- def loadResumeCommand(self, resume_data):
- """
- Add a resume command to the graph and validate it in the process. This
- will raise a PackageNotFound exception if a package is not available.
- """
- self._sets["args"].update(resume_data.get("favorites", []))
- mergelist = resume_data.get("mergelist", [])
- fakedb = self.mydbapi
- trees = self.trees
- for x in mergelist:
- if len(x) != 4:
- continue
- pkg_type, myroot, pkg_key, action = x
- if pkg_type not in self.pkg_tree_map:
- continue
- if action != "merge":
- continue
- mydb = trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
- try:
- metadata = dict(izip(self._mydbapi_keys,
- mydb.aux_get(pkg_key, self._mydbapi_keys)))
- except KeyError:
- # It does no exist or it is corrupt.
- raise portage.exception.PackageNotFound(pkg_key)
- fakedb[myroot].cpv_inject(pkg_key, metadata=metadata)
- if pkg_type == "ebuild":
- pkgsettings = self.pkgsettings[myroot]
- pkgsettings.setcpv(pkg_key, mydb=fakedb[myroot])
- fakedb[myroot].aux_update(pkg_key, {"USE":pkgsettings["USE"]})
- self.spinner.update()
-
-class RepoDisplay(object):
- def __init__(self, roots):
- self._shown_repos = {}
- self._unknown_repo = False
- repo_paths = set()
- for root_config in roots.itervalues():
- portdir = root_config.settings.get("PORTDIR")
- if portdir:
- repo_paths.add(portdir)
- overlays = root_config.settings.get("PORTDIR_OVERLAY")
- if overlays:
- repo_paths.update(overlays.split())
- repo_paths = list(repo_paths)
- self._repo_paths = repo_paths
- self._repo_paths_real = [ os.path.realpath(repo_path) \
- for repo_path in repo_paths ]
-
- # pre-allocate index for PORTDIR so that it always has index 0.
- for root_config in roots.itervalues():
- portdb = root_config.trees["porttree"].dbapi
- portdir = portdb.porttree_root
- if portdir:
- self.repoStr(portdir)
-
- def repoStr(self, repo_path_real):
- real_index = -1
- if repo_path_real:
- real_index = self._repo_paths_real.index(repo_path_real)
- if real_index == -1:
- s = "?"
- self._unknown_repo = True
- else:
- shown_repos = self._shown_repos
- repo_paths = self._repo_paths
- repo_path = repo_paths[real_index]
- index = shown_repos.get(repo_path)
- if index is None:
- index = len(shown_repos)
- shown_repos[repo_path] = index
- s = str(index)
- return s
-
- def __str__(self):
- output = []
- shown_repos = self._shown_repos
- unknown_repo = self._unknown_repo
- if shown_repos or self._unknown_repo:
- output.append("Portage tree and overlays:\n")
- show_repo_paths = list(shown_repos)
- for repo_path, repo_index in shown_repos.iteritems():
- show_repo_paths[repo_index] = repo_path
- if show_repo_paths:
- for index, repo_path in enumerate(show_repo_paths):
- output.append(" "+teal("["+str(index)+"]")+" %s\n" % repo_path)
- if unknown_repo:
- output.append(" "+teal("[?]") + \
- " indicates that the source repository could not be determined\n")
- return "".join(output)
-
-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)
- self.curval = 0
-
- def merge(self, mylist, favorites, mtimedb):
- from portage.elog import elog_process
- from portage.elog.filtering import filter_mergephases
- failed_fetches = []
- fetchonly = "--fetchonly" in self.myopts or \
- "--fetch-all-uri" in self.myopts
- pretend = "--pretend" in self.myopts
- mymergelist=[]
- ldpath_mtimes = mtimedb["ldpath"]
- xterm_titles = "notitles" not in self.settings.features
-
- #check for blocking dependencies
- if "--fetchonly" not in self.myopts and \
- "--fetch-all-uri" 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()
- return 1
-
- if "--resume" in self.myopts:
- # We're resuming.
- print colorize("GOOD", "*** Resuming merge...")
- emergelog(xterm_titles, " *** Resuming merge...")
- mylist = mtimedb["resume"]["mergelist"][:]
- if "--skipfirst" in self.myopts and mylist:
- del mtimedb["resume"]["mergelist"][0]
- del mylist[0]
- mtimedb.commit()
- mymergelist = mylist
-
- # Verify all the manifests now so that the user is notified of failure
- # as soon as possible.
- if "--fetchonly" not in self.myopts and \
- "--fetch-all-uri" not in self.myopts and \
- "strict" in self.settings.features:
- shown_verifying_msg = False
- quiet_settings = {}
- for myroot, pkgsettings in self.pkgsettings.iteritems():
- quiet_config = portage.config(clone=pkgsettings)
- quiet_config["PORTAGE_QUIET"] = "1"
- quiet_config.backup_changes("PORTAGE_QUIET")
- quiet_settings[myroot] = quiet_config
- del quiet_config
- for x in mylist:
- if x[0] != "ebuild" or x[-1] == "nomerge":
- continue
- if not shown_verifying_msg:
- shown_verifying_msg = True
- print ">>> Verifying ebuild Manifests..."
- mytype, myroot, mycpv, mystatus = x
- portdb = self.trees[myroot]["porttree"].dbapi
- quiet_config = quiet_settings[myroot]
- quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
- if not portage.digestcheck([], quiet_config, strict=True):
- return 1
- del x, mytype, myroot, mycpv, mystatus, quiet_config
- del shown_verifying_msg, quiet_settings
-
- root_config = RootConfig(self.trees[self.target_root])
- system_set = root_config.sets["system"]
- args_set = InternalPackageSet(favorites)
- world_set = root_config.sets["world"]
- if "--resume" not in self.myopts:
- mymergelist = mylist
- 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"]
- resume_opts = self.myopts.copy()
- # For automatic resume, we need to prevent
- # any of bad_resume_opts from leaking in
- # via EMERGE_DEFAULT_OPTS.
- resume_opts["--ignore-default-opts"] = True
- for myopt, myarg in resume_opts.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
- del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
- resume_opts
-
- metadata_keys = [k for k in portage.auxdbkeys \
- if not k.startswith("UNUSED_")] + ["USE"]
-
- mergecount=0
- for x in mymergelist:
- mergecount+=1
- pkg_type = x[0]
- 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]
- metadata = {}
- if pkg_type == "blocks":
- pass
- elif pkg_type == "ebuild":
- mydbapi = portdb
- metadata.update(izip(metadata_keys,
- mydbapi.aux_get(pkg_key, metadata_keys)))
- pkgsettings.setcpv(pkg_key, mydb=mydbapi)
- metadata["USE"] = pkgsettings["USE"]
- else:
- if pkg_type == "binary":
- mydbapi = bindb
- else:
- raise AssertionError("Package type: '%s'" % pkg_type)
- metadata.update(izip(metadata_keys,
- mydbapi.aux_get(pkg_key, metadata_keys)))
- 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 system_set.findAtomForPackage(pkg_key, metadata) \
- 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)
- self.curval += 1
- 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)
- binpkg_tmpfile = os.path.join(pkgsettings["PKGDIR"],
- pkg_key + ".tbz2." + str(os.getpid()))
- pkgsettings["PORTAGE_BINPKG_TMPFILE"] = binpkg_tmpfile
- pkgsettings.backup_changes("PORTAGE_BINPKG_TMPFILE")
- retval = portage.doebuild(y, "package", myroot,
- pkgsettings, self.edebug, mydbapi=portdb,
- tree="porttree")
- del pkgsettings["PORTAGE_BINPKG_TMPFILE"]
- if retval != os.EX_OK or \
- "--buildpkgonly" in self.myopts:
- elog_process(pkg_key, pkgsettings, phasefilter=filter_mergephases)
- if retval != os.EX_OK:
- return retval
- bintree = self.trees[myroot]["bintree"]
- bintree.inject(pkg_key, filename=binpkg_tmpfile)
- if "--buildpkgonly" not in self.myopts:
- 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)
- try:
- self.trees[myroot]["bintree"].gettbz2(pkg_key)
- except portage.exception.FileNotFound:
- writemsg("!!! Fetching Binary failed " + \
- "for '%s'\n" % pkg_key, noiselevel=-1)
- if not fetchonly:
- return 1
- failed_fetches.append(pkg_key)
- except portage.exception.DigestException, e:
- writemsg("\n!!! Digest verification failed:\n",
- noiselevel=-1)
- writemsg("!!! %s\n" % e.value[0],
- noiselevel=-1)
- writemsg("!!! Reason: %s\n" % e.value[1],
- noiselevel=-1)
- writemsg("!!! Got: %s\n" % e.value[2],
- noiselevel=-1)
- writemsg("!!! Expected: %s\n" % e.value[3],
- noiselevel=-1)
- os.unlink(mytbz2)
- if not fetchonly:
- return 1
- failed_fetches.append(pkg_key)
- finally:
- if tbz2_lock:
- portage.locks.unlockfile(tbz2_lock)
-
- if "--fetchonly" in self.myopts or \
- "--fetch-all-uri" in self.myopts:
- self.curval += 1
- 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 not fetchonly and not pretend and \
- args_set.findAtomForPackage(pkg_key, metadata):
- world_set.lock()
- world_set.load() # maybe it's changed on disk
- myfavkey = create_world_atom(pkg_key, metadata,
- args_set, root_config)
- if myfavkey:
- print ">>> Recording",myfavkey,"in \"world\" favorites file..."
- emergelog(xterm_titles, " === ("+\
- str(mergecount)+" of "+\
- str(len(mymergelist))+\
- ") Updating world file ("+x[pkgindex]+")")
- world_set.add(myfavkey)
- world_set.unlock()
-
- 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"]
- resume_opts = self.myopts.copy()
- # For automatic resume, we need to prevent
- # any of bad_resume_opts from leaking in
- # via EMERGE_DEFAULT_OPTS.
- resume_opts["--ignore-default-opts"] = True
- for myopt, myarg in resume_opts.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()
- self.curval += 1
-
- 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)
- elif unmerge_action == "prune":
- if len(mymatch) == 1:
- continue
- best_version = mymatch[0]
- best_slot = vartree.getslot(best_version)
- best_counter = vartree.dbapi.cpv_counter(best_version)
- for mypkg in mymatch[1:]:
- myslot = vartree.getslot(mypkg)
- mycounter = vartree.dbapi.cpv_counter(mypkg)
- if (myslot == best_slot and mycounter > best_counter) or \
- mypkg == portage.best([mypkg, best_version]):
- if myslot == best_slot:
- if mycounter < best_counter:
- # On slot collision, keep the one with the
- # highest counter since it is the most
- # recently installed.
- continue
- best_version = mypkg
- best_slot = myslot
- best_counter = mycounter
- pkgmap[mykey]["protected"].append(best_version)
- pkgmap[mykey]["selected"] = [mypkg for mypkg in mymatch \
- if mypkg != best_version]
- numselected = numselected + len(pkgmap[mykey]["selected"])
- else:
- # unmerge_action == "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:
- 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:
- portage.writemsg_stdout("\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:
- 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"))
- if "--quiet" not in myopts:
- print "\n "+white(x)
- else:
- print white(x)+": ",
- for mytype in ["selected","protected","omitted"]:
- if "--quiet" not in myopts:
- portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
- if pkgmap[x][mytype]:
- sorted_pkgs = [portage.catpkgsplit(mypkg)[1:] \
- for mypkg in pkgmap[x][mytype]]
- sorted_pkgs.sort(portage.pkgcmp)
- for pn, ver, rev in sorted_pkgs:
- if rev == "r0":
- myversion = ver
- else:
- myversion = ver + "-" + rev
- 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)
- if "--quiet" not in myopts:
- portage.writemsg_stdout("\n", noiselevel=-1)
- if "--quiet" in myopts:
- 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:
- 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):
-
- 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:
- portage.writemsg_stdout(" "+green("*")+" GNU info directory index is up-to-date.\n")
- else:
- portage.writemsg_stdout(" "+green("*")+" Regenerating GNU info directory index...\n")
-
- dir_extensions = ("", ".gz", ".bz2")
- icount=0
- badcount=0
- for inforoot in regen_infodirs:
- if inforoot=='':
- continue
-
- if not os.path.isdir(inforoot):
- continue
- errmsg = ""
- file_list = os.listdir(inforoot)
- file_list.sort()
- dir_file = os.path.join(inforoot, "dir")
- moved_old_dir = False
- processed_count = 0
- for x in file_list:
- if x.startswith(".") or \
- os.path.isdir(os.path.join(inforoot, x)):
- continue
- if x.startswith("dir"):
- skip = False
- for ext in dir_extensions:
- if x == "dir" + ext or \
- x == "dir" + ext + ".old":
- skip = True
- break
- if skip:
- continue
- if processed_count == 0:
- for ext in dir_extensions:
- try:
- os.rename(dir_file + ext, dir_file + ext + ".old")
- moved_old_dir = True
- except EnvironmentError, e:
- if e.errno != errno.ENOENT:
- raise
- del e
- processed_count += 1
- 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
-
- if moved_old_dir and not os.path.exists(dir_file):
- # We didn't generate a new dir file, so put the old file
- # back where it was originally found.
- for ext in dir_extensions:
- try:
- os.rename(dir_file + ext + ".old", dir_file + ext)
- except EnvironmentError, e:
- if e.errno != errno.ENOENT:
- raise
- del e
-
- # Clean dir.old cruft so that they don't prevent
- # unmerge of otherwise empty directories.
- for ext in dir_extensions:
- try:
- os.unlink(dir_file + ext + ".old")
- except EnvironmentError, e:
- if e.errno != errno.ENOENT:
- raise
- del e
-
- #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 display_news_notification(trees):
- for target_root in trees:
- if len(trees) > 1 and target_root != "/":
- break
- settings = trees[target_root]["vartree"].settings
- portdb = trees[target_root]["porttree"].dbapi
- vardb = trees[target_root]["vartree"].dbapi
- NEWS_PATH = os.path.join("metadata", "news")
- UNREAD_PATH = os.path.join(target_root, NEWS_LIB_PATH, "news")
- newsReaderDisplay = False
-
- for repo in portdb.getRepositories():
- unreadItems = checkUpdatedNewsItems(
- portdb, vardb, NEWS_PATH, UNREAD_PATH, repo)
- if unreadItems:
- if not newsReaderDisplay:
- newsReaderDisplay = True
- print
- print colorize("WARN", " * IMPORTANT:"),
- print "%s news items need reading for repository '%s'." % (unreadItems, repo)
-
-
- if newsReaderDisplay:
- print colorize("WARN", " *"),
- print "Use " + colorize("GOOD", "eselect news") + " to read news items."
- print
-
-def post_emerge(trees, mtimedb, retval):
- """
- Misc. things to run at the end of a merge session.
-
- Update Info Files
- Update Config Files
- Update News Items
- Commit mtimeDB
- Display preserved libs warnings
- Exit Emerge
-
- @param trees: A dictionary mapping each ROOT to it's package databases
- @type trees: dict
- @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)
- """
- for target_root in trees:
- if len(trees) > 1 and target_root != "/":
- break
- vardbapi = trees[target_root]["vartree"].dbapi
- settings = vardbapi.settings
- info_mtimes = mtimedb["info"]
-
- # Load the most current variables from ${ROOT}/etc/profile.env
- settings.unlock()
- settings.reload()
- settings.regenerate()
- settings.lock()
-
- config_protect = settings.get("CONFIG_PROTECT","").split()
- infodirs = settings.get("INFOPATH","").split(":") + \
- settings.get("INFODIR","").split(":")
-
- os.chdir("/")
-
- if retval == os.EX_OK:
- exit_msg = " *** exiting successfully."
- else:
- exit_msg = " *** exiting unsuccessfully with status '%s'." % retval
- emergelog("notitles" not in settings.features, exit_msg)
-
- # Dump the mod_echo output now so that our other notifications are shown
- # last.
- try:
- from portage.elog import mod_echo
- except ImportError:
- pass # happens during downgrade to a version without the module
- else:
- mod_echo.finalize()
-
- vdb_path = os.path.join(target_root, portage.VDB_PATH)
- portage.util.ensure_dirs(vdb_path)
- vdb_lock = portage.locks.lockdir(vdb_path)
- try:
- if "noinfo" not in settings.features:
- chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
- mtimedb.commit()
- finally:
- portage.locks.unlockdir(vdb_lock)
-
- chk_updated_cfg_files(target_root, config_protect)
-
- display_news_notification(trees)
-
- if vardbapi.plib_registry.hasEntries():
- print colorize("WARN", "!!!") + " existing preserved libs:"
- plibdata = vardbapi.plib_registry.getPreservedLibs()
- for cpv in plibdata:
- print colorize("WARN", ">>>") + " package: %s" % cpv
- for f in plibdata[cpv]:
- print colorize("WARN", " * ") + " - %s" % f
- print "Use " + colorize("GOOD", "revdep-rebuild") + " to rebuild packages using these libraries"
- print "and then remerge the packages listed above."
-
- 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_ISLNK(mymode):
- # We want to treat it like a directory if it
- # is a symlink to an existing directory.
- try:
- real_mode = os.stat(x).st_mode
- if stat.S_ISDIR(real_mode):
- mymode = real_mode
- except OSError:
- pass
- if stat.S_ISDIR(mymode):
- mycommand = "find '%s' -iname '._cfg????_*'" % x
- else:
- mycommand = "find '%s' -maxdepth 1 -iname '._cfg????_%s'" % \
- os.path.split(x.rstrip(os.path.sep))
- mycommand += " ! -iname '.*~' ! -iname '.*.bak' -print0"
- a = commands.getstatusoutput(mycommand)
- if a[0] != 0:
- sys.stderr.write(" %s error scanning '%s': " % (bad("*"), x))
- sys.stderr.flush()
- # Show the error message alone, sending stdout to /dev/null.
- os.system(mycommand + " 1>/dev/null")
- else:
- files = a[1].split('\0')
- # split always produces an empty string as the last element
- if files and not files[-1]:
- del files[-1]
- 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("*")+" See the "+colorize("INFORM","CONFIGURATION FILES")+ \
- " section of the " + bold("emerge")
- print " "+yellow("*")+" man page to learn how to update config files."
-
-def checkUpdatedNewsItems(portdb, vardb, 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 portdb: a portage tree database
- @type portdb: pordbapi
- @param vardb: an installed package database
- @type vardb: vardbapi
- @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(portdb, vardb, 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 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
- 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 = []
- import shlex, StringIO
- 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
- "--filter=H_**/files/digest-*", # Exclude manifest1 digests and delete on the receiving side
- ])
-
- 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)
- lexer = shlex.shlex(StringIO.StringIO(
- settings.get("PORTAGE_RSYNC_OPTS","")), posix=True)
- lexer.whitespace_split = True
- rsync_opts.extend(lexer)
- del lexer
-
- 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")
-
- 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:
- rsync_initial_timeout = \
- int(settings.get("PORTAGE_RSYNC_INITIAL_TIMEOUT", "15"))
- except ValueError:
- rsync_initial_timeout = 15
-
- 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)
- lexer = shlex.shlex(StringIO.StringIO(
- settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")), posix=True)
- lexer.whitespace_split = True
- extra_rsync_opts = list(lexer)
- del lexer
- all_rsync_opts.update(extra_rsync_opts)
- family = socket.AF_INET
- 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 = ["/usr/bin/rsync"] + rsync_opts + extra_rsync_opts
-
- if "--debug" in myopts:
- print rsynccommand
-
- exitcode = os.EX_OK
- servertimestamp = 0
- # Even if there's no timestamp available locally, fetch the
- # timestamp anyway as an initial probe to verify that the server is
- # responsive. This protects us from hanging indefinitely on a
- # connection attempt to an unresponsive server which rsync's
- # --timeout option does not prevent.
- if True:
- # Temporary file for remote server timestamp comparison.
- from tempfile import mkstemp
- fd, tmpservertimestampfile = mkstemp()
- os.close(fd)
- mycommand = rsynccommand[:]
- mycommand.append(dosyncuri.rstrip("/") + \
- "/metadata/timestamp.chk")
- mycommand.append(tmpservertimestampfile)
- content = None
- mypids = []
- try:
- def timeout_handler(signum, frame):
- raise portage.exception.PortageException("timed out")
- signal.signal(signal.SIGALRM, timeout_handler)
- # Timeout here in case the server is unresponsive. The
- # --timeout rsync option doesn't apply to the initial
- # connection attempt.
- if rsync_initial_timeout:
- signal.alarm(rsync_initial_timeout)
- try:
- mypids.extend(portage.process.spawn(
- mycommand, env=settings.environ(), returnpid=True))
- exitcode = os.waitpid(mypids[0], 0)[1]
- content = portage.grabfile(tmpservertimestampfile)
- finally:
- if rsync_initial_timeout:
- signal.alarm(0)
- try:
- os.unlink(tmpservertimestampfile)
- except OSError:
- pass
- except portage.exception.PortageException, e:
- # timed out
- print e
- del e
- if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
- os.kill(mypids[0], signal.SIGTERM)
- os.waitpid(mypids[0], 0)
- # This is the same code rsync uses for timeout.
- exitcode = 30
- else:
- if exitcode != os.EX_OK:
- if exitcode & 0xff:
- exitcode = (exitcode & 0xff) << 8
- else:
- exitcode = exitcode >> 8
- if mypids:
- portage.process.spawned_pids.remove(mypids[0])
- if content:
- try:
- servertimestamp = time.mktime(time.strptime(
- content[0], "%a, %d %b %Y %H:%M:%S +0000"))
- except (OverflowError, ValueError):
- pass
- del mycommand, mypids, content
- 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.process.spawn(mycommand,
- env=settings.environ())
- if exitcode in [0,1,3,4,11,14,20,21]:
- break
- elif exitcode in [1,3,4,11,14,20,21]:
- break
- else:
- # Code 2 indicates protocol incompatibility, which is expected
- # for servers with protocol < 29 that don't support
- # --prune-empty-directories. Retry for a server that supports
- # at least rsync protocol version 29 (>=rsync-2.6.4).
- pass
-
- 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(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
- print red(" * ")+"To update portage, run 'emerge portage' now."
- print
-
- display_news_notification(trees)
-
-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.cp_list(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
-
- 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)
- pkg_matches = [portage.catpkgsplit(cpv)[1:] for cpv in pkg_matches]
- pkg_matches.sort(portage.pkgcmp)
- pkgs = []
- for pn, ver, rev in pkg_matches:
- if rev != "r0":
- pkgs.append(ver + "-" + rev)
- else:
- pkgs.append(ver)
- if pkgs:
- pkgs = ", ".join(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_title = "Package Settings"
- print header_width * "="
- print header_title.rjust(int(header_width/2 + len(header_title)/2))
- print header_width * "="
- from portage.output import EOutput
- out = EOutput()
- 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:
- # 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
- print ">>> Attempting to run pkg_info() for '%s'" % pkg
- ebuildpath = vardb.findname(pkg)
- if not ebuildpath or not os.path.exists(ebuildpath):
- out.ewarn("No ebuild found for '%s'" % pkg)
- continue
- portage.doebuild(ebuildpath, "info", pkgsettings["ROOT"],
- pkgsettings, debug=(settings.get("PORTAGE_DEBUG", "") == 1),
- mydbapi=trees[settings["ROOT"]]["vartree"].dbapi,
- tree="vartree")
-
-def action_search(settings, portdb, vartree, myopts, myfiles, spinner, setconfig):
- if not myfiles:
- print "emerge: no search terms provided."
- else:
- searchinstance = search(settings, portdb,
- vartree, spinner, "--searchdesc" in myopts,
- "--quiet" not in myopts, setconfig)
- 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, action, myfiles, spinner):
- # Kill packages that aren't explicitly merged or are required as a
- # dependency of another package. World file is explicit.
-
- msg = []
- msg.append("Depclean may break link level dependencies. Thus, it is\n")
- msg.append("recommended to use a tool such as " + good("`revdep-rebuild`") + " (from\n")
- msg.append("app-portage/gentoolkit) in order to detect such breakage.\n")
- msg.append("\n")
- msg.append("Also study the list of packages to be cleaned for any obvious\n")
- msg.append("mistakes. Packages that are part of the world set will always\n")
- msg.append("be kept. They can be manually added to this set with\n")
- msg.append(good("`emerge --noreplace <atom>`") + ". Packages that are listed in\n")
- msg.append("package.provided (see portage(5)) will be removed by\n")
- msg.append("depclean, even if they are part of the world set.\n")
- msg.append("\n")
- msg.append("As a safety measure, depclean will not remove any packages\n")
- msg.append("unless *all* required dependencies have been resolved. As a\n")
- msg.append("consequence, it is often necessary to run\n")
- msg.append(good("`emerge --update --newuse --deep world`") + " prior to depclean.\n")
-
- if action == "depclean" and "--quiet" not in myopts and not myfiles:
- portage.writemsg_stdout("\n")
- for x in msg:
- portage.writemsg_stdout(colorize("BAD", "*** WARNING *** ") + x)
-
- xterm_titles = "notitles" not in settings.features
- myroot = settings["ROOT"]
- portdb = trees[myroot]["porttree"].dbapi
- dep_check_trees = {}
- dep_check_trees[myroot] = {}
- dep_check_trees[myroot]["vartree"] = \
- FakeVartree(trees[myroot]["vartree"],
- trees[myroot]["porttree"].dbapi,
- depgraph._mydbapi_keys)
- vardb = dep_check_trees[myroot]["vartree"].dbapi
- # Constrain dependency selection to the installed packages.
- dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
- system_set = SystemSet(settings.profiles)
- syslist = list(system_set)
- world_set = WorldSet(myroot)
- worldlist = list(world_set)
- args_set = InternalPackageSet()
- 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 action == "depclean":
- emergelog(xterm_titles, " >>> depclean")
- if myfiles:
- for x in myfiles:
- if not is_valid_package_atom(x):
- portage.writemsg("!!! '%s' is not a valid package atom.\n" % x,
- noiselevel=-1)
- portage.writemsg("!!! Please check ebuild(5) for full details.\n")
- return
- try:
- atom = portage.dep_expand(x, mydb=vardb, settings=settings)
- except ValueError, e:
- print "!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
- print "!!! one of the following fully-qualified ebuild names instead:\n"
- for i in e[0]:
- print " " + colorize("INFORM", i)
- print
- return
- args_set.add(atom)
- matched_packages = False
- for x in args_set:
- if vardb.match(x):
- matched_packages = True
- break
- if not matched_packages:
- portage.writemsg_stdout(
- ">>> No packages selected for removal by %s\n" % action)
- return
-
- if "--quiet" not in myopts:
- print "\nCalculating dependencies ",
-
- soft = 0
- hard = 1
- remaining_atoms = []
- if action == "depclean":
- for atom in worldlist:
- if vardb.match(atom):
- remaining_atoms.append((atom, 'world', hard))
- for atom in syslist:
- if vardb.match(atom):
- remaining_atoms.append((atom, 'system', hard))
- elif action == "prune":
- for atom in syslist:
- if vardb.match(atom):
- remaining_atoms.append((atom, 'system', hard))
- # Pull in everything that's installed since we don't want to prune a
- # package if something depends on it.
- remaining_atoms.extend((atom, 'world', hard) for atom in vardb.cp_all())
- if not myfiles:
- # Try to prune everything that's slotted.
- for cp in vardb.cp_all():
- if len(vardb.cp_list(cp)) > 1:
- args_set.add(cp)
-
- unresolveable = {}
- aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
- metadata_keys = ["PROVIDE", "SLOT", "USE"]
- graph = digraph()
-
- 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
- if action == "depclean" and parent == "world" and myfiles:
- # Filter out packages given as arguments since the user wants
- # to remove those.
- filtered_pkgs = []
- for pkg in pkgs:
- metadata = dict(izip(metadata_keys,
- vardb.aux_get(pkg, metadata_keys)))
- arg_atom = None
- try:
- arg_atom = args_set.findAtomForPackage(pkg, metadata)
- except portage.exception.InvalidDependString, e:
- file_path = os.path.join(myroot, VDB_PATH, pkg, "PROVIDE")
- portage.writemsg("\n\nInvalid PROVIDE: %s\n" % str(s),
- noiselevel=-1)
- portage.writemsg("See '%s'\n" % file_path,
- noiselevel=-1)
- del e
- if not arg_atom:
- filtered_pkgs.append(pkg)
- pkgs = filtered_pkgs
- prune_this = False
- if action == "prune":
- for pkg in pkgs:
- metadata = dict(izip(metadata_keys,
- vardb.aux_get(pkg, metadata_keys)))
- try:
- arg_atom = args_set.findAtomForPackage(pkg, metadata)
- except portage.exception.InvalidDependString, e:
- file_path = os.path.join(myroot, VDB_PATH, pkg, "PROVIDE")
- portage.writemsg("\n\nInvalid PROVIDE: %s\n" % str(s),
- noiselevel=-1)
- portage.writemsg("See '%s'\n" % file_path,
- noiselevel=-1)
- del e
- continue
- if arg_atom:
- prune_this = True
- break
- if len(pkgs) > 1 and (parent != "world" or prune_this):
- # Prune all but the best matching slot, since that's all that a
- # deep world update would pull in. Don't prune if this atom comes
- # directly from world though, since world atoms are greedy when
- # they don't specify a slot.
- visible_in_portdb = [cpv for cpv in pkgs if portdb.match("="+cpv)]
- if visible_in_portdb:
- # For consistency with the update algorithm, keep the highest
- # visible version and prune any versions that are either masked
- # or no longer exist in the portage tree.
- pkgs = visible_in_portdb
- pkgs = [portage.best(pkgs)]
- for pkg in pkgs:
- graph.add(pkg, parent)
- 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])
- if unresolveable:
- print
- print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
- print "%s? It may be necessary to manually uninstall packages that no longer" % action
- print "exist in the portage tree since it may not be possible to satisfy their"
- print "dependencies. Also, be aware of the --with-bdeps option that is documented"
- print "in " + good("`man emerge`") + "."
- print
- if action == "prune":
- print "If you would like to ignore dependencies then use %s." % \
- good("--nodeps")
- return
-
- def show_parents(child_node):
- parent_nodes = graph.parent_nodes(child_node)
- if not parent_nodes:
- # With --prune, the highest version can be pulled in without any
- # real parent since all installed packages are pulled in. In that
- # case there's nothing to show here.
- return
- parent_nodes.sort()
- msg = []
- msg.append(" %s pulled in by:\n" % str(child_node))
- for parent_node in parent_nodes:
- msg.append(" %s\n" % str(parent_node))
- msg.append("\n")
- portage.writemsg_stdout("".join(msg), noiselevel=-1)
-
- cleanlist = []
- if action == "depclean":
- if myfiles:
- for pkg in vardb.cpv_all():
- metadata = dict(izip(metadata_keys,
- vardb.aux_get(pkg, metadata_keys)))
- arg_atom = None
- try:
- arg_atom = args_set.findAtomForPackage(pkg, metadata)
- except portage.exception.InvalidDependString:
- # this error has already been displayed by now
- continue
- if arg_atom:
- if not fakedb.cpv_exists(pkg):
- cleanlist.append(pkg)
- elif "--verbose" in myopts:
- show_parents(pkg)
- else:
- for pkg in vardb.cpv_all():
- if not fakedb.cpv_exists(pkg):
- cleanlist.append(pkg)
- elif "--verbose" in myopts:
- show_parents(pkg)
- elif action == "prune":
- # Prune really uses all installed instead of world. It's not a real
- # reverse dependency so don't display it as such.
- if graph.contains("world"):
- graph.remove("world")
- for atom in args_set:
- for pkg in vardb.match(atom):
- if not fakedb.cpv_exists(pkg):
- cleanlist.append(pkg)
- elif "--verbose" in myopts:
- show_parents(pkg)
-
- if not cleanlist:
- portage.writemsg_stdout(
- ">>> No packages selected for removal by %s\n" % action)
- if "--verbose" not in myopts:
- portage.writemsg_stdout(
- ">>> To see reverse dependencies, use %s\n" % \
- good("--verbose"))
- if action == "prune":
- portage.writemsg_stdout(
- ">>> To ignore dependencies, use %s\n" % \
- good("--nodeps"))
-
- if len(cleanlist):
- unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
- "unmerge", cleanlist, ldpath_mtimes)
-
- if action == "prune":
- return
-
- if not cleanlist and "--quiet" in myopts:
- return
-
- 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=[]
- merge_count = 0
- pretend = "--pretend" in myopts
- fetchonly = "--fetchonly" in myopts or "--fetch-all-uri" in myopts
- if pretend or fetchonly:
- # make the mtimedb readonly
- mtimedb.filename = None
- if "--quiet" not in myopts and \
- ("--pretend" in myopts or "--ask" in myopts or \
- "--tree" in myopts or "--verbose" in myopts):
- action = ""
- if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
- action = "fetched"
- elif "--buildpkgonly" in myopts:
- action = "built"
- 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()
-
- # Adjust config according to options of the command being resumed.
- for myroot in trees:
- mysettings = trees[myroot]["vartree"].settings
- mysettings.unlock()
- adjust_config(myopts, mysettings)
- mysettings.lock()
- del myroot, mysettings
-
- # "myopts" is a list for backward compatibility.
- resume_opts = mtimedb["resume"].get("myopts", [])
- if isinstance(resume_opts, list):
- resume_opts = dict((k,True) for k in resume_opts)
- for opt in ("--skipfirst", "--ask", "--tree"):
- resume_opts.pop(opt, None)
- myopts.update(resume_opts)
- show_spinner = "--quiet" not in myopts and "--nodeps" not in myopts
- if not show_spinner:
- spinner.update = spinner.update_quiet
- if show_spinner:
- print "Calculating dependencies ",
- myparams = create_depgraph_params(myopts, myaction)
- mydepgraph = depgraph(settings, trees,
- myopts, myparams, spinner)
- try:
- mydepgraph.loadResumeCommand(mtimedb["resume"])
- except portage.exception.PackageNotFound:
- if show_spinner:
- print
- from portage.output import EOutput
- out = EOutput()
- out.eerror("Error: The resume list contains packages that are no longer")
- out.eerror(" available to be emerged. Please restart/continue")
- out.eerror(" the merge operation manually.")
- return 1
- if show_spinner:
- print "\b\b... done!"
- else:
- if ("--resume" in myopts):
- print darkgreen("emerge: It seems we have nothing to resume...")
- return os.EX_OK
-
- myparams = create_depgraph_params(myopts, myaction)
- if myaction in ["system","world"]:
- if "--quiet" not in myopts and "--nodeps" not 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."
- return 1
- if "--quiet" not in myopts and "--nodeps" not in myopts:
- print "\b\b... done!"
- else:
- if "--quiet" not in myopts and "--nodeps" not 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)
- return 1
- if not retval:
- return 1
- if "--quiet" not in myopts and "--nodeps" not 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")
- return 1
-
- if "--pretend" not in myopts and \
- ("--ask" in myopts or "--tree" in myopts or \
- "--verbose" in myopts) and \
- not ("--quiet" in myopts and "--ask" not in myopts):
- if "--resume" in myopts:
- 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...")
- return os.EX_OK
- favorites = mtimedb["resume"]["favorites"]
- retval = mydepgraph.display(mymergelist, favorites=favorites)
- if retval != os.EX_OK:
- return retval
- prompt="Would you like to resume merging these packages?"
- else:
- retval = mydepgraph.display(
- mydepgraph.altlist(reversed=("--tree" in myopts)),
- favorites=favorites)
- if retval != os.EX_OK:
- return retval
- 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()
- return 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
- return os.EX_OK
- 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 "--ask" in myopts and userquery(prompt) == "No":
- print
- print "Quitting."
- print
- return os.EX_OK
- # Don't ask again (e.g. when auto-cleaning packages after merge)
- myopts.pop("--ask", None)
-
- if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
- if ("--resume" in myopts):
- 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...")
- return os.EX_OK
- favorites = mtimedb["resume"]["favorites"]
- retval = mydepgraph.display(mymergelist, favorites=favorites)
- if retval != os.EX_OK:
- return retval
- else:
- retval = mydepgraph.display(
- mydepgraph.altlist(reversed=("--tree" in myopts)),
- favorites=favorites)
- if retval != os.EX_OK:
- return retval
- if "--buildpkgonly" in myopts and \
- not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
- print "\n!!! --buildpkgonly requires all dependencies to be merged."
- print "!!! You have to merge the dependencies before you can build this package.\n"
- return 1
- 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"
- return 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)
- merge_count = mergetask.curval
- 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()
- if favorites:
- mydepgraph.saveNomergeFavorites()
- del mydepgraph
- mergetask = MergeTask(settings, trees, myopts)
- retval = mergetask.merge(pkglist, favorites, mtimedb)
- merge_count = mergetask.curval
-
- if retval == os.EX_OK and not (pretend or fetchonly):
- mtimedb.pop("resume", None)
- if "yes" == settings.get("AUTOCLEAN"):
- portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
- 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")
-
- if merge_count and not (pretend or fetchonly):
- post_emerge(trees, mtimedb, retval)
- return retval
-
-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")
- },
- "--reinstall": {
- "help":"specify conditions to trigger package reinstallation",
- "type":"choice",
- "choices":["changed-use"]
- }
- }
-
- 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
- for var in "ARCH", "USERLAND":
- if mysettings.get(var):
- continue
- print >> sys.stderr, bad(("\a!!! %s is not set... " % var) + \
- "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(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 myopts:
- 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
-
- if "--quiet" not in myopts:
- 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 colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
- break
-
- setconfigpaths = [os.path.join(GLOBAL_CONFIG_PATH, "sets.conf")]
- setconfigpaths.append(os.path.join(settings["PORTDIR"], "sets.conf"))
- setconfigpaths += [os.path.join(x, "sets.conf") for x in settings["PORDIR_OVERLAY"].split()]
- setconfigpaths.append(os.path.join(settings["PORTAGE_CONFIGROOT"],
- USER_CONFIG_PATH.lstrip(os.path.sep), "sets.conf"))
- #setconfig = SetConfig(setconfigpaths, settings, trees[settings["ROOT"]])
- setconfig = make_default_config(settings, trees[settings["ROOT"]])
- del setconfigpaths
- if myaction not in ["search", "metadata", "sync"]:
- oldargs = myfiles[:]
- packagesets, setconfig_errors = setconfig.getSetsWithAliases()
- for s in packagesets:
- if s in myfiles:
- # TODO: check if the current setname also resolves to a package name
- if myaction in ["unmerge", "prune", "clean", "depclean"] and not packagesets[s].supportsOperation("unmerge"):
- print "emerge: the given set %s does not support unmerge operations" % s
- sys.exit(1)
- if not packagesets[s].getAtoms():
- print "emerge: '%s' is an empty set" % s
- else:
- myfiles.extend(packagesets[s].getAtoms())
- for e in packagesets[s].errors:
- print e
- myfiles.remove(s)
- # Need to handle empty sets specially, otherwise emerge will react
- # with the help message for empty argument lists
- if oldargs and not myfiles:
- print "emerge: no targets left after set expansion"
- sys.exit(0)
- del oldargs
-
- 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 "--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") or \
- (myaction == "sync" and os.access(settings["PORTDIR"], os.W_OK)))
- 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 is 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 is " + \
- "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, setconfig)
- elif myaction in ("clean", "unmerge") or \
- (myaction == "prune" and "--nodeps" in myopts):
- 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(trees, mtimedb, os.EX_OK)
-
- elif myaction in ("depclean", "prune"):
- validate_ebuild_environment(trees)
- action_depclean(settings, trees, mtimedb["ldpath"],
- myopts, myaction, myfiles, spinner)
- if "--pretend" not in myopts:
- post_emerge(trees, mtimedb, os.EX_OK)
- # "update", "system", or just process files:
- else:
- validate_ebuild_environment(trees)
- if "--pretend" not in myopts:
- display_news_notification(trees)
- retval = action_build(settings, trees, mtimedb,
- myopts, myaction, myfiles, spinner)
- if "--pretend" in myopts:
- display_news_notification(trees)
- return retval
-
-if __name__ == "__main__":
- retval = emerge_main()
- sys.exit(retval)
diff --git a/pym/emerge/help.py b/pym/emerge/help.py
deleted file mode 100644
index 5bb93a1f4..000000000
--- a/pym/emerge/help.py
+++ /dev/null
@@ -1,394 +0,0 @@
-# Copyright 1999-2007 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-# $Id$
-
-
-import os,sys
-from portage.output import bold, turquoise, green
-
-def shorthelp():
- print bold("emerge:")+" the other white meat (command-line interface to the Portage system)"
- print bold("Usage:")
- print " "+turquoise("emerge")+" [ "+green("options")+" ] [ "+green("action")+" ] [ "+turquoise("ebuildfile")+" | "+turquoise("tbz2file")+" | "+turquoise("dependency")+" ] [ ... ]"
- print " "+turquoise("emerge")+" [ "+green("options")+" ] [ "+green("action")+" ] < "+turquoise("system")+" | "+turquoise("world")+" >"
- print " "+turquoise("emerge")+" < "+turquoise("--sync")+" | "+turquoise("--metadata")+" | "+turquoise("--info")+" >"
- print " "+turquoise("emerge")+" "+turquoise("--resume")+" [ "+green("--pretend")+" | "+green("--ask")+" | "+green("--skipfirst")+" ]"
- print " "+turquoise("emerge")+" "+turquoise("--help")+" [ "+green("system")+" | "+green("world")+" | "+green("--sync")+" ] "
- print bold("Options:")+" "+green("-")+"["+green("abBcCdDefgGhkKlnNoOpqPsStuvV")+"] ["+green("--oneshot")+"] ["+green("--newuse")+"] ["+green("--noconfmem")+"]"
- print " [ " + green("--color")+" < " + turquoise("y") + " | "+ turquoise("n")+" > ] [ "+green("--columns")+" ]"
- print " [ "+green("--reinstall ")+turquoise("changed-use")+" ] ["+green("--nospinner")+"]"
- print " [ "+green("--deep")+" ] [" + green("--with-bdeps")+" < " + turquoise("y") + " | "+ turquoise("n")+" > ]"
- print bold("Actions:")+" [ "+green("--clean")+" | "+green("--depclean")+" | "+green("--prune")+" | "+green("--regen")+" | "+green("--search")+" | "+green("--unmerge")+" ]"
-
-def help(myaction,myopts,havecolor=1):
- if not myaction and ("--verbose" not in myopts):
- shorthelp()
- print
- print " For more help try 'emerge --help --verbose' or consult the man page."
- elif not myaction:
- shorthelp()
- print
- print turquoise("Help (this screen):")
- print " "+green("--help")+" ("+green("-h")+" short option)"
- print " Displays this help; an additional argument (see above) will tell"
- print " emerge to display detailed help."
- print
- print turquoise("Actions:")
- print " "+green("--clean")+" ("+green("-c")+" short option)"
- print " Cleans the system by removing outdated packages which will not"
- print " remove functionalities or prevent your system from working."
- print " The arguments can be in several different formats :"
- print " * world "
- print " * system or"
- print " * 'dependency specification' (in single quotes is best.)"
- print " Here are a few examples of the dependency specification format:"
- print " "+bold("binutils")+" matches"
- print " binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
- print " "+bold("sys-devel/binutils")+" matches"
- print " binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
- print " "+bold(">sys-devel/binutils-2.11.90.0.7")+" matches"
- print " binutils-2.11.92.0.12.3-r1"
- print " "+bold(">=sys-devel/binutils-2.11.90.0.7")+" matches"
- print " binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
- print " "+bold("<=sys-devel/binutils-2.11.92.0.12.3-r1")+" matches"
- print " binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
- print
- print " "+green("--config")
- print " Runs package-specific operations that must be executed after an"
- print " emerge process has completed. This usually entails configuration"
- print " file setup or other similar setups that the user may wish to run."
- print
- print " "+green("--depclean")
- print " Cleans the system by removing packages that are not associated"
- print " with explicitly merged packages. Depclean works by creating the"
- print " full dependency tree from the system list and the world file,"
- print " then comparing it to installed packages. Packages installed, but"
- print " not associated with an explicit merge are listed as candidates"
- print " for unmerging. Inexperienced users are advised to use --pretend"
- print " with this option in order to see a preview of which packages will"
- print " be uninstalled. "+turquoise(" WARNING: Removing some packages may cause")
- print " "+turquoise("packages which link to the removed package to stop working and")
- print " "+turquoise("complain about missing libraries. Rebuild the complaining package")
- print " "+turquoise("to fix this issue.")+" Also see --with-bdeps for behavior with"
- print " respect to build time dependencies that are not strictly"
- print " required. Depclean serves as a dependency aware version of"
- print " --unmerge. When given one or more atoms, it will unmerge matched"
- print " packages that have no reverse dependencies. Use --depclean"
- print " together with --verbose to show reverse dependencies."
- print
- print " "+green("--info")
- print " Displays important portage variables that will be exported to"
- print " ebuild.sh when performing merges. This information is useful"
- print " for bug reports and verification of settings. All settings in"
- print " make.{conf,globals,defaults} and the environment show up if"
- print " run with the '--verbose' flag."
- print
- print " "+green("--metadata")
- print " Transfers metadata cache from ${PORTDIR}/metadata/cache/ to"
- print " /var/cache/edb/dep/ as is normally done on the tail end of an"
- print " rsync update using " + bold("emerge --sync") + ". This process populates the"
- print " cache database that portage uses for pre-parsed lookups of"
- print " package data. It does not populate cache for the overlays"
- print " listed in PORTDIR_OVERLAY. In order to generate cache for"
- print " overlays, use " + bold("--regen") + "."
- print
- print " "+green("--prune")+" ("+green("-P")+" short option)"
- print " "+turquoise("WARNING: This action can remove important packages!")
- print " Removes all but the highest installed version of a package"
- print " from your system. This action doesn't verify the possible binary"
- print " compatibility between versions and can thus remove essential"
- print " dependencies from your system. Use --prune together with"
- print " --verbose to show reverse dependencies or with --nodeps to"
- print " ignore all dependencies."
- print
- print " "+green("--regen")
- print " Causes portage to check and update the dependency cache of all"
- print " ebuilds in the portage tree. This is not recommended for rsync"
- print " users as rsync updates the cache using server-side caches."
- print " Rsync users should simply 'emerge --sync' to regenerate."
- print
- print " "+green("--resume")
- print " Resumes the most recent merge list that has been aborted due to an"
- print " error. Please note that this operation will only return an error"
- print " on failure. If there is nothing for portage to do, then portage"
- print " will exit with a message and a success condition. A resume list"
- print " will persist until it has been completed in entirety or until"
- print " another aborted merge list replaces it. The resume history is"
- print " capable of storing two merge lists. After one resume list"
- print " completes, it is possible to invoke --resume once again in order"
- print " to resume an older list."
- print
- print " "+green("--search")+" ("+green("-s")+" short option)"
- print " Searches for matches of the supplied string in the current local"
- print " portage tree. By default emerge uses a case-insensitive simple "
- print " search, but you can enable a regular expression search by "
- print " prefixing the search string with %."
- print " Prepending the expression with a '@' will cause the category to"
- print " be included in the search."
- print " A few examples:"
- print " "+bold("emerge --search libc")
- print " list all packages that contain libc in their name"
- print " "+bold("emerge --search '%^kde'")
- print " list all packages starting with kde"
- print " "+bold("emerge --search '%gcc$'")
- print " list all packages ending with gcc"
- print " "+bold("emerge --search '%@^dev-java.*jdk'")
- print " list all available Java JDKs"
- print
- print " "+green("--searchdesc")+" ("+green("-S")+" short option)"
- print " Matches the search string against the description field as well"
- print " the package's name. Take caution as the descriptions are also"
- print " matched as regular expressions."
- print " emerge -S html"
- print " emerge -S applet"
- print " emerge -S 'perl.*module'"
- print
- print " "+green("--unmerge")+" ("+green("-C")+" short option)"
- print " "+turquoise("WARNING: This action can remove important packages!")
- print " Removes all matching packages. This does no checking of"
- print " dependencies, so it may remove packages necessary for the proper"
- print " operation of your system. Its arguments can be atoms or"
- print " ebuilds. For a dependency aware version of --unmerge, use"
- print " --depclean or --prune."
- print
- print " "+green("--update")+" ("+green("-u")+" short option)"
- print " Updates packages to the best version available, which may not"
- print " always be the highest version number due to masking for testing"
- print " and development. This will also update direct dependencies which"
- print " may not what you want. Package atoms specified on the command line"
- print " are greedy, meaning that unspecific atoms may match multiple"
- print " installed versions of slotted packages."
- print
- print " "+green("--version")+" ("+green("-V")+" short option)"
- print " Displays the currently installed version of portage along with"
- print " other information useful for quick reference on a system. See"
- print " "+bold("emerge info")+" for more advanced information."
- print
- print turquoise("Options:")
- print " "+green("--alphabetical")
- print " When displaying USE and other flag output, combines the enabled"
- print " and disabled flags into a single list and sorts it alphabetically."
- print " With this option, output such as USE=\"dar -bar -foo\" will instead"
- print " be displayed as USE=\"-bar dar -foo\""
- print
- print " "+green("--ask")+" ("+green("-a")+" short option)"
- print " before performing the merge, display what ebuilds and tbz2s will"
- print " be installed, in the same format as when using --pretend; then"
- print " ask whether to continue with the merge or abort. Using --ask is"
- print " more efficient than using --pretend and then executing the same"
- print " command without --pretend, as dependencies will only need to be"
- print " calculated once. WARNING: If the \"Enter\" key is pressed at the"
- print " prompt (with no other input), it is interpreted as acceptance of"
- print " the first choice. Note that the input buffer is not cleared prior"
- print " to the prompt, so an accidental press of the \"Enter\" key at any"
- print " time prior to the prompt will be interpreted as a choice!"
- print
- print " "+green("--buildpkg")+" ("+green("-b")+" short option)"
- print " Tell emerge to build binary packages for all ebuilds processed"
- print " (in addition to actually merging the packages. Useful for"
- print " maintainers or if you administrate multiple Gentoo Linux"
- print " systems (build once, emerge tbz2s everywhere) as well as disaster"
- print " recovery."
- print
- print " "+green("--buildpkgonly")+" ("+green("-B")+" short option)"
- print " Creates a binary package, but does not merge it to the"
- print " system. This has the restriction that unsatisfied dependencies"
- print " must not exist for the desired package as they cannot be used if"
- print " they do not exist on the system."
- print
- print " "+green("--changelog")+" ("+green("-l")+" short option)"
- print " When pretending, also display the ChangeLog entries for packages"
- print " that will be upgraded."
- print
- print " "+green("--color") + " < " + turquoise("y") + " | "+ turquoise("n")+" >"
- print " Enable or disable color output. This option will override NOCOLOR"
- print " (see make.conf(5)) and may also be used to force color output when"
- print " stdout is not a tty (by default, color is disabled unless stdout"
- print " is a tty)."
- print
- print " "+green("--columns")
- print " Display the pretend output in a tabular form. Versions are"
- print " aligned vertically."
- print
- print " "+green("--debug")+" ("+green("-d")+" short option)"
- print " Tell emerge to run the ebuild command in --debug mode. In this"
- print " mode, the bash build environment will run with the -x option,"
- print " causing it to output verbose debug information print to stdout."
- print " --debug is great for finding bash syntax errors as providing"
- print " very verbose information about the dependency and build process."
- print
- print " "+green("--deep")+" ("+green("-D")+" short option)"
- print " This flag forces emerge to consider the entire dependency tree of"
- print " packages, instead of checking only the immediate dependencies of"
- print " the packages. As an example, this catches updates in libraries"
- print " that are not directly listed in the dependencies of a package."
- print " Also see --with-bdeps for behavior with respect to build time"
- print " dependencies that are not strictly required."
- print
- print " "+green("--emptytree")+" ("+green("-e")+" short option)"
- print " Virtually tweaks the tree of installed packages to contain"
- print " nothing. This is great to use together with --pretend. This makes"
- print " it possible for developers to get a complete overview of the"
- print " complete dependency tree of a certain package."
- print
- print " "+green("--fetchonly")+" ("+green("-f")+" short option)"
- print " Instead of doing any package building, just perform fetches for"
- print " all packages (main package as well as all dependencies.) When"
- print " used in combination with --pretend all the SRC_URIs will be"
- print " displayed multiple mirrors per line, one line per file."
- print
- print " "+green("--fetch-all-uri")+" ("+green("-F")+" short option)"
- print " Same as --fetchonly except that all package files, including those"
- print " not required to build the package, will be processed."
- print
- print " "+green("--getbinpkg")+" ("+green("-g")+" short option)"
- print " Using the server and location defined in PORTAGE_BINHOST, portage"
- print " will download the information from each binary file there and it"
- print " will use that information to help build the dependency list. This"
- print " option implies '-k'. (Use -gK for binary-only merging.)"
- print
- print " "+green("--getbinpkgonly")+" ("+green("-G")+" short option)"
- print " This option is identical to -g, as above, except it will not use"
- print " ANY information from the local machine. All binaries will be"
- print " downloaded from the remote server without consulting packages"
- print " existing in the packages directory."
- print
- print " "+green("--newuse")+" ("+green("-N")+" short option)"
- print " Tells emerge to include installed packages where USE flags have "
- print " changed since installation."
- print
- print " "+green("--noconfmem")
- print " Portage keeps track of files that have been placed into"
- print " CONFIG_PROTECT directories, and normally it will not merge the"
- print " same file more than once, as that would become annoying. This"
- print " can lead to problems when the user wants the file in the case"
- print " of accidental deletion. With this option, files will always be"
- print " merged to the live fs instead of silently dropped."
- print
- print " "+green("--nodeps")+" ("+green("-O")+" short option)"
- print " Merge specified packages, but don't merge any dependencies."
- print " Note that the build may fail if deps aren't satisfied."
- print
- print " "+green("--noreplace")+" ("+green("-n")+" short option)"
- print " Skip the packages specified on the command-line that have"
- print " already been installed. Without this option, any packages,"
- print " ebuilds, or deps you specify on the command-line *will* cause"
- print " Portage to remerge the package, even if it is already installed."
- print " Note that Portage won't remerge dependencies by default."
- print
- print " "+green("--nospinner")
- print " Disables the spinner regardless of terminal type."
- print
- print " "+green("--oneshot")+" ("+green("-1")+" short option)"
- print " Emerge as normal, but don't add packages to the world profile."
- print " This package will only be updated if it is depended upon by"
- print " another package."
- print
- print " "+green("--onlydeps")+" ("+green("-o")+" short option)"
- print " Only merge (or pretend to merge) the dependencies of the"
- print " specified packages, not the packages themselves."
- print
- print " "+green("--pretend")+" ("+green("-p")+" short option)"
- print " Instead of actually performing the merge, simply display what"
- print " ebuilds and tbz2s *would* have been installed if --pretend"
- print " weren't used. Using --pretend is strongly recommended before"
- print " installing an unfamiliar package. In the printout, N = new,"
- print " U = updating, R = replacing, F = fetch restricted, B = blocked"
- print " by an already installed package, D = possible downgrading,"
- print " S = slotted install. --verbose causes affecting use flags to be"
- print " printed out accompanied by a '+' for enabled and a '-' for"
- print " disabled USE flags."
- print
- print " "+green("--quiet")+" ("+green("-q")+" short option)"
- print " Effects vary, but the general outcome is a reduced or condensed"
- print " output from portage's displays."
- print
- print " "+green("--reinstall ") + turquoise("changed-use")
- print " Tells emerge to include installed packages where USE flags have"
- print " changed since installation. Unlike --newuse, this option does"
- print " not trigger reinstallation when flags that the user has not"
- print " enabled are added or removed."
- print
- print " "+green("--skipfirst")
- print " This option is only valid in a resume situation. It removes the"
- print " first package in the resume list so that a merge may continue in"
- print " the presence of an uncorrectable or inconsequential error. This"
- print " should only be used in cases where skipping the package will not"
- print " result in failed dependencies."
- print
- print " "+green("--tree")+" ("+green("-t")+" short option)"
- print " Shows the dependency tree using indentation for dependencies."
- print " The packages are also listed in reverse merge order so that"
- print " a package's dependencies follow the package. Only really useful"
- print " in combination with --emptytree, --update or --deep."
- print
- print " "+green("--usepkg")+" ("+green("-k")+" short option)"
- print " Tell emerge to use binary packages (from $PKGDIR) if they are"
- print " available, thus possibly avoiding some time-consuming compiles."
- print " This option is useful for CD installs; you can export"
- print " PKGDIR=/mnt/cdrom/packages and then use this option to have"
- print " emerge \"pull\" binary packages from the CD in order to satisfy"
- print " dependencies."
- print
- print " "+green("--usepkgonly")+" ("+green("-K")+" short option)"
- print " Like --usepkg above, except this only allows the use of binary"
- print " packages, and it will abort the emerge if the package is not"
- print " available at the time of dependency calculation."
- print
- print " "+green("--verbose")+" ("+green("-v")+" short option)"
- print " Effects vary, but the general outcome is an increased or expanded"
- print " display of content in portage's displays."
- print
- print " "+green("--with-bdeps")+" < " + turquoise("y") + " | "+ turquoise("n")+" >"
- print " In dependency calculations, pull in build time dependencies that"
- print " are not strictly required. This defaults to 'n' for installation"
- print " actions and 'y' for the --depclean action. This setting can be"
- print " added to EMERGE_DEFAULT_OPTS (see make.conf(5)) and later"
- print " overridden via the command line."
- print
- elif myaction == "sync":
- print
- print bold("Usage: ")+turquoise("emerge")+" "+turquoise("--sync")
- print
- print " 'emerge --sync' tells emerge to update the Portage tree as specified in"
- print " The SYNC variable found in /etc/make.conf. By default, SYNC instructs"
- print " emerge to perform an rsync-style update with rsync.gentoo.org."
- print
- print " 'emerge-webrsync' exists as a helper app to emerge --sync, providing a"
- print " method to receive the entire portage tree as a tarball that can be"
- print " extracted and used. First time syncs would benefit greatly from this."
- print
- print " "+turquoise("WARNING:")
- print " If using our rsync server, emerge will clean out all files that do not"
- print " exist on it, including ones that you may have created. The exceptions"
- print " to this are the distfiles, local and packages directories."
- print
- elif myaction=="system":
- print
- print bold("Usage: ")+turquoise("emerge")+" [ "+green("options")+" ] "+turquoise("system")
- print
- print " \"emerge system\" is the Portage system update command. When run, it"
- print " will scan the etc/make.profile/packages file and determine what"
- print " packages need to be installed so that your system meets the minimum"
- print " requirements of your current system profile. Note that this doesn't"
- print " necessarily bring your system up-to-date at all; instead, it just"
- print " ensures that you have no missing parts. For example, if your system"
- print " profile specifies that you should have sys-apps/iptables installed"
- print " and you don't, then \"emerge system\" will install it (the most"
- print " recent version that matches the profile spec) for you. It's always a"
- print " good idea to do an \"emerge --pretend system\" before an \"emerge"
- print " system\", just so you know what emerge is planning to do."
- print
- elif myaction=="world":
- print
- print bold("Usage: ")+turquoise("emerge")+" [ "+green("options")+" ] "+turquoise("world")
- print
- print " 'emerge world' is the Portage command for completely updating your"
- print " system. The normal procedure is to first do an 'emerge --sync' and"
- print " then an 'emerge --update --deep world'. The first command brings your"
- print " local Portage tree up-to-date with the latest version information and"
- print " ebuilds. The second command then rebuilds all packages for which newer"
- print " versions or newer ebuilds have become available since you last did a"
- print " sync and update."
- print
-