#!@PYTHON@ -O
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
-# $Id: /var/cvsroot/gentoo-src/portage/bin/emerge,v 1.345.2.38 2005/08/13 17:25:26 ferringb Exp $
-
-import os,sys
-os.environ["PORTAGE_CALLER"]="emerge"
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+# $Id$
+import sys
+# This block ensures that ^C interrupts are handled quietly.
try:
- import portage
+ 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) # If they control C during imports, just die silently
+ sys.exit(1)
-import emergehelp,xpak,string,re,commands,time,shutil,traceback,signal,socket,types
-from stat import *
-from output import *
+import os, stat
+sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+
+os.environ["PORTAGE_LEGACY_GLOBALS"] = "false"
+import portage
+del os.environ["PORTAGE_LEGACY_GLOBALS"]
+from portage import digraph
+
+import emergehelp, xpak, commands, errno, re, socket, string, time, types
+from output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
+ havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
+ xtermTitleReset, yellow
+from output import create_color_func
+good = create_color_func("GOOD")
+bad = create_color_func("BAD")
import portage_util
import portage_locks
import portage_exception
import portage_const
+from portage_data import secpass
+
+if not hasattr(__builtins__, "set"):
+ from sets import Set as set
+
+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 = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
-spinner_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.",
- ]
-
-
-def update_basic_spinner():
- global spinner, spinpos
- spinpos = (spinpos+1) % 500
- if (spinpos % 100) == 0:
- if spinpos == 0:
- sys.stdout.write(". ")
- else:
- sys.stdout.write(".")
- sys.stdout.flush()
-
-def update_scroll_spinner():
- global spinner, spinpos
- if(spinpos >= len(spinner)):
- sys.stdout.write(darkgreen(" \b\b\b"+spinner[len(spinner)-1-(spinpos%len(spinner))]))
- else:
- sys.stdout.write(green("\b "+spinner[spinpos]))
- sys.stdout.flush()
- spinpos = (spinpos+1) % (2*len(spinner))
-
-def update_twirl_spinner():
- global spinner, spinpos
- spinpos = (spinpos+1) % len(spinner)
- sys.stdout.write("\b\b "+spinner[spinpos])
- sys.stdout.flush()
+ 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_quiet_spinner():
- return
+ 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))
-spinpos = 0
-spinner = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
-update_spinner = update_twirl_spinner
-if "candy" in portage.settings.features:
- spinner = spinner_msgs[int(time.time()*100)%len(spinner_msgs)]
- update_spinner = update_scroll_spinner
+ 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()
-if (not sys.stdout.isatty()) or (portage.settings["NOCOLOR"] in ["yes","true"]):
- nocolor()
+ 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.
+ 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.
while True:
response=raw_input("["+string.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,
ret.insert(x, ver)
return ret
-if portage.settings.has_key("PORTAGE_NICENESS"):
- try:
- os.nice(int(portage.settings["PORTAGE_NICENESS"]))
- except (OSError,ValueError), e:
- print "!!! Failed to change nice value to '"+str(portage.settings["PORTAGE_NICENESS"])+"'"
- print "!!!",e
-
-#Freeze the portdbapi for enhanced performance:
-portage.portdb.freeze()
-
-# Kill noauto as it will break merges otherwise.
-while 'noauto' in portage.features:
- del portage.features[portage.features.index('noauto')]
-#number of ebuilds merged
-merged=0
-params=["selective", "deep", "self", "recurse", "empty"]
actions=[
"clean", "config", "depclean",
"info", "metadata",
options=[
"--ask", "--alphabetical",
"--buildpkg", "--buildpkgonly",
-"--changelog", "--columns", "--cols",
+"--changelog", "--columns",
"--debug", "--deep",
"--digest",
"--emptytree",
"--onlydeps", "--pretend",
"--quiet", "--resume",
"--searchdesc", "--selective",
-"--skipfirst", "--skip-first",
+"--skipfirst",
"--tree",
"--update",
"--usepkg", "--usepkgonly",
"v":"--verbose", "V":"--version"
}
-myaction=None
-myopts=[]
-myfiles=[]
-edebug=0
-
-# process short actions
-tmpcmdline=sys.argv[1:]
-if "--ignore-default-opts" not in tmpcmdline:
- tmpcmdline.extend(portage.settings["EMERGE_DEFAULT_OPTS"].split())
-cmdline=[]
-for x in tmpcmdline:
- if x[0:1]=="-" and x[1:2]!="-":
- for y in x[1:]:
- if shortmapping.has_key(y):
- if shortmapping[y] in cmdline:
- print
- print "*** Warning: Redundant use of",shortmapping[y]
- else:
- cmdline.append(shortmapping[y])
- else:
- print "!!! Error: -"+y+" is an invalid short action or option."
- sys.exit(1)
- else:
- cmdline.append(x)
-
-# process the options and command arguments
-for x in cmdline:
- if not x:
- continue
- if len(x)>=2 and x[0:2]=="--":
- if x == "--cols":
- x = "--columns"
- elif x == "--skip-first":
- x = "--skipfirst"
- if x in options:
- if x not in myopts:
- myopts.append(x)
- elif x[2:] in actions:
- if myaction:
- if myaction not in ["system", "world"]:
- myaction="--"+myaction
- print
- print red("!!!")+green(" Multiple actions requested... Please choose one only.")
- print red("!!!")+" '"+darkgreen(myaction)+"' "+red("or")+" '"+darkgreen(x)+"'"
- print
- sys.exit(1)
- myaction=x[2:]
- else:
- print "!!! Error:",x,"is an invalid option."
- sys.exit(1)
- elif (not myaction) and (x in actions):
- if x not in ["system", "world"]:
- print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
- if myaction:
- print
- print red("!!!")+green(" Multiple actions requested... Please choose one only.")
- print red("!!! '")+darkgreen(myaction)+"' "+red("or")+" '"+darkgreen(x)+"'"
- print
- sys.exit(1)
- myaction=x
- elif x[-1]=="/":
- # this little conditional helps tab completion
- myfiles.append(x[:-1])
- else:
- myfiles.append(x)
-
-
-if "moo" in myfiles:
- print """
-
- Larry loves Gentoo (""" + os.uname()[0] + """)
-
- _______________________
-< Have you mooed today? >
- -----------------------
- \ ^__^
- \ (oo)\_______
- (__)\ )\/\
- ||----w |
- || ||
-
-"""
-
-if (myaction in ["world", "system"]) and myfiles:
- print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
- sys.exit(1)
-
-for x in myfiles:
- ext = os.path.splitext(x)[1]
- if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
- print "emerging by path implies --oneshot... adding --oneshot to options."
- print red("\n*** emerging by path is broken and may not always work!!!\n")
- break
-
-if ("--tree" in myopts) and ("--columns" in myopts):
- print "emerge: can't specify both of \"--tree\" and \"--columns\"."
- sys.exit(1)
-
-if ("--quiet" in myopts):
- update_spinner = update_quiet_spinner
- portage_util.noiselimit = -1
- portage.settings.unlock()
- portage.settings["PORTAGE_QUIET"]="1"
- portage.settings.backup_changes("PORTAGE_QUIET")
- portage.settings.lock()
-
-# Always create packages if FEATURES=buildpkg
-# Imply --buildpkg if --buildpkgonly
-if ("buildpkg" in portage.features) or ("--buildpkgonly" in myopts):
- if "--buildpkg" not in myopts:
- myopts.append("--buildpkg")
-
-# --tree only makes sense with --pretend
-if "--tree" in myopts and not (("--pretend" in myopts) or ("--ask" in myopts)):
- print ">>> --tree implies --pretend... adding --pretend to options."
- myopts.append("--pretend")
-
-# 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.append("--search")
- myaction = "search"
-
-# Always try and fetch binary packages if FEATURES=getbinpkg
-if ("getbinpkg" in portage.features):
- myopts.append("--getbinpkg")
-
-if "--skipfirst" in myopts and "--resume" not in myopts:
- myopts.append("--resume")
-
-if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
- myopts.append("--usepkgonly")
-
-if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
- myopts.append("--getbinpkg")
-
-if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
- myopts.append("--usepkg")
-
-# Also allow -K to apply --usepkg/-k
-if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
- myopts.append("--usepkg")
-
-if ("--newuse" in myopts) and not ("--update" in myopts):
- print ">>> --newuse implies --update... adding --update to options."
- myopts.append("--update")
-
-# Also allow -l to apply --pretend/-p, but if already in --ask mode
-if ("--changelog" in myopts) and not (("--pretend" in myopts) or ("--ask" in myopts)):
- print ">>> --changelog implies --pretend... adding --pretend to options."
- myopts.append("--pretend")
-
-# Allow -p to remove --ask
-if ("--pretend" in myopts) and ("--ask" in myopts):
- print ">>> --pretend disables --ask... removing --ask from options."
- myopts.remove("--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")
- sys.exit(1)
-
-# Set so that configs will be merged regardless of remembered status
-if ("--noconfmem" in myopts):
- portage.settings.unlock()
- portage.settings["NOCONFMEM"]="1"
- portage.settings.backup_changes("NOCONFMEM")
- portage.settings.lock()
-
-# Set various debug markers... They should be merged somehow.
-if ("--debug" in myopts):
- portage.settings.unlock()
- portage.settings["PORTAGE_DEBUG"]="1"
- portage.settings.backup_changes("PORTAGE_DEBUG")
- portage.debug=1
- portage.settings.lock()
- if "python-trace" in portage.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..."
- myopts.remove("--tree")
-
-# Set color output
-if "--nocolor" in myopts or \
-portage.settings["NOCOLOR"] in ("yes","true"):
- nocolor()
- if "NOCOLOR" not in portage.settings:
- portage.settings.unlock()
- portage.settings["NOCOLOR"] = "true"
- portage.settings.backup_changes("NOCOLOR")
- portage.settings.lock()
-
-if not ("--quiet" in myopts):
- if not sys.stdout.isatty() or ("--nospinner" in myopts):
- update_spinner = update_basic_spinner
-
-CLEAN_DELAY = 5
-EMERGE_WARNING_DELAY = 10
-if portage.settings["CLEAN_DELAY"]:
- CLEAN_DELAY = string.atoi("0"+portage.settings["CLEAN_DELAY"])
-if portage.settings["EMERGE_WARNING_DELAY"]:
- EMERGE_WARNING_DELAY = string.atoi("0"+portage.settings["EMERGE_WARNING_DELAY"])
-
-def emergelog(mystr,short_msg=None):
- if "notitles" not in portage.features:
+def emergelog(xterm_titles, mystr, short_msg=None):
+ if xterm_titles:
if short_msg:
xtermTitle(short_msg)
else:
xtermTitle(mystr)
try:
- #seems odd opening a file each write...
- elog = portage_const.EPREFIX+"/var/log/emerge.log"
- if not os.path.exists(elog):
- mylogfile=open(elog, "w")
- os.chmod(elog, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
- os.chown(elog, portage.portage_uid, portage.portage_gid)
- else:
- mylogfile=open(elog, "a")
+ file_path = portage_const.EPREFIX+"/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)
l=portage_locks.lockfile(mylogfile)
# seek because we may have gotten held up by the lock.
mylogfile.flush()
portage_locks.unlockfile(l)
mylogfile.close()
- except SystemExit, e:
- raise # Needed else can't exit
- except Exception, e:
- if edebug:
- print "emergelog():",e
- pass
-
-def emergeexit():
- """This gets out final log message in before we quit."""
- if "--pretend" not in myopts:
- emergelog(" *** terminating.")
- if "notitles" not in portage.features:
- xtermTitleReset()
-portage.atexit_register(emergeexit)
-
-def emergeexitsig(signum, frame):
- signal.signal(signal.SIGINT, signal.SIG_IGN)
- portage.portageexit()
- portage_util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
- sys.exit(100+signum)
-signal.signal(signal.SIGINT, emergeexitsig)
+ except (IOError,OSError,portage_exception.PortageException), e:
+ if secpass >= 1:
+ print >> sys.stderr, "emergelog():",e
def countdown(secs=5, doing="Starting"):
if secs:
ticks=range(secs)
ticks.reverse()
for sec in ticks:
- sys.stdout.write(red(str(sec+1)+" "))
+ sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
sys.stdout.flush()
time.sleep(1)
print
return mystr+" kB"
-def getgccversion():
+def getgccversion(chost):
"""
rtype: C{str}
return: the current in-use gcc version
"""
- gcc_env_dir = os.path.join('/', 'etc', 'env.d', 'gcc')
- gcc_config_config = os.path.join(gcc_env_dir, 'config')
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."
+ "!!! other terminals also.\n"
)
- gcc_distcc_broken_error = green(
- '!!! Relying on the shell to locate gcc, this may break\n' +
- '!!! DISTCC, installing gcc-config and setting your current gcc\n' +
- '!!! profile will fix this'
- )
-
- def fallback():
-
- print >>sys.stderr, gcc_distcc_broken_error
-
- gccout = commands.getstatusoutput(gcc_ver_command)
-
- if gccout[0] != 0:
- print >>sys.stderr, gcc_not_found_error
- gccver = "[unavailable]"
+ 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 len(myoutput.split("-")) > 0:
+ return gcc_ver_prefix + myoutput.split("-")[-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:
- gccver = gcc_ver_prefix + gccout[1]
-
- return gccver
-
- if os.path.isfile(gcc_config_config):
- try:
- gccver_str = open(gcc_config_config).read().strip()
- gccver = gcc_ver_prefix + string.join(gccver_str.split('-')[4:], '-')
- except IndexError:
- gccver = fallback()
-
- else:
- import glob
- dir_l = glob.glob(os.path.join(gcc_env_dir, '*-*'))
-
- if len(dir_l) == 1:
try:
- gccver = gcc_ver_prefix + dir_l[0].split('-')[-1]
- except IndexError:
- gccver = fallback()
-
- else:
- # There was no "config" file in /etc/env.d/gcc and there was more
- # than one profile in /etc/env.d/gcc so we can't actively
- # determine what version of gcc we are using so we fall back on the
- # old way that breaks distcc
+ profilever = "!" + os.readlink(profile)
+ except (OSError):
+ pass
+ del realpath, basepath
- gccver = fallback()
-
- return gccver
-
-def getportageversion():
- try:
- import re
- profilever = os.path.normpath("///"+os.readlink(portage_const.EPREFIX+"/etc/make.profile"))
- basepath = os.path.normpath("///"+portage.settings["PORTDIR"]+"/profiles")
- if re.match(basepath,profilever):
- profilever = profilever[len(basepath)+1:]
- else:
- profilever = "!"+profilever
- del basepath
- except SystemExit, e:
- raise # Needed else can't exit
- except:
- profilever="unavailable"
libcver=[]
- libclist = portage.vardbapi(portage.root).match("virtual/libc")
- libclist += portage.vardbapi(portage.root).match("virtual/glibc")
+ 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="unavailable"
- gccver = getgccversion()
+ gccver = getgccversion(chost)
unameout=os.uname()[2]+" "+os.uname()[4]
return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
-def help():
- # Move all the help stuff out of this file.
- emergehelp.help(myaction,myopts,havecolor)
-
-if "--version" in myopts:
- print getportageversion()
- sys.exit(0)
-elif "--help" in myopts:
- help()
- sys.exit(0)
-
-if "--debug" in myopts:
- print "myaction", myaction
- print "myopts", myopts
-
-# 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"):
- if portage.secpass >= 1:
- if "--fetchonly" not in myopts and \
- "--fetch-all-uri" not in myopts:
- print "emerge: root access required."
- sys.exit(1)
- else:
- print "emerge: root access required."
- sys.exit(1)
-
-if not "--pretend" in myopts:
- emergelog("Started emerge on: "+time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
- myelogstr=""
- if myopts:
- myelogstr=string.join(myopts, " ")
- if myaction:
- myelogstr+=" "+myaction
- if myfiles:
- myelogstr+=" "+string.join(myfiles, " ")
- emergelog(" *** emerge "+myelogstr)
-
-#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
-# empty: pretend nothing is merged
-myparams=["self","recurse"]
-add=[]
-sub=[]
-if "--update" in myopts or myaction in ("system", "world"):
- add.extend(["selective","empty"])
-if "--emptytree" in myopts:
- add.extend(["empty"])
- sub.extend(["selective"])
-if "--nodeps" in myopts:
- sub.extend(["recurse"])
-if "--noreplace" in myopts:
- add.extend(["selective"])
-if "--deep" in myopts:
- add.extend(["deep"])
-if "--selective" in myopts:
- add.extend(["selective"])
-if myaction in ["world","system"]:
- add.extend(["selective"])
-elif myaction in ["depclean"]:
- add.extend(["empty"])
- sub.extend(["selective"])
-for x in add:
- if (x not in myparams) and (x not in sub):
- myparams.append(x)
-for x in sub:
- if x in myparams:
- myparams.remove(x)
+def create_depgraph_params(myopts, myaction):
+ #configure emerge engine parameters
+ #
+ # self: include _this_ package regardless of if it is merged.
+ # selective: exclude the package if it is merged
+ # recurse: go into the dependencies
+ # deep: go into the dependencies of already merged packages
+ # empty: pretend nothing is merged
+ myparams = ["recurse"]
+ add=[]
+ sub=[]
+ if "--update" in myopts or \
+ "--newuse" in myopts or \
+ "--noreplace" in myopts or \
+ myaction in ("system", "world"):
+ add.extend(["selective"])
+ if "--emptytree" in myopts:
+ add.extend(["empty"])
+ sub.extend(["selective"])
+ if "--nodeps" in myopts:
+ sub.extend(["recurse"])
+ if "--deep" in myopts:
+ add.extend(["deep"])
+ for x in add:
+ if (x not in myparams) and (x not in sub):
+ myparams.append(x)
+ for x in sub:
+ if x in myparams:
+ myparams.remove(x)
+ return myparams
# search functionality
class search:
#
# public interface
#
- def __init__(self):
+ def __init__(self, settings, portdb, vartree, spinner, searchdesc,
+ verbose):
"""Searches the available and installed packages for the supplied search key.
The list of available and installed packages is created at object instantiation.
This makes successive searches faster."""
- self.installcache = portage.db["/"]["vartree"]
+ self.settings = settings
+ self.portdb = portdb
+ self.vartree = vartree
+ self.spinner = spinner
+ self.verbose = verbose
+ self.searchdesc = searchdesc
def execute(self,searchkey):
"""Performs the search for the supplied search key"""
- global myopts
match_category = 0
self.searchkey=searchkey
self.packagematches = []
- if "--searchdesc" in myopts:
+ if self.searchdesc:
self.searchdesc=1
self.matches = {"pkg":[], "desc":[]}
else:
self.matches = {"pkg":[]}
print "Searching... ",
+ regexsearch = False
+ if self.searchkey[0] == '%':
+ regexsearch = True
+ self.searchkey = self.searchkey[1:]
if self.searchkey[0] == '@':
match_category = 1
self.searchkey = self.searchkey[1:]
- if self.searchkey=="*":
- #hack for people who aren't regular expression gurus
- self.searchkey==".*"
- if re.search("\+\+", self.searchkey):
- #hack for people who aren't regular expression gurus
- self.searchkey=re.sub("\+\+","\+\+",self.searchkey)
- self.searchre=re.compile(self.searchkey.lower(),re.I)
- for package in portage.portdb.cp_all():
- update_spinner()
+ 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[:]
masked=0
if self.searchre.search(match_string):
- if not portage.portdb.xmatch("match-visible",package):
+ if not self.portdb.xmatch("match-visible", package):
masked=1
self.matches["pkg"].append([package,masked])
elif self.searchdesc: # DESCRIPTION searching
- full_package = portage.portdb.xmatch("bestmatch-visible",package)
+ 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(portage.portdb.xmatch("match-all",package))
+ full_package = portage.best(
+ self.portdb.xmatch("match-all", package))
if not full_package:
continue
else:
masked=1
try:
- full_desc = portage.portdb.aux_get(full_package,["DESCRIPTION"])[0]
+ full_desc = self.portdb.aux_get(
+ full_package, ["DESCRIPTION"])[0]
except KeyError:
print "emerge: search: aux_get() failed, skipping"
continue
for match,masked in self.matches[mtype]:
if mtype=="pkg":
catpack=match
- full_package = portage.portdb.xmatch("bestmatch-visible",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(portage.portdb.xmatch("match-all",match))
+ full_package = portage.best(
+ self.portdb.xmatch("match-all",match))
else:
full_package = match
match = portage.pkgsplit(match)[0]
if full_package:
try:
- desc, homepage, license = portage.portdb.aux_get(full_package,["DESCRIPTION","HOMEPAGE","LICENSE"])
+ desc, homepage, license = self.portdb.aux_get(
+ full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
except KeyError:
print "emerge: search: aux_get() failed, skipping"
continue
mysum = [0,0]
mycat = match.split("/")[0]
mypkg = match.split("/")[1]
-
- mydigest = portage.db["/"]["porttree"].dbapi.finddigest(mycat+"/"+mypkg + "-" + myversion)
-
+ mycpv = match + "-" + myversion
+ myebuild = self.portdb.findname(mycpv)
+ pkgdir = os.path.dirname(myebuild)
+ import portage_manifest
+ mf = portage_manifest.Manifest(
+ pkgdir, self.settings["DISTDIR"])
+ fetchlist = self.portdb.getfetchlist(mycpv,
+ mysettings=self.settings, all=True)[1]
try:
- myfile = open(mydigest,"r")
- for line in myfile.readlines():
- mysum[0] += int(line.split(" ")[3])
- myfile.close()
+ 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 SystemExit, e:
- raise # Needed else can't exit
- except Exception, e:
- if edebug:
- print "!!! Exception:",e
- mysum[0]=" [no/bad digest]"
+ except KeyError, e:
+ mysum[0] = "Unknown (missing digest for %s)" % str(e)
- if "--quiet" not in myopts:
+ if self.verbose:
print " ", darkgreen("Latest version available:"),myversion
print " ", self.getInstallationStatus(mycat+'/'+mypkg)
print " ", darkgreen("Size of files:"),mysum[0]
# private interface
#
def getInstallationStatus(self,package):
- installed_package = self.installcache.dep_bestmatch(package)
+ installed_package = self.vartree.dep_bestmatch(package)
result = ""
version = self.getVersion(installed_package,search.VERSION_RELEASE)
if len(version) > 0:
#build our package digraph
-def getlist(mode):
+def getlist(settings, mode):
if mode=="system":
- mylines=portage.settings.packages
+ mylines = settings.packages
elif mode=="world":
try:
- myfile = open(os.path.join(portage.root, portage.WORLD_FILE), "r")
- mylines=myfile.readlines()
+ file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
+ myfile = open(file_path, "r")
+ mylines = myfile.readlines()
myfile.close()
- except OSError:
- print "!!! Couldn't open "+pfile+"; exiting."
- sys.exit(1)
- except IOError:
- #world file doesn't exist
- mylines=[]
+ 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=string.join(string.split(x))
# Remove everything that is package.provided from our list
for atom in mynewlines[:]:
- for expanded_atom in portage.flatten(portage.dep_virtual([atom], portage.settings)):
+ for expanded_atom in portage.flatten(
+ portage.dep_virtual([atom], settings)):
mykey = portage.dep_getkey(expanded_atom)
- if portage.settings.pprovideddict.has_key(mykey) and \
- portage.match_from_list(expanded_atom, portage.settings.pprovideddict[mykey]):
+ if mykey in settings.pprovideddict and \
+ portage.match_from_list(
+ expanded_atom, settings.pprovideddict[mykey]):
mynewlines.remove(atom)
break
return mynewlines
+def clean_world(vardb, cpv):
+ """Remove a package from the world file when unmerged."""
+ world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
+ worldlist = portage_util.grabfile(world_filename)
+ mykey = portage.cpv_getkey(cpv)
+ newworldlist = []
+ for x in worldlist:
+ if portage.dep_getkey(x) == mykey:
+ matches = vardb.match(x, use_cache=0)
+ if not matches:
+ #zap our world entry
+ pass
+ elif len(matches) == 1 and matches[0] == cpv:
+ #zap our world entry
+ pass
+ else:
+ #others are around; keep it.
+ newworldlist.append(x)
+ else:
+ #this doesn't match the package we're unmerging; keep it.
+ newworldlist.append(x)
+
+ portage_util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
+ gid=portage.portage_gid, mode=02770)
+ portage_util.write_atomic(world_filename, "\n".join(newworldlist))
+
def genericdict(mylist):
mynewdict={}
for x in mylist:
mynewdict[portage.dep_getkey(x)]=x
return mynewdict
-olddbapi=None
class depgraph:
- def __init__(self,myaction,myopts):
- global olddbapi
- self.pkgsettings = portage.config(clone=portage.settings)
- if not self.pkgsettings["ARCH"]:
- portage.writemsg(red("\a!!! ARCH is not set... Are you missing the /etc/make.profile symlink?\n"))
- portage.writemsg(red("\a!!! Is the symlink correct? Is your portage tree complete?\n\n"))
- sys.exit(9)
- self.applied_useflags = {}
+ pkg_tree_map = {
+ "ebuild":"porttree",
+ "binary":"bintree",
+ "installed":"vartree"}
+
+ def __init__(self, settings, trees, myopts, myparams, spinner):
+ self.settings = settings
+ self.target_root = settings["ROOT"]
+ self.trees = trees
+ self.myopts = myopts
+ self.myparams = myparams
+ self.edebug = 0
+ if settings.get("PORTAGE_DEBUG", "") == "1":
+ self.edebug = 1
+ self.spinner = spinner
+ self.pkgsettings = {}
+ self.pkgsettings[self.target_root] = portage.config(clone=settings)
+ if self.target_root != "/":
+ self.pkgsettings["/"] = \
+ portage.config(clone=trees["/"]["vartree"].settings)
+ self.useFlags = {}
+ self.useFlags[self.target_root] = {}
+ if self.target_root != "/":
+ self.useFlags["/"] = {}
self.missingbins=[]
- self.myaction=myaction
self.digraph=portage.digraph()
self.orderedkeys=[]
self.outdatedpackages=[]
self.mydbapi={}
- self.mydbapi["/"] = portage.fakedbapi()
- if "empty" not in myparams or portage.root != "/":
- for pkg in portage.db["/"]["vartree"].getallcpv():
- self.mydbapi["/"].cpv_inject(pkg)
- if portage.root != "/":
- self.mydbapi[portage.root] = portage.fakedbapi()
- if "empty" not in myparams:
- for pkg in portage.db[portage.root]["vartree"].getallcpv():
- self.mydbapi[portage.root].cpv_inject(pkg)
-
- if "--usepkg" in myopts:
- portage.db["/"]["bintree"].populate(("--getbinpkg" in myopts), ("--getbinpkgonly" in myopts))
-
- def create(self,mybigkey,myparent=None,addme=1,myuse=None):
- """creates the actual digraph of packages to merge. return 1 on success, 0 on failure
- mybigkey = specification of package to merge; myparent = parent package (one depending on me);
- addme = should I be added to the tree? (for the --onlydeps mode)"""
+ self.mydbapi["/"] = portage.fakedbapi(settings=settings)
+ vardb = self.trees["/"]["vartree"].dbapi
+ fakedb = self.mydbapi["/"]
+ if "empty" not in self.myparams or self.target_root != "/":
+ for pkg in vardb.cpv_all():
+ myslot = vardb.aux_get(pkg, ["SLOT"])[0]
+ fakedb.cpv_inject(pkg, myslot=myslot)
+ if self.target_root != "/":
+ self.mydbapi[self.target_root] = \
+ portage.fakedbapi(settings=settings)
+ vardb = self.trees[self.target_root]["vartree"].dbapi
+ fakedb = self.mydbapi[self.target_root]
+ if "empty" not in self.myparams:
+ for pkg in vardb.cpv_all():
+ myslot = vardb.aux_get(pkg, ["SLOT"])[0]
+ fakedb.cpv_inject(pkg, myslot=myslot)
+ if "--usepkg" in self.myopts:
+ trees["/"]["bintree"].populate(
+ "--getbinpkg" in self.myopts, "--getbinpkgonly" in self.myopts)
+ if self.target_root != "/":
+ trees[self.target_root]["bintree"].populate(
+ "--getbinpkg" in self.myopts,
+ "--getbinpkgonly" in self.myopts)
+ self.args_keys = []
+ self.global_updates = {}
+
+ def create(self, mybigkey, myparent=None, addme=1, myuse=None,
+ priority=digraph.HARD, 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
+ #IUSE-aware emerge -> USE DEP aware depgraph
#"no downgrade" emerge
- #print "mybigkey:",mybigkey
-
- jbigkey=string.join(mybigkey)
- if self.digraph.hasnode(jbigkey+" merge") or self.digraph.hasnode(jbigkey+" nomerge"):
- #this conditional is needed to prevent infinite recursion on already-processed deps
+ """
+
+ jbigkey = " ".join(mybigkey) + " merge"
+ if self.digraph.hasnode(jbigkey):
+ if addme and jbigkey != myparent:
+ # Refuse to make a node depend on itself so that the we don't
+ # don't create a bogus circular dependency in self.altlist().
+ if rev_dep and myparent:
+ self.digraph.addnode(myparent, jbigkey, priority=priority)
+ else:
+ self.digraph.addnode(jbigkey, myparent, priority=priority)
return 1
-
- update_spinner()
-
+ jbigkey = " ".join(mybigkey) + " nomerge"
+ if self.digraph.hasnode(jbigkey):
+ """XXX: It's possible that this package has been explicitly
+ requested as a command line argument. This can be solved by
+ checking all args prior to marking packages as nomerge"""
+ if rev_dep and myparent:
+ self.digraph.addnode(myparent, jbigkey, priority=priority)
+ else:
+ self.digraph.addnode(jbigkey, myparent, priority=priority)
+ return 1
+
+ self.spinner.update()
mytype,myroot,mykey=mybigkey
+ if mytype == "blocks":
+ if addme and "--buildpkgonly" not in self.myopts and myparent:
+ mybigkey[1] = myparent.split()[1]
+ self.digraph.addnode(" ".join(mybigkey), myparent,
+ priority=priority)
+ return 1
+ if not arg:
+ arg = portage.best_match_to_list(mykey, self.args_keys)
# select the correct /var database that we'll be checking against
- vardbapi=portage.db[myroot]["vartree"].dbapi
+ 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.
- if mytype=="blocks":
- # we've encountered a "blocks" node. We will totally ignore this
- # node and not add it to our digraph if it doesn't apply to us.
- if addme and "--buildpkgonly" not in myopts and myparent and (self.mydbapi[myroot].match(mykey) or vardbapi.match(mykey)):
- mybigkey.append(myparent.split()[2])
- self.digraph.addnode(string.join(mybigkey),myparent)
- return 1
- if myuse == None:
- self.pkgsettings.setcpv(mykey)
- myuse = self.pkgsettings["USE"].split()
- self.applied_useflags[mykey] = myuse
+ mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
+
+ if myuse is None:
+ self.pkgsettings[myroot].setcpv(mykey)
+ myuse = self.pkgsettings[myroot]["USE"].split()
+ self.useFlags[myroot][mykey] = myuse
merging=1
- if addme:
+ if mytype == "installed":
+ merging = 0
+ if addme and mytype != "installed":
# this is where we add the node to the list of packages to merge
- if not myparent:
- # command-line specified or part of a world list...
- if ("self" not in myparams) or (("selective" in myparams) and vardbapi.cpv_exists(mykey)):
- # the package is on the system, so don't merge it.
+ if "selective" in self.myparams or not arg:
+ if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
merging=0
- elif ("selective" in myparams) and vardbapi.cpv_exists(mykey):
- merging=0
- if (merging==0 and "--newuse" in myopts and vardbapi.cpv_exists(mykey)):
+ """ If we aren't merging, perform the --newuse check.
+ If the package has new iuse flags or different use flags then if
+ --newuse is specified, we need to merge the package. """
+ if merging==0 and "--newuse" in self.myopts and \
+ vardbapi.cpv_exists(mykey):
+ pkgsettings.setcpv(mykey)
+ forced_flags = set()
+ forced_flags.update(pkgsettings.useforce)
+ forced_flags.update(pkgsettings.puseforce)
+ forced_flags.update(pkgsettings.usemask)
+ forced_flags.update(pkgsettings.pusemask)
old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
- if mytype == "binary":
- iuses = portage.db["/"]["bintree"].dbapi.aux_get(mykey, ["IUSE"])[0].split()
- else:
- iuses = portage.db["/"]["porttree"].dbapi.aux_get(mykey, ["IUSE"])[0].split()
- for x in iuses:
- if (old_use.count(x) and not myuse.count(x)) or (not old_use.count(x) and myuse.count(x)):
- merging=1
- break
- else:
- #onlydeps mode; don't merge
- merging=2
- if merging==1:
+ iuses = set(mydbapi.aux_get(mykey, ["IUSE"])[0].split())
+ old_iuse = set(vardbapi.aux_get(mykey, ["IUSE"])[0].split())
+ if iuses.symmetric_difference(
+ old_iuse).difference(forced_flags):
+ merging = 1
+ elif old_iuse.intersection(old_use) != \
+ iuses.intersection(myuse):
+ merging=1
+
+ if addme and merging == 1:
mybigkey.append("merge")
else:
mybigkey.append("nomerge")
- # whatever the case, we need to add the node to our digraph so
- # that children can depend upon it.
- self.digraph.addnode(string.join(mybigkey),myparent)
- if ("deep" not in myparams) and (not merging):
+ if merging == 0 and vardbapi.cpv_exists(mykey):
+ myuse = vardbapi.aux_get(mykey, ["USE"])[0].split()
+ self.useFlags[myroot][mykey] = myuse
+
+ """ At this point, we have either hit a blocker and returned, found the package in the
+ depgraph already and returned, or we are here. Whether we are merging or not; we must
+ add the package to the depgraph; so we do that here. """
+ if rev_dep and myparent:
+ self.digraph.addnode(myparent, " ".join(mybigkey),
+ priority=priority)
+ else:
+ self.digraph.addnode(" ".join(mybigkey), myparent,
+ priority=priority)
+
+ """ 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 myparams:
+ 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={}
- if mytype=="binary":
- mypkgparts=portage.catpkgsplit(mykey)
- tbz2name = string.split(mykey, "/")[1]+".tbz2"
- if tbz2name in portage.db[portage.root]["bintree"].invalids:
- sys.stderr.write("\nINVALID PACKAGE (is required to continue): "+str(mykey)+"\n")
- sys.exit(1)
- if portage.db[portage.root]["bintree"].isremote(mykey):
- edepend = portage.db[portage.root]["bintree"].remotepkgs[tbz2name]
- edepend["DEPEND"] =""
- edepend["RDEPEND"]=string.join(string.split(edepend["RDEPEND"])," ")
- edepend["PDEPEND"]=string.join(string.split(edepend["PDEPEND"])," ")
- edepend["SLOT"] =string.strip(edepend["SLOT"])
- #portage.db[portage.root]["bintree"].gettbz2(mykey)
- else: # It's local.
- mytbz2=xpak.tbz2(portage.db[portage.root]["bintree"].getname(mykey))
- edepend["DEPEND"] =""
- edepend["RDEPEND"]=string.join(mytbz2.getelements("RDEPEND")," ")
- edepend["PDEPEND"]=string.join(mytbz2.getelements("PDEPEND")," ")
- edepend["SLOT"] =mytbz2.getfile("SLOT",mypkgparts[2])
- elif mytype=="ebuild":
- try:
- mymeta = ["DEPEND","RDEPEND","PDEPEND"]
- myfoo = portage.portdb.aux_get(mykey, mymeta)
- for index in range(0,len(mymeta)):
- edepend[mymeta[index]] = myfoo[index]
- if "--buildpkgonly" in myopts:
- edepend["RDEPEND"] = ""
- edepend["PDEPEND"] = ""
- except (KeyError,IOError):
- print "emerge: create(): aux_get() error on",mykey+"; aborting..."
- sys.exit(1)
- mydep={}
+ depkeys = ["DEPEND","RDEPEND","PDEPEND"]
+ depvalues = mydbapi.aux_get(mykey, depkeys)
+ for i in xrange(len(depkeys)):
+ edepend[depkeys[i]] = depvalues[i]
+
+ if mytype == "ebuild":
+ if "--buildpkgonly" in self.myopts:
+ edepend["RDEPEND"] = ""
+ edepend["PDEPEND"] = ""
+ if self.myopts.get("--with-bdeps", "n") == "n" and \
+ (mytype == "binary" or mybigkey[3] == "nomerge"):
+ edepend["DEPEND"] = ""
+
+ """ We have retrieve the dependency information, now we need to recursively
+ process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
+
mp=string.join(mybigkey)
- if myroot=="/":
- mydep["/"]=edepend["DEPEND"]+" "+edepend["RDEPEND"]
- if not self.select_dep("/",mydep["/"],myparent=mp,myuse=myuse):
- return 0
- else:
- mydep["/"]=edepend["DEPEND"]
- mydep[myroot]=edepend["RDEPEND"]
- if not self.select_dep("/",mydep["/"],myparent=mp,myuse=myuse):
- return 0
- if not self.select_dep(myroot,mydep[myroot],myparent=mp,myuse=myuse):
+ try:
+ if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
+ myuse=myuse, 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"],myuse=myuse):
+ """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=digraph.MEDIUM, 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=digraph.SOFT, rev_deps=True, parent_arg=arg):
+ return 0
+ except ValueError, e:
+ pkgs = e.args[0]
+ portage.writemsg("\n\n!!! An atom in the dependencies " + \
+ "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
+ for cpv in pkgs:
+ portage.writemsg(" %s\n" % cpv, noiselevel=-1)
+ portage.writemsg("\n", noiselevel=-1)
+ if mytype == "binary":
+ portage.writemsg(
+ "!!! This binary package cannot be installed: '%s'\n" % \
+ mykey, noiselevel=-1)
+ elif mytype == "ebuild":
+ myebuild, mylocation = portdb.findname2(mykey)
+ portage.writemsg("!!! This ebuild cannot be installed: " + \
+ "'%s'\n" % myebuild, noiselevel=-1)
+ portage.writemsg("!!! Please notify the package maintainer " + \
+ "that atoms must be fully-qualified.\n", noiselevel=-1)
+ return 0
return 1
def select_files(self,myfiles):
"given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
myfavorites=[]
+ myroot = self.target_root
+ portdb = self.trees[myroot]["porttree"].dbapi
+ bindb = self.trees[myroot]["bintree"].dbapi
+ pkgsettings = self.pkgsettings[myroot]
+ arg_atoms = []
for x in myfiles:
ext = os.path.splitext(x)[1]
if ext==".tbz2":
if not os.path.exists(x):
- if os.path.exists(self.pkgsettings["PKGDIR"]+"/All/"+x):
- x=self.pkgsettings["PKGDIR"]+"/All/"+x
- elif os.path.exists(self.pkgsettings["PKGDIR"]+"/"+x):
- x=self.pkgsettings["PKGDIR"]+"/"+x
+ if os.path.exists(
+ os.path.join(pkgsettings["PKGDIR"], "All", x)):
+ x = os.path.join(pkgsettings["PKGDIR"], "All", x)
+ elif os.path.exists(
+ os.path.join(pkgsettings["PKGDIR"], x)):
+ x = os.path.join(pkgsettings["PKGDIR"], x)
else:
print "\n\n!!! Binary package '"+str(x)+"' does not exist."
print "!!! Please ensure the tbz2 exists as specified.\n"
sys.exit(1)
mytbz2=xpak.tbz2(x)
mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
- if os.path.realpath(portage.db["/"]["bintree"].getname(mykey)) != os.path.realpath(x):
- print red("\n*** You need to adjust PKGDIR to emerge this package.\n")
+ if os.path.realpath(x) != \
+ os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
+ print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
sys.exit(1)
- if not self.create(["binary",portage.root,mykey],None,"--onlydeps" not in myopts):
+ if not self.create(["binary", myroot, mykey],
+ None, "--onlydeps" not in self.myopts):
return (0,myfavorites)
- elif not "--oneshot" in myopts:
+ elif not "--oneshot" in self.myopts:
myfavorites.append(mykey)
elif ext==".ebuild":
x = os.path.realpath(x)
mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
- ebuild_path = portage.db["/"]["porttree"].dbapi.findname(mykey)
+ ebuild_path = portdb.findname(mykey)
if ebuild_path:
if os.path.realpath(ebuild_path) != x:
- print red("\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
+ print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
sys.exit(1)
- if mykey not in portage.db["/"]["porttree"].dbapi.xmatch("match-visible", portage.dep_getkey(mykey)):
- print red("\n*** You are emerging a masked package. It is MUCH better to use")
- print red("*** /etc/portage/package.* to accomplish this. See portage(5) man")
- print red("*** page for details.")
- countdown(EMERGE_WARNING_DELAY, "Continuing...")
+ 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:
- print red("\n*** %s is not in a valid PORTDIR heirarchy or does not exist" % x)
- sys.exit(1)
- if not self.create(["ebuild",portage.root,mykey],None,"--onlydeps" not in myopts):
+ raise portage_exception.PackageNotFound(
+ "%s is not in a valid portage tree hierarchy or does not exist" % x)
+ if not self.create(["ebuild", myroot, mykey],
+ None, "--onlydeps" not in self.myopts):
return (0,myfavorites)
- elif not "--oneshot" in myopts:
+ elif not "--oneshot" in self.myopts:
myfavorites.append(mykey)
else:
if not is_valid_package_atom(x):
- portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x)
+ portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
+ noiselevel=-1)
portage.writemsg("!!! Please check ebuild(5) for full details.\n")
portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
return (0,[])
try:
- mykey=portage.dep_expand(x,mydb=portage.portdb)
+ mykey = None
+ if "--usepkg" in self.myopts:
+ mykey = portage.dep_expand(x, mydb=bindb,
+ settings=pkgsettings)
+ if (mykey and not mykey.startswith("null/")) or \
+ "--usepkgonly" in self.myopts:
+ arg_atoms.append((x, mykey))
+ continue
+
+ mykey = portage.dep_expand(x,
+ mydb=portdb, settings=pkgsettings)
+ arg_atoms.append((x, mykey))
except ValueError, errpkgs:
print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
print "!!! one of the following fully-qualified ebuild names instead:\n"
print
sys.exit(1)
- # select needs to return 0 on dep_check failure
-
- sys.stdout.flush()
- sys.stderr.flush()
-
+ if "--update" in self.myopts:
+ """Make sure all installed slots are updated when possible. Do this
+ with --emptytree also, to ensure that all slots are remerged."""
+ vardb = self.trees[self.target_root]["vartree"].dbapi
+ greedy_atoms = []
+ for myarg, myatom in arg_atoms:
+ greedy_atoms.append((myarg, myatom))
+ myslots = set()
+ for cpv in vardb.match(myatom):
+ myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
+ if len(myslots) > 1:
+ for myslot in myslots:
+ myslot_atom = "%s:%s" % \
+ (portage.dep_getkey(myatom), myslot)
+ available = False
+ if "--usepkgonly" not in self.myopts and \
+ self.trees[self.target_root][
+ "porttree"].dbapi.match(myslot_atom):
+ available = True
+ elif "--usepkg" in self.myopts and \
+ self.trees[self.target_root][
+ "bintree"].dbapi.match(myslot_atom):
+ available = True
+ if available:
+ greedy_atoms.append((myarg, myslot_atom))
+ arg_atoms = greedy_atoms
+
+ """ These are used inside self.create() in order to ensure packages
+ that happen to match arguments are not incorrectly marked as nomerge."""
+ self.args_keys = [x[1] for x in arg_atoms]
+ for myarg, myatom in arg_atoms:
try:
- self.mysd = self.select_dep(portage.root,mykey,arg=x)
+ 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))
+ 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))
+ portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
sys.exit(1)
except SystemExit, e:
raise # Needed else can't exit
except Exception, e:
- if "--debug" in myopts:
- raise
- print "\n\n!!! Problem in",mykey,"dependencies."
- print "!!!",str(e),e.__module__
- sys.exit(1)
+ print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
+ print >> sys.stderr, "!!!", str(e), e.__module__
+ raise
if not self.mysd:
return (0,myfavorites)
- elif not "--oneshot" in myopts:
- myfavorites.append(portage.dep_getkey(mykey))
+ elif not "--oneshot" in self.myopts:
+ mykey = portage.dep_getkey(myatom)
+ if mykey not in myfavorites:
+ myfavorites.append(mykey)
missing=0
- if "--usepkgonly" in myopts:
- for x in self.digraph.dict.keys():
- xs=string.split(x," ")
- if (xs[0] != "binary") and (xs[3]=="merge"):
+ if "--usepkgonly" in self.myopts:
+ for x in self.digraph.all_nodes():
+ xs = x.split()
+ if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
if missing == 0:
print
missing += 1
print "Missing binary for:",xs[2]
+ self.validate_blockers()
+
# We're true here unless we are missing binaries.
return (not missing,myfavorites)
def is_newer_ver_installed(self,myroot,pkg,pkgver):
"if there is a version of pkg installed newer than pkgver, return it"
- vardbapi=portage.db[myroot]["vartree"].dbapi
+ vardbapi = self.trees[myroot]["vartree"].dbapi
- matches=portage.db[myroot]["vartree"].dbapi.match(pkg)
+ matches = self.trees[myroot]["vartree"].dbapi.match(pkg)
if matches:
- myslot=portage.db["/"]["porttree"].getslot(pkgver)
+ myslot = self.trees[myroot]["porttree"].getslot(pkgver)
for match in matches:
if portage.pkgcmp(portage.catpkgsplit(pkgver)[1:], portage.catpkgsplit(match)[1:]) < 0:
- curslot=portage.db[myroot]["vartree"].getslot(match)
+ curslot = self.trees[myroot]["vartree"].getslot(match)
if curslot == myslot:
return match
- def select_dep(self,myroot,depstring,myparent=None,arg=None,myuse=None,raise_on_missing=False):
- "given a dependency string, create the appropriate depgraph and return 1 on success and 0 on failure"
- if "--debug" in myopts:
+ def select_dep(self, myroot, depstring, myparent=None, arg=None,
+ myuse=None, raise_on_missing=False, priority=digraph.HARD, rev_deps=False,
+ parent_arg=None):
+ """ Given a depstring, create the depgraph such that all dependencies are satisfied.
+ myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
+ myparent = the node whose depstring is being passed in
+ arg = package was specified on the command line, merge even if it's already installed
+ myuse = USE flags at present
+ raise_on_missing = Given that the depgraph is not proper, raise an exception if true
+ else continue trying.
+ return 1 on success, 0 for failure
+ """
+
+ portdb = self.trees[myroot]["porttree"].dbapi
+ bindb = self.trees[myroot]["bintree"].dbapi
+ vardb = self.trees[myroot]["vartree"].dbapi
+ pkgsettings = self.pkgsettings[myroot]
+
+ if "--debug" in self.myopts:
print
print "Parent: ",myparent
print "Depstring:",depstring
- if not arg:
- #processing dependencies
- mycheck=portage.dep_check(depstring,self.mydbapi[myroot],self.pkgsettings,myuse=myuse,use_binaries=("--usepkgonly" in myopts),myroot=myroot)
-
- if not mycheck[0]:
- mymerge=[]
- else:
- mymerge=mycheck[1]
-
- else:
- #we're processing a command-line argument; unconditionally merge it even if it's already merged
- mymerge=[depstring]
+ if rev_deps:
+ print "Reverse:", rev_deps
+ print "Priority:", priority
+
+ #processing dependencies
+ """ Call portage.dep_check to evaluate the use? conditionals and make sure all
+ dependencies are satisfiable. """
+ mycheck = portage.dep_check(depstring, self.mydbapi[myroot],
+ pkgsettings, myuse=myuse,
+ use_binaries=("--usepkgonly" in self.myopts),
+ myroot=myroot, trees=self.trees, return_all_deps=True)
+
+ if not mycheck[0]:
+ sys.stderr.write("\n\n%s\n\n" % mycheck[1])
+ sys.stderr.write("%s\n\n" % depstring)
+ return 0
+ mymerge = mycheck[1]
- # dep_check has been run so we can now add our parent to our
- # build state to update virtuals and other settings. This
- # happens after the package is added to the tree so that a
- # package can depend on a virtual which it satisfies.
if myparent:
- myp = myparent.split()
- if myp[3]=="merge":
- self.mydbapi[myroot].cpv_inject(myp[2])
- if myp[0]=="binary":
- self.pkgsettings.setinst(myp[2],portage.db["/"]["bintree"].dbapi)
- else:
- self.pkgsettings.setinst(myp[2],portage.db[myroot]["porttree"].dbapi)
-
- if not mymerge:
- return 1
-
- if "--debug" in myopts:
+ # In order to get past circular dependencies (in
+ # `emerge -e world`, for example), the parent must be allowed
+ # to satisfy dependencies of it's children.
+
+ # 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
+ # or an old-style virtual that it satisfies (unfortunately, this
+ # only works for one level of deps, so it won't work for new-style
+ # virtuals since they introduce an additional level of dependency
+ # indirection).
+
+ p_type, p_root, p_key, p_status = myparent.split()
+ if p_status == "merge":
+ """ This fakedbapi data is used in dep_check calls to determine
+ satisfied deps via dep_wordreduce"""
+ myslot = self.trees[p_root][
+ self.pkg_tree_map[p_type]].dbapi.aux_get(
+ p_key, ["SLOT"])[0]
+ self.mydbapi[p_root].cpv_inject(p_key, myslot=myslot)
+
+ # Update old-style virtuals if this package provides any.
+ # These are needed for dep_virtual calls inside dep_check.
+ self.pkgsettings[p_root].setinst(p_key,
+ self.trees[p_root][self.pkg_tree_map[p_type]].dbapi)
+
+ if "--debug" in self.myopts:
print "Candidates:",mymerge
for x in mymerge:
- myk=None
- binpkguseflags=None
+ selected_pkg = None
if x[0]=="!":
# if this package is myself, don't append it to block list.
- if "--debug" in myopts:
+ if "--debug" in self.myopts:
print "Myparent",myparent
if (myparent):
- if myparent.split()[2] in portage.portdb.xmatch("match-all", x[1:]):
+ if myparent.split()[2] in \
+ portdb.xmatch("match-all", x[1:]):
# myself, so exit.
continue
# adding block
- myk=["blocks",myroot,x[1:]]
+ selected_pkg = ["blocks", myroot, x[1:], None]
else:
#We are not processing a blocker but a normal dependency
- myeb=None
- myeb_matches = portage.portdb.xmatch("match-visible",x)
- if ("--usepkgonly" not in myopts):
- myeb=portage.best(myeb_matches)
+ if myparent:
+ """In some cases, dep_check will return deps that shouldn't
+ be proccessed any further, so they are identified and
+ discarded here."""
+ if "empty" not in self.myparams and \
+ "deep" not in self.myparams and \
+ not ("--update" in self.myopts and parent_arg) and \
+ vardb.match(x):
+ continue
+
+ pkg_key = portage.dep_getkey(x)
+ if pkg_key in pkgsettings.pprovideddict and \
+ portage.match_from_list(
+ x, pkgsettings.pprovideddict[pkg_key]):
+ continue
+
+ # List of acceptable packages, ordered by type preference.
+ matched_packages = []
+ myeb_matches = portdb.xmatch("match-visible", x)
+ myeb = None
+ if "--usepkgonly" not in self.myopts:
+ myeb = portage.best(myeb_matches)
myeb_pkg=None
- if ("--usepkg" in myopts):
+ if "--usepkg" in self.myopts:
# The next line assumes the binarytree has been populated.
# XXX: Need to work out how we use the binary tree with roots.
- myeb_pkg_matches=portage.db["/"]["bintree"].dbapi.match(x)
- if ("--usepkgonly" not in myopts):
+ myeb_pkg_matches = bindb.match(x)
+ if "--usepkgonly" not in self.myopts:
# Remove any binary package entries that are masked in the portage tree (#55871)
- for idx in range(len(myeb_pkg_matches)-1,-1,-1):
- if myeb_pkg_matches[idx] not in myeb_matches:
- del myeb_pkg_matches[idx]
- myeb_pkg = portage.best(myeb_pkg_matches)
-
- if not myeb_pkg:
- myeb_pkg = None
- elif ("--newuse" in myopts):
- iuses=string.split(portage.db["/"]["bintree"].dbapi.aux_get(myeb_pkg, ["IUSE"])[0])
- old_use=string.split(portage.db["/"]["bintree"].dbapi.aux_get(myeb_pkg, ["USE"])[0])
- self.pkgsettings.setcpv(myeb_pkg)
- now_use=string.split(self.pkgsettings["USE"])
- for x in iuses:
- if (old_use.count(x) and not now_use.count(x)) or (not old_use.count(x) and now_use.count(x)):
- myeb_pkg = None
- break
-
- if (not myeb) and (not myeb_pkg):
+ myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
+ if pkg in myeb_matches or \
+ not portdb.cpv_exists(pkg)]
+ if myeb_pkg_matches:
+ myeb_pkg = portage.best(myeb_pkg_matches)
+
+ if myeb_pkg and "--newuse" in self.myopts:
+ iuses = set(bindb.aux_get(myeb_pkg, ["IUSE"])[0].split())
+ old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
+ pkgsettings.setcpv(myeb_pkg)
+ now_use = pkgsettings["USE"].split()
+ forced_flags = set()
+ forced_flags.update(pkgsettings.useforce)
+ forced_flags.update(pkgsettings.puseforce)
+ forced_flags.update(pkgsettings.usemask)
+ forced_flags.update(pkgsettings.pusemask)
+ cur_iuse = iuses
+ if "--usepkgonly" not in self.myopts and myeb:
+ cur_iuse = set(portdb.aux_get(myeb, ["IUSE"])[0].split())
+ if iuses.symmetric_difference(
+ cur_iuse).difference(forced_flags):
+ myeb_pkg = None
+ elif iuses.intersection(old_use) != \
+ cur_iuse.intersection(now_use):
+ myeb_pkg = None
+ if myeb_pkg:
+ binpkguseflags = \
+ self.trees[myroot]["bintree"].dbapi.aux_get(
+ myeb_pkg, ["USE"])[0].split()
+ matched_packages.append(
+ ["binary", myroot, myeb_pkg, binpkguseflags])
+
+ if "--usepkgonly" not in self.myopts and myeb_matches:
+ matched_packages.append(
+ ["ebuild", myroot, myeb, None])
+
+ if not matched_packages:
+ """Fall back to the installed package database. This is a
+ last resort because the metadata tends to diverge from that
+ of the ebuild in the tree."""
+ myeb_inst_matches = vardb.match(x)
+ if "--usepkgonly" not in self.myopts:
+ """ TODO: Improve masking check for installed and
+ binary packages. bug #149816"""
+ myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
+ if not portdb.cpv_exists(pkg)]
+ myeb_inst = None
+ if myeb_inst_matches:
+ myeb_inst = portage.best(myeb_inst_matches)
+ if myeb_inst:
+ binpkguseflags = vardb.aux_get(
+ myeb_inst, ["USE"])[0].split()
+ matched_packages.append(
+ ["installed", myroot, myeb_inst, binpkguseflags])
+ """Now make sure that *DEPEND atoms are up to date.
+ This is done on the fly for single packages only when
+ necessary, since it can be time consuming to run this
+ on all installed packages."""
+ from portage_update import grab_updates, \
+ parse_updates, update_dbentries
+ if myroot not in self.global_updates:
+ updpath = os.path.join(
+ pkgsettings["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)
+ del updpath, rawupdates
+ self.global_updates[myroot] = upd_commands
+ upd_commands = self.global_updates[myroot]
+ aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
+ aux_vals = vardb.aux_get(myeb_inst, aux_keys)
+ aux_dict = dict(zip(aux_keys, aux_vals))
+ updates = update_dbentries(upd_commands, aux_dict)
+ if updates:
+ vardb.aux_update(myeb_inst, updates)
+ del binpkguseflags, myeb_inst, upd_commands, \
+ aux_keys, aux_vals, aux_dict, updates
+
+ if not matched_packages:
if raise_on_missing:
raise ValueError
if not arg:
xinfo='"'+arg+'"'
if myparent:
xfrom = '(dependency required by '+green('"'+myparent.split()[2]+'"')+red(' ['+myparent.split()[0]+"]")+')'
- alleb=portage.portdb.xmatch("match-all",x)
+ alleb = portdb.xmatch("match-all", x)
if alleb:
- if "--usepkgonly" not in myopts:
+ if "--usepkgonly" not in self.myopts:
print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
print "!!! One of the following masked packages is required to complete your request:"
oldcomment = ""
for p in alleb:
- mreasons = portage.getmaskingstatus(p)
+ mreasons = portage.getmaskingstatus(p,
+ settings=pkgsettings, portdb=portdb)
print "- "+p+" (masked by: "+string.join(mreasons, ", ")+")"
- comment = portage.getmaskingreason(p)
+ comment = portage.getmaskingreason(p,
+ settings=pkgsettings, portdb=portdb)
if comment and comment != oldcomment:
print comment
oldcomment = comment
print
return 0
- if "--debug" in myopts:
- print "ebuild:",myeb
- print "binpkg:",myeb_pkg
+ if "--debug" in self.myopts:
+ for pkg in matched_packages:
+ print (pkg[0] + ":").rjust(10), pkg[2]
- if myeb and myeb_pkg:
- myeb_s = portage.catpkgsplit(myeb)
- myeb_s = [myeb_s[0]+"/"+myeb_s[1], myeb_s[2], myeb_s[3]]
- myeb_pkg_s = portage.catpkgsplit(myeb_pkg)
- myeb_pkg_s = [myeb_pkg_s[0]+"/"+myeb_pkg_s[1], myeb_pkg_s[2], myeb_pkg_s[3]]
+ if len(matched_packages) > 1:
+ bestmatch = portage.best(
+ [pkg[2] for pkg in matched_packages])
+ matched_packages = [pkg for pkg in matched_packages \
+ if pkg[2] == bestmatch]
- if portage.pkgcmp(myeb_s, myeb_pkg_s) == 0: # pkg is same version as ebuild
- myeb = None
- else:
- myeb_pkg = None
+ # ordered by type preference ("ebuild" type is the last resort)
+ selected_pkg = matched_packages[0]
- if myeb:
- myk=["ebuild",myroot,myeb]
- elif myeb_pkg:
- binpkguseflags=portage.db[portage.root]["bintree"].get_use(myeb_pkg)
- myk=["binary",myroot,myeb_pkg]
- else:
- sys.stderr.write("!!! Confused... Don't know what's being used for dependency info. :(\n")
- sys.exit(1)
-
- #if "--usepkg" in myopts:
- # #If we want to use packages, see if we have a pre-built one...
- # mypk=portage.db["/"]["bintree"].dbapi.match(x)
- # if myeb in mypk:
- # #Use it only if it's exactly the version we want.
- # myk=["binary",myroot,myeb]
- # else:
- # myk=["ebuild",myroot,myeb]
- #else:
- # myk=["ebuild",myroot,myeb]
if myparent:
#we are a dependency, so we want to be unconditionally added
- if not self.create(myk,myparent,myuse=binpkguseflags):
+ mypriority = priority
+ if mypriority > digraph.SOFT and vardb.match(x):
+ mypriority = digraph.SOFT
+ if not self.create(selected_pkg[0:3], myparent,
+ myuse=selected_pkg[-1], priority=mypriority,
+ rev_dep=rev_deps, arg=arg):
return 0
else:
#if mysource is not set, then we are a command-line dependency and should not be added
#if --onlydeps is specified.
- if not self.create(myk,myparent,"--onlydeps" not in myopts,myuse=binpkguseflags):
+ if not self.create(selected_pkg[0:3], myparent,
+ addme=("--onlydeps" not in self.myopts),
+ myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
return 0
- if "--debug" in myopts:
+ if "--debug" in self.myopts:
print "Exiting...",myparent
return 1
-
- def altlist(self):
+ def validate_blockers(self):
+ """Remove any blockers from the digraph that do not match any of the
+ packages within the graph. Blockers are only matched against the
+ final state of the graph. Thus, it's possible that mutually blocking
+ packages will be installed simultaneously a some point(s) during the
+ transition from the initial to the final state."""
+
+ """ It's possible that some of the nodes haven't been added to the
+ fakedb yet, so make sure they're all accounted for."""
+ for node in self.digraph.all_nodes():
+ node_split = node.split()
+ mytype, myroot, mykey = node_split[0:3]
+ if mytype in self.pkg_tree_map:
+ mydb = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
+ myslot = mydb.aux_get(mykey, ["SLOT"])[0]
+ self.mydbapi[myroot].cpv_inject(mykey, myslot=myslot)
+
+ all_blockers = [node for node in self.digraph.all_nodes()
+ if node.split()[0] == "blocks"]
+ for blocker in all_blockers:
+ mytype, myroot, mydep = blocker.split()
+ """Prior to being added to the digraph, any blockers against
+ old-style virtuals have been expanded to real packages via
+ dep_virtual calls inside dep_check."""
+ if not self.mydbapi[myroot].match(mydep):
+ self.digraph.remove(blocker)
+
+ def altlist(self, reversed=False):
mygraph=self.digraph.copy()
- dolist=["/"]
retlist=[]
- for x in portage.db.keys():
- portage.db[x]["merge"]=[]
- if x not in dolist:
- dolist.append(x)
- while (not mygraph.empty()):
- mycurkey=mygraph.firstzero()
- if not mycurkey:
+ if reversed:
+ get_nodes = mygraph.root_nodes
+ else:
+ get_nodes = mygraph.leaf_nodes
+ while not mygraph.empty():
+ for ignore_priority in \
+ (digraph.NONE, digraph.SOFT, digraph.MEDIUM):
+ nodes = get_nodes(ignore_priority=ignore_priority)
+ if nodes:
+ break
+ selected_nodes = None
+ if nodes:
+ if ignore_priority <= digraph.SOFT:
+ selected_nodes = [nodes[0]]
+ else:
+ """Recursively gather a group of nodes that RDEPEND on
+ eachother. This ensures that they are merged as a group
+ and get their RDEPENDs satisfied as soon as possible."""
+ def gather_deps(mergeable_nodes, selected_nodes, node):
+ if node in selected_nodes:
+ return True
+ if node not in mergeable_nodes:
+ return False
+ selected_nodes.add(node)
+ for child in mygraph.child_nodes(node,
+ ignore_priority=digraph.SOFT):
+ if not gather_deps(
+ mergeable_nodes, selected_nodes, child):
+ return False
+ return True
+ mergeable_nodes = set(nodes)
+ for node in nodes:
+ selected_nodes = set()
+ if gather_deps(
+ mergeable_nodes, selected_nodes, node):
+ break
+ else:
+ selected_nodes = None
+
+ if not selected_nodes:
print "!!! Error: circular dependencies:"
print
- for x in mygraph.dict.keys():
- for y in mygraph.dict[x][1]:
- print y,"depends on",x
- print
+ mygraph.debug_print()
sys.exit(1)
- splitski=string.split(mycurkey)
- #I'm not sure of the significance of the following lines (vestigal?) so I'm commenting 'em out.
- #These lines remove already-merged things from our alt-list
- #if "--update" in myopts:
- # if not portage.db["/"]["vartree"].exists_specific(splitski[2]):
- # portage.db["/"]["merge"].append(splitski)
- #else:
- portage.db[splitski[1]]["merge"].append(splitski)
- mygraph.delnode(mycurkey)
- for x in dolist:
- for y in portage.db[x]["merge"]:
- retlist.append(y)
+
+ for node in selected_nodes:
+ retlist.append(node.split())
+ mygraph.remove(node)
+
return retlist
def xcreate(self,mode="system"):
- global syslist
+ vardb = self.trees[self.target_root]["vartree"].dbapi
world_problems = False
if mode=="system":
- mylist=syslist
+ mylist = getlist(self.settings, "system")
else:
#world mode
- worldlist=getlist("world")
- sysdict=genericdict(syslist)
+ worldlist = getlist(self.settings, "world")
+ sysdict = genericdict(getlist(self.settings, "system"))
worlddict=genericdict(worldlist)
for x in worlddict.keys():
if not portage.isvalidatom(x):
world_problems = True
- elif not portage.db["/"]["vartree"].dbapi.match(x):
+ elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
world_problems = True
else:
sysdict[x]=worlddict[x]
newlist = []
for atom in mylist:
- if portage.dep_getkey(atom).split("/")[-1] == "portage":
+ mykey = portage.dep_getkey(atom)
+ if portage.catsplit(mykey)[-1] == "portage":
newlist.insert(0, atom)
else:
newlist.append(atom)
+ """Make sure all installed slots are updated when possible.
+ Do this with --emptytree also, to ensure that all slots are
+ remerged."""
+ myslots = set()
+ for cpv in vardb.match(mykey):
+ myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
+ if len(myslots) > 1:
+ for myslot in myslots:
+ myslot_atom = "%s:%s" % (mykey, myslot)
+ available = False
+ if "--usepkgonly" not in self.myopts and \
+ self.trees[self.target_root][
+ "porttree"].dbapi.match(myslot_atom):
+ available = True
+ elif "--usepkg" in self.myopts and \
+ self.trees[self.target_root][
+ "bintree"].dbapi.match(myslot_atom):
+ available = True
+ if available:
+ newlist.append(myslot_atom)
mylist = newlist
missing_atoms = []
for mydep in mylist:
try:
- if not self.select_dep(portage.root, mydep, raise_on_missing=True):
- print "\n\n!!! Problem resolving dependencies for", mydep
+ if not self.select_dep(
+ self.target_root, mydep, raise_on_missing=True, arg=mydep):
+ print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
return 0
except ValueError:
- if "--debug" in myopts:
- raise
missing_atoms.append(mydep)
+ self.validate_blockers()
+
if world_problems:
- print "\n!!! Problems have been detected with your world file"
- print "!!! Please run "+green("emaint --check world")+"\n"
+ 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 and "--verbose" in myopts:
- print "\n!!! Packages for the following atoms are either all"
- print "!!! masked or don't exist:"
- print " ".join(missing_atoms) + "\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 match(self,mydep,myroot=portage.root,mykey=None):
+ def match(self, mydep, myroot=None, mykey=None):
# support mutual exclusive deps
+ if myroot is None:
+ myroot = self.target_root
mydep2=mydep
if mydep2[0]=="!":
mydep2=mydep[1:]
#add our blocker; it will be ignored later if necessary (if we are remerging the same pkg, for example)
myk="blocks "+myroot+" "+mydep2
else:
- myeb=portage.db[portage.root]["porttree"].dep_bestmatch(mydep2)
+ myeb = self.trees[myroot]["porttree"].dep_bestmatch(mydep2)
if not myeb:
if not mykey:
print "\n!!! Error: couldn't find match for",mydep
print
sys.exit(1)
- if "--usepkg" in myopts:
- mypk=portage.db[portage.root]["bintree"].dep_bestmatch(mydep)
+ if "--usepkg" in self.myopts:
+ mypk = self.trees[myroot]["bintree"].dep_bestmatch(mydep)
if myeb==mypk:
- myk="binary "+portage.root+" "+mypk
+ myk = " ".join(("binary", myroot, mypk))
else:
- myk="ebuild "+myroot+" "+myeb
+ myk = " ".join(("ebuild", myroot, myeb))
else:
myk="ebuild "+myroot+" "+myeb
return myk
- def display(self,mylist,verbosity=("--quiet" in myopts and 1 or "--verbose" in myopts and 3 or 2)):
+ def display(self,mylist,verbosity=None):
+ if verbosity is None:
+ verbosity = ("--quiet" in self.myopts and 1 or \
+ "--verbose" in self.myopts and 3 or 2)
changelogs=[]
p=[]
totalsize=0
- if verbosity == 1:
+ if verbosity == 1 and "--verbose" not in self.myopts:
def create_use_string(*args):
return ""
else:
- def create_use_string(name, cur_iuse, cur_use, old_iuse, old_use, is_new,
- all_flags=(verbosity == 3), alphabetical=("--alphabetical" in myopts)):
+ def create_use_string(name, cur_iuse, iuse_forced, cur_use,
+ old_iuse, old_use,
+ is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
+ alphabetical=("--alphabetical" in self.myopts)):
enabled = []
if alphabetical:
disabled = enabled
+ removed = enabled
else:
disabled = []
- for flag in cur_iuse:
- if flag in cur_use:
+ removed = []
+ cur_iuse = set(cur_iuse)
+ enabled_flags = cur_iuse.intersection(cur_use)
+ removed_iuse = set(old_iuse).difference(cur_iuse)
+ any_iuse = cur_iuse.union(old_iuse)
+ any_iuse = list(any_iuse)
+ any_iuse.sort()
+ for flag in any_iuse:
+ flag_str = None
+ isEnabled = False
+ if flag in enabled_flags:
+ isEnabled = True
if is_new or flag in old_use and all_flags:
- enabled.append(red(flag))
+ flag_str = red(flag)
elif flag not in old_iuse:
- enabled.append(yellow(flag)+"%")
+ flag_str = yellow(flag) + "%*"
elif flag not in old_use:
- enabled.append(green(flag)+"*")
+ flag_str = green(flag) + "*"
+ elif flag in removed_iuse:
+ if all_flags:
+ flag_str = yellow("-" + flag) + "%"
+ if flag in old_use:
+ flag_str += "*"
+ flag_str = "(" + flag_str + ")"
+ removed.append(flag_str)
+ continue
else:
if is_new or flag in old_iuse and flag not in old_use and all_flags:
- disabled.append(blue("-"+flag))
+ flag_str = blue("-" + flag)
elif flag not in old_iuse:
- disabled.append(yellow("-"+flag)+"%")
+ flag_str = yellow("-" + flag)
+ if flag not in iuse_forced:
+ flag_str += "%"
elif flag in old_use:
- disabled.append(green("-"+flag)+"*")
+ 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)
- enabled = " ".join(enabled)
if alphabetical:
- disabled = ""
- else:
- disabled = " ".join(disabled)
- if enabled and disabled:
- ret = enabled + " " + disabled
- elif enabled:
- ret = enabled
+ ret = " ".join(enabled)
else:
- ret = disabled
+ ret = " ".join(enabled + disabled + removed)
if ret:
ret = '%s="%s" ' % (name, ret)
return ret
if verbosity == 3:
- overlays = string.split(portage.settings['PORTDIR_OVERLAY'])
-
- if "--tree" in myopts:
- mylist.reverse()
- mygraph=self.digraph.copy()
-
+ # FIXME: account for the possibility of different overlays in
+ # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
+ overlays = self.settings["PORTDIR_OVERLAY"].split()
+ overlays_real = [os.path.realpath(t) \
+ for t in self.settings["PORTDIR_OVERLAY"].split()]
+
+ tree_nodes = []
+ node_depth = {}
i = 0
- while i < len(mylist):
- if mylist[i][-1]=="nomerge":
- if not ("--tree" in myopts):
- # we don't care about this elements
- mylist.pop(i)
- continue
- if (i == (len(mylist) - 1)) \
- or (mygraph.depth(string.join(mylist[i])) \
- >= mygraph.depth(string.join(mylist[i+1]))):
- # end of a useless branch (may be the last one)
- # -> delete the element and test the previous one
- mylist.pop(i)
- if i > 0:
- i -= 1
- continue
- # the branch continues, or we've found a good element.
- # -> let's see what's next, if anything
- i += 1
+ depth = 0
+ for x in mylist:
+ graph_key = " ".join(x)
+ if "--tree" in self.myopts:
+ depth = len(tree_nodes)
+ while depth and graph_key not in \
+ self.digraph.child_nodes(tree_nodes[depth-1]):
+ depth -= 1
+ tree_nodes = tree_nodes[:depth]
+ tree_nodes.append(graph_key)
+ node_depth[graph_key] = depth
+
+ last_merge_depth = 0
+ for i in xrange(len(mylist)-1,-1,-1):
+ graph_key = " ".join(mylist[i])
+ if mylist[i][-1] != "nomerge":
+ last_merge_depth = node_depth[graph_key]
+ continue
+ if node_depth[graph_key] >= last_merge_depth or \
+ i < len(mylist) - 1 and \
+ node_depth[graph_key] >= node_depth[" ".join(mylist[i+1])]:
+ del mylist[i]
+ del node_depth[graph_key]
+ del tree_nodes
display_overlays=False
# files to fetch list - avoids counting a same file twice
myfetchlist=[]
for x in mylist:
pkg_type = x[0]
+ myroot = x[1]
pkg_key = x[2]
- if pkg_key not in self.applied_useflags:
+ portdb = self.trees[myroot]["porttree"].dbapi
+ bindb = self.trees[myroot]["bintree"].dbapi
+ vartree = self.trees[myroot]["vartree"]
+ pkgsettings = self.pkgsettings[myroot]
+ pkgsettings.setcpv(pkg_key)
+ if pkg_key not in self.useFlags[myroot]:
if "binary" == pkg_type:
- self.applied_useflags[pkg_key] = portage.db["/"]["bintree"].dbapi.aux_get(pkg_key, ["USE"])[0].split()
+ self.useFlags[myroot][pkg_key] = bindb.aux_get(
+ pkg_key, ["USE"])[0].split()
elif "ebuild" == pkg_type:
- self.pkgsettings.setcpv(pkg_key)
- self.applied_useflags[pkg_key] = self.pkgsettings["USE"].split()
+ self.useFlags[myroot][pkg_key] = pkgsettings["USE"].split()
fetch=" "
if x[0]=="blocks":
addl=""+red("B")+" "+fetch+" "
- resolved=portage.db[x[1]]["vartree"].resolve_key(x[2])
+ resolved = self.trees[x[1]]["vartree"].resolve_key(x[2])
print "["+x[0]+" "+addl+"]",red(resolved),
+ block_parents = self.digraph.parent_nodes(" ".join(x))
+ block_parents = [pnode.split()[2] for pnode in block_parents]
+ block_parents = ", ".join(block_parents)
if resolved!=x[2]:
- if x[3]:
- print red("(\""+x[2]+"\" is blocking "+x[3]+")")
- else:
- print red("(\""+x[2]+"\")")
+ print bad("(\"%s\" is blocking %s)") % \
+ (pkg_key, block_parents)
else:
- if x[3]:
- print red("(is blocking "+x[3]+")")
- else:
- print
+ print bad("(is blocking %s)") % block_parents
else:
- if (x[0]!="binary") and ("fetch" in string.split(portage.portdb.aux_get(x[2],["RESTRICT"])[0])):
+ mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
+ if "ebuild" == pkg_type and x[3] != "nomerge" and \
+ "fetch" in portdb.aux_get(
+ x[2], ["RESTRICT"])[0].split():
fetch = red("F")
- if portage.portdb.fetch_check(x[2], self.applied_useflags[x[2]]):
+ if portdb.fetch_check(
+ pkg_key, self.useFlags[myroot][pkg_key]):
fetch = green("f")
#we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
#param is used for -u, where you still *do* want to see when something is being upgraded.
myoldbest=""
- if (not "--emptytree" in myopts) and portage.db[x[1]]["vartree"].exists_specific(x[2]):
+ if "--emptytree" not in self.myopts and \
+ self.trees[x[1]]["vartree"].exists_specific(x[2]):
addl=" "+yellow("R")+fetch+" "
- elif (not "--emptytree" in myopts) and portage.db[x[1]]["vartree"].exists_specific_cat(x[2]):
- if x[0] == "binary":
- mynewslot=portage.db["/"]["bintree"].getslot(x[2])
- elif x[0] == "ebuild":
- mynewslot=portage.db["/"]["porttree"].getslot(x[2])
- myoldlist=portage.db[x[1]]["vartree"].dbapi.match(portage.pkgsplit(x[2])[0])
- myinslotlist=filter((lambda p: portage.db[portage.root]["vartree"].getslot(p)==mynewslot),myoldlist)
+ elif "--emptytree" not in self.myopts and \
+ self.trees[x[1]]["vartree"].exists_specific_cat(x[2]):
+ mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
+ myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
+ portage.pkgsplit(x[2])[0])
+ myinslotlist = [inst_pkg for inst_pkg in myoldlist
+ if mynewslot == vartree.getslot(inst_pkg)]
if myinslotlist:
myoldbest=portage.best(myinslotlist)
addl=" "+fetch
# New slot, mark it new.
addl=" "+green("NS")+fetch+" "
- if "--changelog" in myopts:
+ if "--changelog" in self.myopts:
changelogs.extend(self.calc_changelog(
- portage.portdb.findname(x[2]),
- portage.db[x[1]]["vartree"].dep_bestmatch('/'.join(portage.catpkgsplit(x[2])[:2])),
- x[2]
- ))
+ portdb.findname(pkg_key),
+ self.trees[x[1]]["vartree"].dep_bestmatch(
+ '/'.join(portage.catpkgsplit(x[2])[:2])), x[2]))
else:
addl=" "+green("N")+" "+fetch+" "
verboseadd=""
- if x[2] in self.applied_useflags:
+ if pkg_key in self.useFlags[myroot]:
# USE flag display
- if x[0] == "binary":
- cur_iuse = string.split(portage.db["/"]["bintree"].dbapi.aux_get(x[2],["IUSE"])[0])
- elif x[0] == "ebuild":
- cur_iuse = string.split(portage.portdb.aux_get(x[2],["IUSE"])[0])
- else:
- cur_iuse = []
+ cur_iuse = mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()
+
+ forced_flags = set()
+ forced_flags.update(pkgsettings.useforce)
+ forced_flags.update(pkgsettings.puseforce)
+ forced_flags.update(pkgsettings.usemask)
+ forced_flags.update(pkgsettings.pusemask)
cur_iuse = portage.unique_array(cur_iuse)
- cur_iuse = [flag for flag in cur_iuse if flag not in portage.settings.usemask]
cur_iuse.sort()
- cur_use = self.applied_useflags[x[2]]
+ cur_use = self.useFlags[myroot][pkg_key]
cur_use = [flag for flag in cur_use if flag in cur_iuse]
if myoldbest:
pkg = myoldbest
else:
pkg = x[2]
- if portage.db[x[1]]["vartree"].dbapi.cpv_exists(pkg):
- (old_iuse, old_use) = portage.db[x[1]]["vartree"].dbapi.aux_get(pkg, ["IUSE", "USE"])
+ 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 = portage.unique_array(old_iuse.split())
old_iuse.sort()
old_use = old_use.split()
old_iuse = []
old_use = []
is_new = True
- old_iuse = [flag for flag in old_iuse if flag not in portage.settings.usemask]
+
old_use = [flag for flag in old_use if flag in old_iuse]
- use_expand = portage.settings["USE_EXPAND"].lower().split()
+ use_expand = pkgsettings["USE_EXPAND"].lower().split()
use_expand.sort()
use_expand.reverse()
- use_expand_hidden = portage.settings["USE_EXPAND_HIDDEN"].lower().split()
+ use_expand_hidden = \
+ pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
- def map_to_use_expand(myvals):
+ def map_to_use_expand(myvals, forcedFlags=False):
ret = {}
+ forced = {}
for exp in use_expand:
ret[exp] = []
+ forced[exp] = set()
for val in myvals[:]:
if val.startswith(exp.lower()+"_"):
+ if val in forced_flags:
+ forced[exp].add(val[len(exp)+1:])
ret[exp].append(val[len(exp)+1:])
myvals.remove(val)
ret["USE"] = myvals
+ forced["USE"] = [val for val in myvals \
+ if val in forced_flags]
for exp in use_expand_hidden:
if exp in ret:
del ret[exp]
+ if forcedFlags:
+ return ret, forced
return ret
- cur_iuse_map = map_to_use_expand(cur_iuse)
+ 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.insert(0, "USE")
for key in use_expand:
- verboseadd += create_use_string(key.upper(), cur_iuse_map[key], cur_use_map[key],
- old_iuse_map[key], old_use_map[key], is_new)
+ if key in use_expand_hidden:
+ continue
+ verboseadd += create_use_string(key.upper(),
+ cur_iuse_map[key], iuse_forced[key],
+ cur_use_map[key], old_iuse_map[key],
+ old_use_map[key], is_new)
if verbosity == 3:
# size verbose
mysize=0
if x[0] == "ebuild" and x[-1]!="nomerge":
- myfilesdict=portage.portdb.getfetchsizes(x[2], useflags=self.applied_useflags[x[2]], debug=edebug)
- if myfilesdict==None:
+ myfilesdict = portdb.getfetchsizes(
+ pkg_key, useflags=self.useFlags[myroot][pkg_key],
+ debug=self.edebug)
+ if myfilesdict is None:
myfilesdict="[empty/missing/bad digest]"
else:
for myfetchfile in myfilesdict.keys():
# overlay verbose
# XXX: Invalid binaries have caused tracebacks here. 'if file_name'
# x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
- file_name=portage.portdb.findname(x[2])
+ file_name = portdb.findname(pkg_key)
if file_name: # It might not exist in the tree
dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
- if (overlays.count(dir_name)>0):
- verboseadd+=teal("["+str(overlays.index(os.path.normpath(dir_name))+1)+"]")+" "
+ if (overlays_real.count(dir_name)>0):
+ verboseadd+=teal("["+str(overlays_real.index(
+ os.path.normpath(dir_name))+1)+"]")+" "
display_overlays=True
else:
verboseadd += "[No ebuild?]"
- verboseadd+="EAPI: "+blue(str(portage.portdb.aux_get(x[2],["EAPI"])[0]))
-
xs=portage.pkgsplit(x[2])
if xs[2]=="r0":
xs[2]=""
else:
xs[2]="-"+xs[2]
- if self.pkgsettings.has_key("COLUMNWIDTH"):
- mywidth=int(self.pkgsettings.settings["COLUMNWIDTH"])
- else:
- mywidth=130
+ 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=""
- if ("--tree" in myopts):
- indent=" "*mygraph.depth(string.join(x))
+ indent = " " * node_depth[" ".join(x)]
if myoldbest:
myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
myoldbest=blue("["+myoldbest+"]")
if x[1]!="/":
- if "--columns" in myopts:
- if "--quiet" in myopts:
+ if myoldbest:
+ myoldbest +=" "
+ if "--columns" in self.myopts:
+ if "--quiet" in self.myopts:
myprint=addl+" "+indent+darkgreen(xs[0])
- myprint=myprint+darkblue(xs[1]+xs[2])+" "
+ myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
myprint=myprint+myoldbest
- myprint=myprint+darkgreen(" to "+x[1])
+ myprint=myprint+darkgreen("to "+x[1])
else:
myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
if (newlp-nc_len(myprint)) > 0:
if (oldlp-nc_len(myprint)) > 0:
myprint=myprint+" "*(oldlp-nc_len(myprint))
myprint=myprint+myoldbest
- myprint=myprint+darkgreen(" to "+x[1])+" "+verboseadd
+ myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
else:
- myprint="["+x[0]+" "+addl+"] "+darkgreen(x[2])+" "+myoldbest+" "+darkgreen("to "+x[1])+" "+verboseadd
+ myprint="["+x[0]+" "+addl+"] "+darkgreen(x[2])+" "+myoldbest+darkgreen("to "+x[1])+" "+verboseadd
else:
- if "--columns" in myopts:
- if "--quiet" in myopts:
+ if "--columns" in self.myopts:
+ if "--quiet" in self.myopts:
myprint=addl+" "+indent+darkgreen(xs[0])
myprint=myprint+" "+green(xs[1]+xs[2])+" "
myprint=myprint+myoldbest
myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
p.append(myprint)
- if ("--tree" not in myopts):
- mysplit=portage.pkgsplit(x[2])
-
- # XXX mysplit _can_ be None.... Why?
- if mysplit and (len(mysplit)==3):
- if "--emptytree" not in myopts:
- if mysplit[0]=="sys-apps/portage":
- if ((mysplit[1]+mysplit[2]) != portage.VERSION) and \
- ("livecvsportage" not in portage.settings.features):
- if mylist.index(x)<len(mylist)-1:
- p.append(red("*** Portage will stop merging at this point and reload itself,"))
- p.append(red(" then resume the merge."))
- print
- else:
- if mysplit[0]=="sys-apps/portage" and ("--emptytree" in myopts):
- if mysplit[1]+mysplit[2]!=portage.VERSION:
- p.append(red("***")+" Please update portage to the above version before proceeding.")
- p.append(" Failure to do so may result in failed or improper merges.")
- p.append(" A simple '"+green("emerge -u portage")+"' is sufficient.")
- p.append("")
- del mysplit
+ 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 :
+ if "--emptytree" in self.myopts:
+ p.append(colorize("WARN", "***")+" Please update portage to the above version before proceeding.")
+ p.append(" Failure to do so may result in failed or improper merges.")
+ p.append(" A simple '"+green("emerge portage")+"' is sufficient.")
+ p.append("")
+ elif mylist.index(x) < len(mylist) - 1 and \
+ "livecvsportage" not in self.settings.features:
+ p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
+ p.append(colorize("WARN", " then resume the merge."))
+ print
+ del mysplit
for x in p:
print x
y=y+1
print " "+teal("["+str(y)+"]"),x
- if "--changelog" in myopts:
+ if "--changelog" in self.myopts:
print
for revision,text in changelogs:
print bold('*'+revision)
divs = []
release = None
while 1:
- match = re.search(r'^\*\ ?([-a-zA-Z0-9_.]*)(?:\ .*)?\n',changelog,re.M)
+ 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))
def outdated(self):
return self.outdatedpackages
- def merge(self,mylist):
+class MergeTask(object):
+
+ def __init__(self, settings, trees, myopts):
+ self.settings = settings
+ self.target_root = settings["ROOT"]
+ self.trees = trees
+ self.myopts = myopts
+ self.edebug = 0
+ if settings.get("PORTAGE_DEBUG", "") == "1":
+ self.edebug = 1
+ self.pkgsettings = {}
+ self.pkgsettings[self.target_root] = portage.config(clone=settings)
+ if self.target_root != "/":
+ self.pkgsettings["/"] = \
+ portage.config(clone=trees["/"]["vartree"].settings)
+
+ def merge(self, mylist, favorites, mtimedb):
returnme=0
mymergelist=[]
+ ldpath_mtimes = mtimedb["ldpath"]
+ xterm_titles = "notitles" not in self.settings.features
#check for blocking dependencies
- if ("--fetchonly" not in myopts) and ("--buildpkgonly" not in myopts):
+ if "--fetchonly" not in self.myopts and \
+ "--buildpkgonly" not in self.myopts:
for x in mylist:
if x[0]=="blocks":
print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
print "!!! the two packages cannot be installed on the same system together."
print "!!! Please use 'emerge --pretend' to determine blockers."
- print
- if ("--pretend" not in myopts):
+ if "--quiet" not in self.myopts:
+ show_blocker_docs_link()
+ if "--pretend" not in self.myopts:
+ try:
+ del mtimedb["resume"]
+ except KeyError:
+ pass
sys.exit(1)
#buildsyspkg: I need mysysdict also on resume (moved from the else block)
- mysysdict=genericdict(syslist)
- if ("--resume" in myopts):
+ mysysdict = genericdict(getlist(self.settings, "system"))
+ if "--resume" in self.myopts:
# We're resuming.
- print green("*** Resuming merge...")
- emergelog(" *** Resuming merge...")
- mymergelist=portage.mtimedb["resume"]["mergelist"][:]
- if ("--skipfirst" in myopts) and mymergelist:
- del portage.mtimedb["resume"]["mergelist"][0]
+ print colorize("GOOD", "*** Resuming merge...")
+ emergelog(xterm_titles, " *** Resuming merge...")
+ mymergelist=mtimedb["resume"]["mergelist"][:]
+ if "--skipfirst" in self.myopts and mymergelist:
+ del mtimedb["resume"]["mergelist"][0]
del mymergelist[0]
- for bigkey in mymergelist:
- (pkgtype, root, cpv, action) = bigkey
- if pkgtype == "binary" and not portage.db["/"]["bintree"].dbapi.match("="+cpv) or \
- pkgtype == "ebuild" and not portage.db["/"]["porttree"].dbapi.xmatch("match-all", "="+cpv):
- print red("!!! Error: The resume list contains packages that no longer")
- print red("!!! available to be emerged. Please restart/continue")
- print red("!!! the merge operation manually.")
- sys.exit(1)
+ mtimedb.commit()
+ validate_merge_list(self.trees, mymergelist)
else:
- myfavs = portage.grabfile(os.path.join(portage.root, portage.WORLD_FILE))
+ myfavs = portage.grabfile(
+ os.path.join(self.target_root, portage.WORLD_FILE))
myfavdict=genericdict(myfavs)
for x in range(len(mylist)):
if mylist[x][3]!="nomerge":
mymergelist.append(mylist[x])
else:
myfavkey=portage.cpv_getkey(mylist[x][2])
- if "--onlydeps" in myopts:
+ if "--onlydeps" in self.myopts:
continue
# Add to the world file. Since we won't be able to later.
- if (not "--fetchonly" in myopts) and (myfavkey in favorites):
+ if "--fetchonly" not in self.myopts and \
+ myfavkey in favorites:
#don't record if already in system profile or already recorded
if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
#we don't have a favorites entry for this package yet; add one
myfavdict[myfavkey]=myfavkey
print ">>> Recording",myfavkey,"in \"world\" favorites file..."
- if not "--fetchonly" in myopts:
+ if not ("--fetchonly" in self.myopts or \
+ "--fetch-all-uri" in self.myopts or \
+ "--pretend" in self.myopts):
portage.write_atomic(
- os.path.join(portage.root, portage.WORLD_FILE),
- "\n".join(myfavdict.values()))
-
- portage.mtimedb["resume"]["mergelist"]=mymergelist[:]
-
- # We need to yank the harmful-to-new-builds settings from features.
- myorigfeat=self.pkgsettings["FEATURES"]
- myfeat=myorigfeat.split()
- while ("keeptemp" in myfeat):
- del myfeat[myfeat.index("keeptemp")]
- while ("keepwork" in myfeat):
- del myfeat[myfeat.index("keepwork")]
-
- self.pkgsettings["FEATURES"]=string.join(myfeat)
-
- if "parallel-fetch" in myfeat and not ("--ask" in myopts or "--pretend" in myopts or "--fetchonly" in myopts):
+ os.path.join(self.target_root, portage.WORLD_FILE),
+ "\n".join(myfavdict.values()))
+
+ mtimedb["resume"]["mergelist"]=mymergelist[:]
+ mtimedb.commit()
+
+ myfeat = self.settings.features[:]
+ bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
+ "--resume"])
+ if "parallel-fetch" in myfeat and \
+ not ("--pretend" in self.myopts or \
+ "--fetch-all-uri" in self.myopts or \
+ "--fetchonly" in self.myopts):
if "distlocks" not in myfeat:
print red("!!!")
print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
print red("!!!")
elif len(mymergelist) > 1:
print ">>> starting parallel fetching"
- pid = os.fork()
- if not pid:
- sys.stdin.close()
- sys.stdout.close()
- sys.stderr.close()
- time.sleep(3) # allow the parent to have first fetch
- sys.stdout = open("/dev/null","w")
- sys.stderr = open("/dev/null","w")
- os.dup2(sys.stdout.fileno(), 1)
- os.dup2(sys.stdout.fileno(), 2)
- # wipe the mtimedb so that portage doesn't attempt to flush it.
- # do not convert this code away from a fork without correcting this.
- portage.mtimedb = None
- for x in ("autoaddcvs", "cvs"):
- try: myfeat.remove(x)
- except ValueError: pass
- self.pkgsettings["FEATURES"] = " ".join(myfeat)
- ret = 0
- for x in mymergelist:
- if x[0] != "ebuild":
- continue
- try:
- ret = portage.doebuild(portage.portdb.findname(x[2]), "fetch", x[1], self.pkgsettings,
- cleanup=0, fetchonly=True, tree="porttree")
- except SystemExit:
- raise
- except Exception:
- ret = 1
- sys.exit(0)
- portage.portage_exec.spawned_pids.append(pid)
+ fetch_log = "/var/log/emerge-fetch.log"
+ logfile = open(fetch_log, "w")
+ fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
+ portage_util.apply_secpass_permissions(fetch_log,
+ uid=portage.portage_uid, gid=portage.portage_gid,
+ mode=0660)
+ fetch_env = os.environ.copy()
+ fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
+ fetch_env["PORTAGE_NICENESS"] = "0"
+ fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
+ for myopt, myarg in self.myopts.iteritems():
+ if myopt not in bad_resume_opts:
+ if myarg is True:
+ fetch_args.append(myopt)
+ else:
+ fetch_args.append(myopt +"="+ myarg)
+ portage.portage_exec.spawn(fetch_args, env=fetch_env,
+ fd_pipes=fd_pipes, returnpid=True)
+ logfile.close() # belongs to the spawned process
mergecount=0
for x in mymergelist:
mergecount+=1
myroot=x[1]
+ pkg_key = x[2]
pkgindex=2
+ portdb = self.trees[myroot]["porttree"].dbapi
+ bindb = self.trees[myroot]["bintree"].dbapi
+ vartree = self.trees[myroot]["vartree"]
+ pkgsettings = self.pkgsettings[myroot]
if x[0]=="blocks":
pkgindex=3
- y=portage.portdb.findname(x[pkgindex])
- if not "--pretend" in myopts:
- print ">>> Emerging ("+str(mergecount)+" of "+str(len(mymergelist))+")",x[pkgindex],"to",x[1]
- emergelog(" >>> emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" to "+x[1])
-
- self.pkgsettings["EMERGE_FROM"] = x[0][:]
- self.pkgsettings.backup_changes("EMERGE_FROM")
- self.pkgsettings.reset()
+ y = portdb.findname(pkg_key)
+ if "--pretend" not in self.myopts:
+ print "\n>>> Emerging (" + \
+ colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
+ colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
+ colorize("GOOD", x[pkgindex]) + " to " + x[1]
+ emergelog(xterm_titles, " >>> emerge ("+\
+ str(mergecount)+" of "+str(len(mymergelist))+\
+ ") "+x[pkgindex]+" to "+x[1])
+
+ pkgsettings["EMERGE_FROM"] = x[0]
+ pkgsettings.backup_changes("EMERGE_FROM")
+ pkgsettings.reset()
#buildsyspkg: Check if we need to _force_ binary package creation
issyspkg = ("buildsyspkg" in myfeat) \
and x[0] != "blocks" \
and mysysdict.has_key(portage.cpv_getkey(x[2])) \
- and not ("--buildpkg" in myopts)
+ and "--buildpkg" not in self.myopts
if x[0] in ["ebuild","blocks"]:
- if (x[0]=="blocks") and ("--fetchonly" not in myopts):
+ if x[0] == "blocks" and "--fetchonly" not in self.myopts:
raise Exception, "Merging a blocker"
- elif ("--fetchonly" in myopts) or ("--fetch-all-uri" in myopts):
- if ("--fetch-all-uri" in myopts):
- retval=portage.doebuild(y,"fetch",myroot,self.pkgsettings,edebug,("--pretend" in myopts),fetchonly=1,fetchall=1,tree="porttree")
+ 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,self.pkgsettings,edebug,("--pretend" in myopts),fetchonly=1,tree="porttree")
- if (retval == None) or retval:
+ 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
returnme=1
continue
- elif "--buildpkg" in myopts or issyspkg:
- #buildsyspkg: Sounds useful to display something, but I don't know if we should also log it
- if issyspkg:
- print ">>> This is a system package, let's pack a rescue tarball."
- #emergelog(">>> This is a system package, let's pack a rescue tarball.")
- #create pkg, then merge pkg
- short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean"
- emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
- retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1,tree="porttree")
- if (retval == None):
- portage_util.writemsg("Unable to run required binary.\n")
- sys.exit(127)
- if retval:
- sys.exit(retval)
- short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Compile"
- emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Packaging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
- retval=portage.doebuild(y,"package",myroot,self.pkgsettings,edebug,tree="porttree")
- if (retval == None):
- portage_util.writemsg("Unable to run required binary.\n")
- sys.exit(127)
- if retval:
- sys.exit(retval)
- #dynamically update our database
- if "--buildpkgonly" not in myopts:
- portage.db[portage.root]["bintree"].inject(x[2])
- mytbz2=portage.db[portage.root]["bintree"].getname(x[2])
- short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge"
- emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
-
- self.pkgsettings["EMERGE_FROM"] = "binary"
- self.pkgsettings.backup_changes("EMERGE_FROM")
-
- retval=portage.pkgmerge(mytbz2,myroot,self.pkgsettings)
- if retval==None:
- sys.exit(1)
- else:
- short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean"
- emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
- retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1,tree="porttree")
- if (retval == None):
- portage_util.writemsg("Unable to run required binary.\n")
- sys.exit(127)
- if retval:
- sys.exit(retval)
- short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Compile"
- emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Merging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
- retval=portage.doebuild(y,"merge",myroot,self.pkgsettings,edebug,tree="porttree")
- if (retval == None):
- portage_util.writemsg("Unable to run required binary.\n")
- sys.exit(127)
- if retval:
- sys.exit(retval)
- #dynamically update our database
+
+ 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)
+ retval = portage.doebuild(y, "package", myroot,
+ pkgsettings, self.edebug, mydbapi=portdb,
+ tree="porttree")
+ if retval != os.EX_OK:
+ return retval
+ if "--buildpkgonly" not in self.myopts:
+ bintree = self.trees[myroot]["bintree"]
+ bintree.inject(pkg_key)
+ mytbz2 = bintree.getname(pkg_key)
+ msg = " === (%s of %s) Merging (%s::%s)" % \
+ (mergecount, len(mymergelist), pkg_key, y)
+ short_msg = "emerge: (%s of %s) %s Merge" % \
+ (mergecount, len(mymergelist), pkg_key)
+ emergelog(xterm_titles, msg, short_msg=short_msg)
+ retval = portage.merge(pkgsettings["CATEGORY"],
+ pkgsettings["PF"], pkgsettings["D"],
+ os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
+ "build-info"), myroot, pkgsettings,
+ myebuild=pkgsettings["EBUILD"],
+ mytree="porttree", mydbapi=portdb,
+ vartree=vartree, prev_mtimes=ldpath_mtimes)
+ if retval != os.EX_OK:
+ return retval
+ elif "noclean" not in pkgsettings.features:
+ portage.doebuild(y, "clean", myroot,
+ pkgsettings, self.edebug, mydbapi=portdb,
+ tree="porttree")
+ else:
+ msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
+ (mergecount, len(mymergelist), pkg_key, y)
+ short_msg = "emerge: (%s of %s) %s Compile" % \
+ (mergecount, len(mymergelist), pkg_key)
+ emergelog(xterm_titles, msg, short_msg=short_msg)
+ retval = portage.doebuild(y, "merge", myroot,
+ pkgsettings, self.edebug, vartree=vartree,
+ mydbapi=portdb, tree="porttree",
+ prev_mtimes=ldpath_mtimes)
+ if retval != os.EX_OK:
+ return retval
+ finally:
+ if builddir_lock:
+ portage_locks.unlockdir(builddir_lock)
+ try:
+ if not catdir_lock:
+ # Lock catdir for removal if empty.
+ catdir_lock = portage_locks.lockdir(catdir)
+ finally:
+ if catdir_lock:
+ try:
+ os.rmdir(catdir)
+ except OSError, e:
+ if e.errno != errno.ENOTEMPTY:
+ raise
+ del e
+ portage_locks.unlockdir(catdir_lock)
+
elif x[0]=="binary":
#merge the tbz2
- mytbz2=portage.db[portage.root]["bintree"].getname(x[2])
- if portage.db[portage.root]["bintree"].isremote(x[2]):
+ mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
+ if self.trees[myroot]["bintree"].isremote(pkg_key):
short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Fetch"
- emergelog(" --- ("+str(mergecount)+" of "+str(len(mymergelist))+") Fetching Binary ("+x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
- if not portage.db[portage.root]["bintree"].gettbz2(x[2]):
+ emergelog(xterm_titles, " --- ("+str(mergecount)+\
+ " of "+str(len(mymergelist))+\
+ ") Fetching Binary ("+x[pkgindex]+\
+ "::"+mytbz2+")", short_msg=short_msg)
+ if not self.trees[myroot]["bintree"].gettbz2(pkg_key):
sys.exit(1)
- if ("--fetchonly" in myopts) or ("--fetch-all-uri" in myopts):
+ if "--fetchonly" in self.myopts or \
+ "--fetch-all-uri" in self.myopts:
continue
short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
- emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging Binary ("+x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
- retval=portage.pkgmerge(mytbz2,x[1],self.pkgsettings)
- if retval==None:
+ 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 is None:
sys.exit(1)
#need to check for errors
- if "--buildpkgonly" not in myopts:
- portage.db[x[1]]["vartree"].inject(x[2])
+ if "--buildpkgonly" not in self.myopts:
+ self.trees[x[1]]["vartree"].inject(x[2])
myfavkey=portage.cpv_getkey(x[2])
- if "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts and myfavkey in favorites:
+ if "--fetchonly" not in self.myopts and \
+ "--fetch-all-uri" not in self.myopts and \
+ myfavkey in favorites:
myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
myfavdict=genericdict(myfavs)
- mysysdict=genericdict(syslist)
#don't record if already in system profile or already recorded
if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
#we don't have a favorites entry for this package yet; add one
myfavdict[myfavkey]=myfavkey
print ">>> Recording",myfavkey,"in \"world\" favorites file..."
- emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Updating world file ("+x[pkgindex]+")")
+ emergelog(xterm_titles, " === ("+\
+ str(mergecount)+" of "+\
+ str(len(mymergelist))+\
+ ") Updating world file ("+x[pkgindex]+")")
portage.write_atomic(
os.path.join(myroot, portage.WORLD_FILE),
"\n".join(myfavdict.values()))
- if ("--pretend" not in myopts) and ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts):
+ 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 self.pkgsettings["AUTOCLEAN"]=="yes":
+ if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
xsplit=portage.pkgsplit(x[2])
- emergelog(" >>> AUTOCLEAN: "+xsplit[0])
- retval=unmerge("clean", [xsplit[0]])
+ emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
+ retval = unmerge(pkgsettings, self.myopts, vartree,
+ "clean", [xsplit[0]], ldpath_mtimes)
if not retval:
- emergelog(" --- AUTOCLEAN: Nothing unmerged.")
+ 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":
+ 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 portage.settings.features):
+ "livecvsportage" not in self.settings.features:
if len(mymergelist) > mergecount:
- emergelog(" *** RESTARTING emerge via exec() after change of portage version.")
- del portage.mtimedb["resume"]["mergelist"][0]
+ 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"]
- badlongopts = ("--ask","--tree","--changelog","--skipfirst","--resume")
- for arg in myopts:
- if arg in badlongopts:
- continue
- mynewargv.append(arg)
+ for myopt, myarg in self.myopts.iteritems():
+ if myopt not in bad_resume_opts:
+ if myarg is True:
+ mynewargv.append(myopt)
+ else:
+ mynewargv.append(myopt +"="+ myarg)
+ # priority only needs to be adjusted on the first run
+ os.environ["PORTAGE_NICENESS"] = "0"
os.execv(mynewargv[0], mynewargv)
- if ("--pretend" not in myopts) and ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts):
- if "noclean" not in portage.features:
+ 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(" === (%s of %s) Post-Build Cleaning (%s::%s)" % \
- (mergecount, len(mymergelist), x[pkgindex], y), short_msg=short_msg)
- emergelog(" ::: completed emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[2]+" to "+x[1])
+ 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 portage.mtimedb["resume"]["mergelist"][0]
+ 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...
- portage.commit_mtimedb()
+ mtimedb.commit()
- emergelog(" *** Finished. Cleaning up...")
+ 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 portage.mtimedb.has_key("resume"):
- del portage.mtimedb["resume"]
-
- if ("--pretend" not in myopts):
- if ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts):
- if (mergecount>0):
- if retval:
- portage.env_update()
+ 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 myopts or "--fetch-all-uri" in myopts:
+ if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
if returnme:
print "\n\n!!! Some fetch errors were encountered. Please see above for details.\n\n"
sys.exit(returnme)
else:
sys.exit(0)
+ return os.EX_OK
-def unmerge(unmerge_action, unmerge_files):
+def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
+ ldpath_mtimes, raise_on_missing=True):
candidate_catpkgs=[]
global_unmerge=0
+ xterm_titles = "notitles" not in settings.features
- realsyslist = getlist("system")
+ realsyslist = getlist(settings, "system")
syslist = []
for x in realsyslist:
mycp = portage.dep_getkey(x)
- if mycp in portage.settings.getvirtuals():
+ if mycp in settings.getvirtuals():
providers = []
- for provider in portage.settings.getvirtuals()[mycp]:
- if portage.db[portage.root]["vartree"].dbapi.match(provider):
+ 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)
- global myopts
- mysettings = portage.config(clone=portage.settings)
+ mysettings = portage.config(clone=settings)
if not unmerge_files or "world" in unmerge_files or "system" in unmerge_files:
if "unmerge"==unmerge_action:
else:
global_unmerge=1
- localtree=portage.db[portage.root]["vartree"]
+ 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(localtree.getallnodes())
elif "system" in unmerge_files:
- candidate_catpkgs.extend(getlist("system"))
+ candidate_catpkgs.extend(getlist(settings, "system"))
else:
#we've got command-line arguments
if not unmerge_files:
sp_absx_len = len(sp_absx)
- vdb_path = portage.root+portage.VDB_PATH
+ vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
vdb_len = len(vdb_path)
sp_vdb = vdb_path.split("/")
if sp_absx_len <= sp_vdb_len:
# The Path is shorter... so it can't be inside the vdb.
- print spabsx
+ print sp_absx
print absx
- print "\n!!!",x,"cannot be inside "+(portage.root+portage.VDB_PATH)+"; aborting.\n"
+ 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 "+(portage.root+portage.VDB_PATH)+"; aborting.\n"
+ print "\n!!!",x,"is not inside "+vdb_path+"; aborting.\n"
return 0
print "="+string.join(sp_absx[sp_vdb_len:],"/")
candidate_catpkgs.append("="+string.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("\n>>> These are the packages that would be unmerged:")
+ print darkgreen(newline+">>> These are the packages that would be unmerged:")
pkgmap={}
numselected=0
#add a "=" if missing
mymatch=localtree.dep_match("="+x)
if not mymatch:
- print "\n--- Couldn't find " + white(x) + " to "+unmerge_action+"."
- continue
- mykey=portage.key_expand(portage.dep_getkey(mymatch[0]),portage.db["/"]["vartree"].dbapi)
+ if raise_on_missing:
+ raise portage_exception.PackageNotFound(x)
+ else:
+ 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":
#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 red("\a\n\n!!! '%s' is part of your system profile." % mykey)
- print yellow("\a!!! Unmerging it may be damaging to your system.\n")
+ 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:
- global EMERGE_WARNING_DELAY
- countdown(EMERGE_WARNING_DELAY,red("Press Ctrl-C to Stop"))
+ countdown(int(settings["EMERGE_WARNING_DELAY"]),
+ colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
print "\n "+white(x)
for mytype in ["selected","protected","omitted"]:
- print string.rjust(mytype,12)+":",
+ portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
if pkgmap[x][mytype]:
for mypkg in pkgmap[x][mytype]:
mysplit=portage.catpkgsplit(mypkg)
else:
myversion=mysplit[2]+"-"+mysplit[3]
if mytype=="selected":
- print red(myversion),
+ portage.writemsg_stdout(
+ colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
else:
- print green(myversion),
+ portage.writemsg_stdout(
+ colorize("GOOD", myversion + " "), noiselevel=-1)
else:
- print "none",
- print
-
- if portage.settings["ROOT"]:
- print string.rjust("ROOT:", 12) + " " + white(portage.settings["ROOT"])
+ portage.writemsg_stdout("none", noiselevel=-1)
+ portage.writemsg_stdout("\n", noiselevel=-1)
- print "\n>>>",red("'Selected'"),"packages are slated for removal."
- print ">>>",green("'Protected'"),"and",green("'omitted'"),"packages will not be removed.\n"
+ 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("Do you want me to unmerge these packages?")=="No":
+ if userquery("Would you like to unmerge these packages?")=="No":
# enter pretend mode for correct formatting of results
- myopts+=["--pretend"]
+ myopts["--pretend"] = True
print
print "Quitting."
print
return 0
#the real unmerging begins, after a short delay....
-
- global CLEAN_DELAY
- countdown(CLEAN_DELAY, ">>> Unmerging")
+ countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
for x in pkgmap.keys():
for y in pkgmap[x]["selected"]:
print ">>> Unmerging "+y+"..."
- emergelog("=== Unmerging... ("+y+")")
+ emergelog(xterm_titles, "=== Unmerging... ("+y+")")
mysplit=string.split(y,"/")
#unmerge...
- retval=portage.unmerge(mysplit[0],mysplit[1],portage.root,mysettings,unmerge_action not in ["clean","prune"])
- if retval:
- emergelog(" !!! unmerge FAILURE: "+y)
+ 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)
else:
- emergelog(" >>> unmerge success: "+y)
- #run ldconfig, etc...
- portage.env_update()
- if not numselected:
- return 0
- else:
- return 1
-
+ clean_world(vartree.dbapi, y)
+ emergelog(xterm_titles, " >>> unmerge success: "+y)
+ return 1
-def chk_updated_info_files(retval):
- root=portage.root
-
- infodirs=[]
- infodirs.extend(string.split(portage.settings["INFOPATH"], ":"))
- infodirs.extend(string.split(portage.settings["INFODIR"], ":"))
+def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
print
- if os.path.exists("install-info"):
+ if os.path.exists(portage_const.EPREFIX+"/usr/bin/install-info"):
regen_infodirs=[]
for z in infodirs:
if z=='':
continue
inforoot=normpath(root+z)
if os.path.isdir(inforoot):
- try:
- infomtime=os.stat(inforoot)[ST_MTIME]
- except SystemExit, e:
- raise # Needed else can't exit
- except:
- infomtime=0
-
- if not portage.mtimedb.has_key("info"):
- portage.mtimedb["info"]={}
- if portage.mtimedb["info"].has_key(inforoot):
- if portage.mtimedb["info"][inforoot]==infomtime:
- pass
- else:
- portage.mtimedb["info"][inforoot]=infomtime
+ infomtime = long(os.stat(inforoot).st_mtime)
+ if inforoot not in prev_mtimes or \
+ prev_mtimes[inforoot] != infomtime:
regen_infodirs.append(inforoot)
- else:
- regen_infodirs.append(inforoot)
if not regen_infodirs:
print " "+green("*")+" GNU info directory index is up-to-date."
if not os.path.isdir(inforoot):
continue
errmsg = ""
- for x in os.listdir(inforoot):
+ file_list = os.listdir(inforoot)
+ file_list.sort()
+ for x in file_list:
if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
continue
- myso=commands.getstatusoutput("LANG=C LANGUAGE=C install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
+ myso=commands.getstatusoutput("LANG=C LANGUAGE=C "+portage_const.EPREFIX+"/usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
existsstr="already exists, for file `"
if myso!="":
if re.search(existsstr,myso):
icount=icount+1
#update mtime so we can potentially avoid regenerating.
- portage.mtimedb["info"][inforoot]=os.stat(inforoot)[ST_MTIME]
+ prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
if badcount:
print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
print " "+green("*")+" Processed",icount,"info files."
-def post_emerge(retval=0):
- global myopts
+def post_emerge(settings, mtimedb, retval):
+ target_root = settings["ROOT"]
+ info_mtimes = mtimedb["info"]
+ config_protect = settings.get("CONFIG_PROTECT","").split()
+ infodirs = settings.get("INFOPATH","").split(":") + \
+ settings.get("INFODIR","").split(":")
+
os.chdir("/")
- if "--pretend" in myopts:
- sys.exit(retval)
- emergelog(" *** exiting successfully.")
+ emergelog("notitles" not in settings.features,
+ " *** exiting successfully.")
- if "noinfo" not in portage.settings.features:
- chk_updated_info_files(retval)
+ if "noinfo" not in settings.features:
+ chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
- chk_updated_cfg_files()
+ chk_updated_cfg_files(target_root, config_protect)
+ mtimedb.commit()
sys.exit(retval)
-def chk_updated_cfg_files():
- if portage.settings["CONFIG_PROTECT"]:
+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 string.split(portage.settings["CONFIG_PROTECT"]):
- x = portage_const.EPREFIX + x
- if os.path.isdir(x):
- a=commands.getstatusoutput("cd "+x+"; find . -iname '._cfg????_*'")
- if a[0]!=0:
- print " "+red("*")+" error scanning",x
- else:
- files=string.split(a[1])
- if files:
- procount=procount+1
- print " "+yellow("* IMPORTANT:")+"",len(files),"config files in",x,"need updating."
+ for x in config_protect:
+ x = os.path.join(target_root, x.lstrip(os.path.sep))
+ try:
+ mymode = os.lstat(x).st_mode
+ except OSError:
+ continue
+ if stat.S_ISDIR(mymode):
+ mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
+ else:
+ mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
+ os.path.split(x.rstrip(os.path.sep))
+ a = commands.getstatusoutput(mycommand)
+ if a[0] != 0:
+ print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
+ else:
+ files = a[1].split()
+ if files:
+ procount += 1
+ print colorize("WARN", " * IMPORTANT:"),
+ if stat.S_ISDIR(mymode):
+ print "%d config files in '%s' need updating." % \
+ (len(files), x)
+ else:
+ print "config file '%s' needs updating." % x
+
if procount:
#print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
testatom = x
return portage.isvalidatom(testatom)
-# general options that should be taken into account before any action
-if "--debug" in myopts:
- edebug=1
+def validate_merge_list(trees, mergelist):
+ """Validate the list to make sure all the packages are still available.
+ This is needed for --resume."""
+ for (pkg_type, myroot, pkg_key, action) in mergelist:
+ if pkg_type == "binary" and \
+ not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
+ pkg_type == "ebuild" and \
+ not trees[myroot]["porttree"].dbapi.xmatch(
+ "match-all", "="+pkg_key):
+ print red("!!! Error: The resume list contains packages that are no longer")
+ print red("!!! available to be emerged. Please restart/continue")
+ print red("!!! the merge operation manually.")
+ sys.exit(1)
-if myaction in ["sync","metadata"] and (not "--help" in myopts):
- if "--pretend" in myopts:
- print "emerge: \"sync\" actions do not support \"--pretend.\""
- sys.exit(1)
+def show_blocker_docs_link():
+ print
+ print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
+ print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
+ print
+ print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
+ print
- emergelog(" === "+str(myaction))
- myportdir=portage.settings["PORTDIR"]
+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=string.rstrip(portage.settings["SYNC"])
+ syncuri=string.rstrip(settings["SYNC"])
os.umask(0022)
if myaction == "metadata":
- if "--ask" in myopts:
- if userquery("Are you sure?") == "No":
- sys.exit(1)
print "skipping sync"
updatecache_flg = True
tmpservertimestampfile = None
rsync_opts = []
- if portage.settings["PORTAGE_RSYNC_OPTS"] == "":
+ if settings["PORTAGE_RSYNC_OPTS"] == "":
portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
rsync_opts.extend([
"--recursive", # Recurse directories
# The below validation is not needed when using the above hardcoded
# defaults.
- portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n")
- rsync_opts.extend(portage.settings["PORTAGE_RSYNC_OPTS"].split())
+ portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
+ rsync_opts.extend(settings["PORTAGE_RSYNC_OPTS"].split())
for opt in ("--recursive", "--times"):
if opt not in rsync_opts:
rsync_opts.append(opt)
for exclude in ("distfiles", "local", "packages"):
- opt = "--exclude='/%s'" % exclude
+ 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 (override with --exclude='!')\n")
+ "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
rsync_opts.append(opt)
- if portage.settings["RSYNC_TIMEOUT"] != "":
+ if settings["RSYNC_TIMEOUT"] != "":
portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
"use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
try:
- mytimeout = int(portage.settings["RSYNC_TIMEOUT"])
+ mytimeout = int(settings["RSYNC_TIMEOUT"])
rsync_opts.append("--timeout=%d" % mytimeout)
except ValueError, e:
portage.writemsg("!!! %s\n" % str(e))
if "--quiet" in myopts:
rsync_opts.append("--quiet") # Shut up a lot
else:
- rsync_opts.append("--progress") # Progress meter for each file
+ rsync_opts.append("--verbose") # Print filelist
if "--verbose" in myopts:
- rsync_opts.append("--verbose") # More noise? Not really sure what
+ rsync_opts.append("--progress") # Progress meter for each file
if "--debug" in myopts:
rsync_opts.append("--checksum") # Force checksum on all files
- if portage.settings["RSYNC_EXCLUDEFROM"] != "":
+ 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(portage.settings["RSYNC_EXCLUDEFROM"]):
+ if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
rsync_opts.append("--exclude-from=%s" % \
- portage.settings["RSYNC_EXCLUDEFROM"])
+ settings["RSYNC_EXCLUDEFROM"])
else:
portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
" but file does not exist.\n")
- if portage.settings["RSYNC_RATELIMIT"] != "":
+ 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" % \
- portage.settings["RSYNC_RATELIMIT"])
+ settings["RSYNC_RATELIMIT"])
- servertimestampdir = portage.settings.depcachedir+"/"
- servertimestampfile = portage.settings.depcachedir+"/timestamp.chk"
- tmpservertimestampdir = portage.settings["PORTAGE_TMPDIR"]+"/"
- tmpservertimestampfile = portage.settings["PORTAGE_TMPDIR"]+"/timestamp.chk"
+ servertimestampdir = settings.depcachedir+"/"
+ servertimestampfile = settings.depcachedir+"/timestamp.chk"
+ tmpservertimestampdir = settings["PORTAGE_TMPDIR"]+"/"
+ tmpservertimestampfile = settings["PORTAGE_TMPDIR"]+"/timestamp.chk"
# We only use the backup if a timestamp exists in the portdir.
content=None
#exitcode=0
try:
- if portage.settings.has_key("RSYNC_RETRIES"):
+ if settings.has_key("RSYNC_RETRIES"):
print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
- maxretries=int(portage.settings["RSYNC_RETRIES"])
+ maxretries=int(settings["RSYNC_RETRIES"])
else:
- maxretries=int(portage.settings["PORTAGE_RSYNC_RETRIES"])
+ maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
except SystemExit, e:
raise # Needed else can't exit
except:
maxretries=3 #default number of retries
retries=0
- hostname, port=re.split("rsync://([^:/]*)(:[0-9]+)?", syncuri)[1:3];
- if port==None:
+ user_name, hostname, port = re.split(
+ "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
+ if port is None:
port=""
+ if user_name is None:
+ user_name=""
updatecache_flg=True
-
+ all_rsync_opts = set(rsync_opts)
+ all_rsync_opts.update(
+ settings.get("PORTAGE_RSYNC_EXTRA_OPTS","").split())
+ family = socket.AF_UNSPEC
+ if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
+ family = socket.AF_INET
+ elif socket.has_ipv6 and \
+ ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
+ family = socket.AF_INET6
ips=[]
while (1):
if ips:
del ips[0]
if ips==[]:
try:
- ips=socket.gethostbyname_ex(hostname)[2]
+ 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])
except SystemExit, e:
raise # Needed else can't exit
except Exception, e:
if ips:
try:
- dosyncuri=string.replace(syncuri, "//"+hostname+port+"/", "//"+ips[0]+port+"/", 1)
+ 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 "Quitting."
print
sys.exit(0)
- emergelog(">>> Starting rsync with "+dosyncuri)
+ emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
if "--quiet" not in myopts:
print ">>> Starting rsync with "+dosyncuri+"..."
else:
- emergelog(">>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri))
+ 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 "--quiet" not in myopts:
print ">>> Checking server timestamp ..."
- rsynccommand = " ".join([portage_const.EPREFIX+"/usr/bin/rsync",
- portage.settings["PORTAGE_RSYNC_EXTRA_OPTS"],
- " ".join(rsync_opts)])
+ rsynccommand = " ".join([portage_const.EPREFIX, "/usr/bin/rsync", " ".join(rsync_opts),
+ settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")])
if "--debug" in myopts:
print rsynccommand
mycommand = " ".join([rsynccommand,
dosyncuri + "/metadata/timestamp.chk",
tmpservertimestampdir])
- exitcode=portage.spawn(mycommand,portage.settings,free=1)
+ exitcode=portage.spawn(mycommand,settings,free=1)
if (exitcode==0):
try:
servertimestamp = time.mktime(time.strptime(portage.grabfile(tmpservertimestampfile)[0], "%a, %d %b %Y %H:%M:%S +0000"))
servertimestamp = 0
if (servertimestamp != 0) and (servertimestamp == mytimestamp):
- emergelog(">>> Cancelling sync -- Already current.")
+ emergelog(xterm_titles,
+ ">>> Cancelling sync -- Already current.")
print
print ">>>"
print ">>> Timestamps on the server and in the local repository are the same."
print
sys.exit(0)
elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
- emergelog(">>> Server out of date: %s" % dosyncuri)
+ emergelog(xterm_titles,
+ ">>> Server out of date: %s" % dosyncuri)
print
print ">>>"
print ">>> SERVER OUT OF DATE: %s" % dosyncuri
elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
# actual sync
mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir
- exitcode=portage.spawn(mycommand,portage.settings,free=1)
+ exitcode=portage.spawn(mycommand,settings,free=1)
if exitcode in [0,1,2,3,4,11,14,20,21]:
break
elif exitcode in [0,1,2,3,4,11,14,20,21]:
break
if (exitcode==0):
- emergelog("=== Sync completed with %s" % dosyncuri)
+ emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
+ # save timestamp.chk for next timestamp check.
+ try:
+ if tmpservertimestampfile is not None:
+ portage.movefile(tmpservertimestampfile,
+ servertimestampfile, mysettings=settings)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ portage.writemsg("!!! Failed to save current timestamp.\n",
+ noiselevel=-1)
+ portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
+ del e
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="+portage.settings["SYNC"])
+ 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="+portage.settings["PORTDIR"])
+ print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
elif exitcode==20:
print darkred("!!!")+green(" Rsync was killed before it finished.")
else:
print
sys.exit(exitcode)
elif syncuri[:6]=="cvs://":
- if not os.path.exists("cvs"):
+ if not os.path.exists(portage_const.EPREFIX+"/usr/bin/cvs"):
print "!!! cvs does not exist, so CVS support is disabled."
print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
sys.exit(1)
if not os.path.exists(myportdir+"/CVS"):
#initial checkout
print ">>> Starting initial cvs checkout with "+syncuri+"..."
- if not portage.spawn("cd "+cvsdir+"; cvs -d "+cvsroot+" login",portage.settings,free=1):
- print "!!! cvs login error; exiting."
- sys.exit(1)
if os.path.exists(cvsdir+"/gentoo-x86"):
print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
sys.exit(1)
- if not portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",portage.settings,free=1):
+ if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
print "!!! cvs checkout error; exiting."
sys.exit(1)
if cvsdir!=myportdir:
- portage.movefile(cvsdir,portage.settings["PORTDIR"])
+ portage.movefile(cvsdir,settings["PORTDIR"])
sys.exit(0)
else:
#cvs update
print ">>> Starting cvs update with "+syncuri+"..."
- sys.exit(portage.spawn("cd "+myportdir+"; cvs -z0 -q update -dP",portage.settings,free=1))
+ sys.exit(portage.spawn("cd "+myportdir+"; cvs -z0 -q update -dP",settings,free=1))
else:
print "!!! rsync setting: ",syncuri,"not recognized; exiting."
sys.exit(1)
- try: # Prevent users from affecting ebuild.sh.
- os.close(sys.stdin.fileno())
- except SystemExit, e:
- raise # Needed else can't exit
- except:
- pass
-
if updatecache_flg and \
myaction != "metadata" and \
- "metadata-transfer" not in portage.settings.features:
+ "metadata-transfer" not in settings.features:
updatecache_flg = False
- if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
- if "--quiet" not in myopts:
- print "\n>>> Updating Portage cache: ",
- os.umask(0002)
- cachedir = os.path.normpath(portage.settings.depcachedir)
- if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
- "/lib", "/opt", "/proc", "/root", "/sbin",
- "/sys", "/tmp", "/usr", "/var"]:
- print "!!! PORTAGE_CACHEDIR IS SET TO A PRIMARY ROOT DIRECTORY ON YOUR SYSTEM."
- print "!!! This is ALMOST CERTAINLY NOT what you want: "+str(cachedir)
- sys.exit(73)
- if not os.path.exists(cachedir):
- os.mkdir(cachedir)
-
- # Potentially bad
- #if os.path.exists(cachedir+"/"+myportdir):
- # portage.spawn("rm -Rf "+cachedir+"/"+myportdir+"/*",portage.settings,free=1)
-
- # save timestamp.chk for next timestamp check.
- try:
- if tmpservertimestampfile != None:
- portage.movefile(tmpservertimestampfile, servertimestampfile)
- except SystemExit, e:
- raise # Needed else can't exit
- except Exception, e:
- print "!!! Failed to save current timestamp."
- print "!!!",e
-
- portage.portdb.flush_cache()
-
- ec = portage.eclass_cache.cache(portage.portdb.porttree_root)
- # kinda ugly.
- # XXX: nuke the filter when mr UNUSED_0? keys are dead
- cm = portage.settings.load_best_module("portdbapi.metadbmodule")(myportdir, "metadata/cache",
- filter(lambda x: not x.startswith("UNUSED_0"), portage.auxdbkeys))
-
- # we don't make overlay trees cache here, plus we don't trust portage.settings.categories
- porttree_root = portage.portdb.porttree_root
- conf = portage.config(config_profile_path=portage.settings.profile_path[:], \
- config_incrementals=portage.settings.incrementals[:])
-
- conf["PORTDIR_OVERLAY"] = ''
- conf.categories = portage.grabfile(os.path.join(porttree_root, "profiles", "categories"))
- try:
- i = conf.categories.index("virtual")
- if i != -1:
- conf.categories.remove(i)
- except (ValueError, IndexError):
- pass
-
- pdb = portage.portdbapi(porttree_root, conf)
-
- cp_all_list = pdb.cp_all()
- import cache.util
-
- class percentage_noise_maker(cache.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()
-
+ # Reload the whole config from scratch.
+ settings, trees, mtimedb = load_emerge_config(trees=trees)
+ portdb = trees[settings["ROOT"]]["porttree"].dbapi
- if "--quiet" in myopts:
- def quicky_cpv_generator(cp_all_list):
- for x in cp_all_list:
- for y in pdb.cp_list(x):
- yield y
- source = quicky_cpv_generator(pdb.cp_all())
- noise_maker = cache.util.quiet_mirroring()
- else:
- noise_maker = source = percentage_noise_maker(pdb)
- cache.util.mirror_cache(source, cm, pdb.auxdb[porttree_root], eclass_cache=ec, verbose_instance=noise_maker)
+ if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
+ action_metadata(settings, portdb, myopts)
- sys.stdout.flush()
+ portage.global_updates(
+ settings, trees, mtimedb["updates"])
+ mtimedb.commit()
+ # Reload the whole config from scratch.
+ settings, trees, mtimedb = load_emerge_config(trees=trees)
+ portdb = trees[settings["ROOT"]]["porttree"].dbapi
- portage.portageexit()
- reload(portage)
- mybestpv=portage.portdb.xmatch("bestmatch-visible","sys-apps/portage")
- mypvs=portage.best(portage.db[portage.root]["vartree"].dbapi.match("sys-apps/portage"))
+ mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
+ mypvs = portage.best(
+ trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
- chk_updated_cfg_files()
+ 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):
try:
- portage.spawn(portage.USER_CONFIG_PATH + "/bin/post_sync " + dosyncuri, portage.settings, free=1)
+ portage.spawn(portage.USER_CONFIG_PATH + "/bin/post_sync " + dosyncuri, settings, free=1)
except:
print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
print red(" * ")+"that you update portage now, before any other packages are updated."
print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
print red(" * ")+"configuration files."
+ print red(" * ")+"To update portage, run 'emerge portage'."
print
-elif myaction=="regen":
- emergelog(" === regen")
+
+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[:])
+
+ import cache.util
+
+ class percentage_noise_maker(cache.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 = cache.util.quiet_mirroring()
+ else:
+ noise_maker = source = percentage_noise_maker(portdb)
+ 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:
except:
pass
sys.stdout.flush()
- mynodes=portage.portdb.cp_all()
+ mynodes = portdb.cp_all()
for x in mynodes:
- mymatches=portage.portdb.xmatch("match-all",x)
- if not "--quiet" in myopts:
- print "processing",x
+ mymatches = portdb.xmatch("match-all",x)
+ portage.writemsg_stdout("processing %s\n" % x)
for y in mymatches:
try:
- foo=portage.portdb.aux_get(y,["DEPEND"])
+ 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)}
print "done!"
-# HELP action
-elif "config"==myaction:
+
+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])
+ 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
- pkgs = portage.db[portage.root]["vartree"].dbapi.match(myfiles[0])
+ 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)
else:
print "Configuring pkg..."
print
- ebuildpath = portage.db[portage.root]["vartree"].dbapi.findname(pkg)
- mysettings = portage.config(clone=portage.settings)
- portage.doebuild(ebuildpath,"config",portage.root,mysettings,debug=("--debug" in myopts),cleanup=True,tree="vartree")
+ 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
-# INFO action
-elif "info"==myaction:
+def action_info(settings, trees, myopts, myfiles):
unameout=commands.getstatusoutput("uname -mrp")[1]
- print getportageversion()
- print "================================================================="
+ 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
- if os.path.exists(portage_const.EPREFIX+"/etc/gentoo-release"):
- os.system("cat "+portage_const.EPREFIX+"/etc/gentoo-release")
+ gentoo_release = portage.grabfile(os.path.join(
+ settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
+ if gentoo_release:
+ print gentoo_release[0]
else:
print "Unknown Host Operating System"
+ lastSync = portage.grabfile(os.path.join(
+ settings["PORTDIR"], "metadata", "timestamp.chk"))
+ print "Last Sync:",
+ if lastSync:
+ print lastSync[0]
+ else:
+ print "Unknown"
output=commands.getstatusoutput("distcc --version")
if not output[0]:
print str(string.split(output[1],"\n",1)[0]),
- if "distcc" in portage.features:
+ if "distcc" in settings.features:
print "[enabled]"
else:
print "[disabled]"
output=commands.getstatusoutput("ccache -V")
if not output[0]:
print str(string.split(output[1],"\n",1)[0]),
- if "ccache" in portage.features:
+ 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/odcctools" ,"sys-devel/libtool", "dev-lang/python"]
- myvars += portage_util.grabfile(portage.settings["PORTDIR"]+"/profiles/info_pkgs")
+ "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 = portage.db["/"]["vartree"].dbapi.match(x)
+ pkg_matches = trees["/"]["vartree"].dbapi.match(x)
pkgs = []
for y in pkg_matches:
mycpv = portage.catpkgsplit(y)
else:
print "%-20s %s" % (x+":", "[NOT VALID]")
- libtool_vers = string.join(portage.db["/"]["vartree"].dbapi.match("sys-devel/libtool"), ",")
+ libtool_vers = string.join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"), ",")
if "--verbose" in myopts:
- myvars=portage.settings.keys()
+ myvars=settings.keys()
else:
- myvars = ['DEFAULT_PATH', 'GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
+ myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
- 'PORTDIR_OVERLAY', 'PREFIX', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
+ 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
- myvars.extend(portage_util.grabfile(portage.settings["PORTDIR"]+"/profiles/info_vars"))
+ 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 portage.settings.has_key(x):
- print x+'="'+portage.settings[x]+'"'
+ if settings.has_key(x):
+ print x+'="'+settings[x]+'"'
else:
unset_vars.append(x)
if unset_vars:
if "cvs_id_string" in dir(module):
print "%s: %s" % (str(x), str(module.cvs_id_string))
-# SEARCH action
-elif "search"==myaction:
+ # See if we can find any packages installed matching the strings
+ # passed on the command line
+ mypkgs = []
+ vardb = trees[settings["ROOT"]]["vartree"].dbapi
+ for x in myfiles:
+ mypkgs.extend(vardb.match(x))
+
+ # If some packages were found...
+ if mypkgs:
+ # Get our global settings (we only print stuff if it varies from
+ # the current config)
+ mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
+ auxkeys = mydesiredvars + [ "USE", "IUSE"]
+ global_vals = {}
+ pkgsettings = portage.config(clone=settings)
+
+ for myvar in mydesiredvars:
+ global_vals[myvar] = set(settings.get(myvar, "").split())
+
+ # Loop through each package
+ # Only print settings if they differ from global settings
+ header_printed = False
+ for pkg in mypkgs:
+ # Get all package specific variables
+ auxvalues = vardb.aux_get(pkg, auxkeys)
+ valuesmap = {}
+ for i in xrange(len(auxkeys)):
+ valuesmap[auxkeys[i]] = set(auxvalues[i].split())
+ diff_values = {}
+ for myvar in mydesiredvars:
+ # If the package variable doesn't match the
+ # current global variable, something has changed
+ # so set diff_found so we know to print
+ if valuesmap[myvar] != global_vals[myvar]:
+ diff_values[myvar] = valuesmap[myvar]
+ valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
+ pkgsettings.reset()
+ pkgsettings.setcpv(pkg)
+ if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
+ valuesmap["USE"]:
+ diff_values["USE"] = valuesmap["USE"]
+ # If a difference was found, print the info for
+ # this package.
+ if diff_values:
+
+ # If we have not yet printed the header,
+ # print it now
+ if not header_printed:
+ header_title = "Package Settings"
+ print header_width * "="
+ print header_title.rjust(int(header_width/2 + len(header_title)/2))
+ print header_width * "="
+ header_printed = True
+
+ # Print package info
+ print "%s was built with the following:" % pkg
+ for myvar in mydesiredvars + ["USE"]:
+ if myvar in diff_values:
+ mylist = list(diff_values[myvar])
+ mylist.sort()
+ print "%s=\"%s\"" % (myvar, " ".join(mylist))
+ print
+
+def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
if not myfiles:
print "emerge: no search terms provided."
else:
- searchinstance = search()
+ searchinstance = search(settings, portdb,
+ vartree, spinner, "--searchdesc" in myopts,
+ "--quiet" not in myopts)
for mysearch in myfiles:
try:
searchinstance.execute(mysearch)
print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
sys.exit(1)
searchinstance.output()
-elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
- if 1==unmerge(myaction, myfiles):
- post_emerge()
-elif "depclean"==myaction:
+def action_depclean(settings, trees, ldpath_mtimes,
+ myopts, spinner):
# Kill packages that aren't explicitly merged or are required as a
# dependency of another package. World file is explicit.
+ warn_prefix = colorize("BAD", "*** WARNING *** ")
print
- print red("*** WARNING ***")+" --depclean is known to be broken. It is highly recommended"
- print red("*** WARNING ***")+" that "+green("`emerge --update --newuse --deep world`")+" be ran before"
- print red("*** WARNING ***")+" commencing. However, using --depclean may still break link"
- print red("*** WARNING ***")+" level consistency within your system. "+green("`revdep-rebuild`")
- print red("*** WARNING ***")+" from app-portage/gentoolkit can help to detect breakage."
- print red("*** WARNING ***")
- print red("*** WARNING ***")+" Also study the list of packages to be cleaned for any"
- print red("*** WARNING ***")+" obvious mistakes. Packages can be manually added to the"
- print red("*** WARNING ***")+" world list by running "+green("`emerge --noreplace <atom>`")+"."
- print red("*** WARNING ***")
- print red("*** WARNING ***")+" "+bold("Make sure you have a backup.")
-
- syslist=getlist("system")
- worldlist=getlist("world")
- myvarlist=portage.vardbapi(portage.root).cp_all()
+ print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
+ print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
+ print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
+ print warn_prefix
+ print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
+ print warn_prefix + "mistakes. Packages that are part of the world set will always"
+ print warn_prefix + "be kept. They can be manually added to this set with"
+ print warn_prefix + good("`emerge --noreplace <atom>`") + "."
+ print warn_prefix
+ print warn_prefix + "As a safety measure, depclean will not remove any packages"
+ print warn_prefix + "unless *all* required dependencies have been resolved. As a"
+ print warn_prefix + "consequence, it is often necessary to run "
+ print warn_prefix + good("`emerge --update --deep world`") + " prior to depclean."
+
+ xterm_titles = "notitles" not in settings.features
+ portdb = trees[settings["ROOT"]]["porttree"].dbapi
+ vartree = trees[settings["ROOT"]]["vartree"]
+ vardb = vartree.dbapi
+ syslist = getlist(settings, "system")
+ worldlist = getlist(settings, "world")
+ fakedb = portage.fakedbapi(settings=settings)
+ emptydb = portage.fakedbapi(settings=settings)
+ myvarlist = vardb.cpv_all()
if not syslist:
print "\n!!! You have no system list.",
print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
if not (syslist and worldlist and myvarlist):
- print "\n!!! Proceeding will break your installation.\n"
- countdown(EMERGE_WARNING_DELAY, ">>> Depclean")
+ print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
+ print " break your installation.\n"
+ if "--pretend" not in myopts:
+ countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
- emergelog(" >>> depclean")
-
- mydepgraph=depgraph(myaction,myopts)
+ emergelog(xterm_titles, " >>> depclean")
- if not ("--quiet" in myopts):
+ if "--quiet" not in myopts:
print "\nCalculating dependencies ",
- if not mydepgraph.xcreate("world"):
- print "\n!!! Failed to create deptree."
- sys.exit(1)
- if not ("--quiet" in myopts):
- print "\b\b... done!"
-
- if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
- sys.stderr.write(red("The following binaries are not available for merging...\n"))
- for x in mydepgraph.missingbins:
- sys.stderr.write(" "+str(x)+"\n")
- sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
- sys.exit(1)
-
- alldeps=mydepgraph.digraph.allnodes()
-
- if not alldeps:
- print "!!! You have no dependencies. Impossible. Bug."
- sys.exit(1)
- reallist=[]
- for x in alldeps:
- myparts=portage.catpkgsplit(string.split(x)[2])
- if not myparts:
- sys.stderr.write(
- red("!!! There appears to be a problem with the following package:\n")+
- red("!!! "+str(string.split(x)[2])+"\n\n")+
- "!!! Please ensure that blocking/conflicting packages are not merged."+
- "!!! 'emerge -p "+str(string.split(x)[2])+"\n\n")
- if ("--pretend" not in myopts) and ("--ask" not in myopts):
- countdown(EMERGE_WARNING_DELAY, "*** Continuing")
+ remaining_atoms = [(atom, 'world') for atom in worldlist if vardb.match(atom)]
+ remaining_atoms += [(atom, 'system') for atom in syslist if vardb.match(atom)]
+ unresolveable = {}
+
+ while remaining_atoms:
+ atom, parent = remaining_atoms.pop()
+ pkgs = vardb.match(atom)
+ if not pkgs:
+ if not atom.startswith("!"):
+ if atom in unresolveable:
+ unresolveable[atom].append(parent)
+ else:
+ unresolveable[atom] = [parent]
continue
+ # Could put slot checking here to ensure that there aren't two
+ # packages with the same slot...
+ for pkg in pkgs:
+ if fakedb.cpv_exists(pkg):
+ continue
+ spinner.update()
+ fakedb.cpv_inject(pkg)
+ mydb = portdb.xmatch("match-visible", "="+pkg) and portdb or vardb
+ if myopts.get("--with-bdeps", "y") == "y":
+ depstr = " ".join(mydb.aux_get(pkg,
+ ["DEPEND", "RDEPEND", "PDEPEND"]))
+ else:
+ depstr = " ".join(mydb.aux_get(pkg,
+ ["RDEPEND", "PDEPEND"]))
+ usedef = vardb.aux_get(pkg, ["USE"])[0].split()
+ success, atoms = portage.dep_check(depstr, emptydb, settings,
+ myuse=usedef, trees=trees, myroot=settings["ROOT"])
+ if not success:
+ print "\n\n"
+ print "Error occurred while processing",pkg
+ print str(atoms)
+ return
+ for atom in atoms:
+ remaining_atoms.append((atom, pkg))
+
+ if "--quiet" not in myopts:
+ print "\b\b... done!\n"
+
+ if unresolveable:
+ print "Dependencies could not be completely resolved due to"
+ print "the following required packages not being installed:"
+ print
+ for atom in unresolveable:
+ print atom, "required by", " ".join(unresolveable[atom])
+ print
+ print "Have you forgotten to run " + good("`emerge --update --deep world`") + " prior to depclean?"
+ print
+ return
- catpack=myparts[0]+"/"+myparts[1]
- if catpack not in reallist:
- reallist.append(catpack)
-
- cleanlist=[]
- for x in myvarlist:
- if x not in reallist:
- if x not in cleanlist:
- cleanlist.append(x)
-
- for x in syslist+worldlist:
- myparts = portage.catpkgsplit(x)
- if myparts:
- if myparts[0][0] in ('<','>','='):
- myparts[0] = myparts[0][1:]
- if myparts[0][0] in ('<','>','='):
- myparts[0] = myparts[0][1:]
- catpack=myparts[0]+"/"+myparts[1]
- else:
- catpack=x
- if catpack in cleanlist:
- cleanlist.remove(catpack)
-
- #print "\n\n\nCleaning: "
- #for x in cleanlist:
- # print x
- #print
+ cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
if len(cleanlist):
- unmerge("unmerge", cleanlist)
+ unmerge(settings, myopts, vartree, "unmerge", cleanlist, ldpath_mtimes)
- print
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(reallist))
- print "Required packages: "+str(len(alldeps))
+ 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))
- post_emerge()
-# "update", "system", or just process files:
-else:
+def action_build(settings, trees, mtimedb,
+ myopts, myaction, myfiles, spinner):
+ ldpath_mtimes = mtimedb["ldpath"]
favorites=[]
- syslist=getlist("system")
if ("--ask" in myopts or "--pretend" in myopts) and not "--quiet" in myopts:
action = ""
if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
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 portage.mtimedb or
- "resume_backup" in portage.mtimedb):
- if "resume" not in portage.mtimedb:
- portage.mtimedb["resume"] = portage.mtimedb["resume_backup"]
- del portage.mtimedb["resume_backup"]
- portage.commit_mtimedb()
- myresumeopts=portage.mtimedb["resume"]["myopts"][:]
+ ("resume" in mtimedb or
+ "resume_backup" in mtimedb):
+ if "resume" not in mtimedb:
+ mtimedb["resume"] = mtimedb["resume_backup"]
+ del mtimedb["resume_backup"]
+ mtimedb.commit()
+ # XXX: "myopts" is a list for backward compatibility.
+ myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
for opt in ("--skipfirst", "--ask", "--tree"):
- while opt in myresumeopts:
- myresumeopts.remove(opt)
+ myresumeopts.pop(opt, None)
- for myopt in myopts:
+ for myopt, myarg in myopts.iteritems():
if myopt not in myresumeopts:
- myresumeopts.append(myopt)
+ myresumeopts[myopt] = myarg
myopts=myresumeopts
- mydepgraph=depgraph("resume",myopts)
- if "--resume" not in myopts:
- myopts+=["--resume"]
+ myparams = create_depgraph_params(myopts, myaction)
+ mydepgraph = depgraph(settings, trees,
+ myopts, myparams, spinner)
else:
if ("--resume" in myopts):
- del myopts[myopts.index("--resume")]
print darkgreen("emerge: It seems we have nothing to resume...")
sys.exit(0)
- mydepgraph=depgraph(myaction,myopts)
+ myparams = create_depgraph_params(myopts, myaction)
+ mydepgraph = depgraph(settings, trees,
+ myopts, myparams, spinner)
if myaction in ["system","world"]:
if not ("--quiet" in myopts):
print "Calculating",myaction,"dependencies ",
if not ("--quiet" in myopts):
print "\b\b... done!"
else:
- if not myfiles:
- print "emerge: please tell me what to do."
- help()
- sys.exit(1)
- #we don't have any files to process; skip this step and exit
if not ("--quiet" in myopts):
print "Calculating dependencies ",
sys.stdout.flush()
- retval,favorites=mydepgraph.select_files(myfiles)
+ try:
+ retval, favorites = mydepgraph.select_files(myfiles)
+ except portage_exception.PackageNotFound, e:
+ portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
+ sys.exit(1)
if not retval:
sys.exit(1)
if not ("--quiet" in myopts):
if "--ask" in myopts:
if "--resume" in myopts:
- mydepgraph.display(portage.mtimedb["resume"]["mergelist"])
- prompt="Do you want me to resume merging these packages?"
+ validate_merge_list(trees, mtimedb["resume"]["mergelist"])
+ mymergelist = mtimedb["resume"]["mergelist"]
+ if "--skipfirst" in myopts:
+ mymergelist = mymergelist[1:]
+ if len(mymergelist) == 0:
+ print colorize("INFORM", "emerge: It seems we have nothing to resume...")
+ sys.exit(0)
+ mydepgraph.display(mymergelist)
+ prompt="Would you like to resume merging these packages?"
else:
- mydepgraph.display(mydepgraph.altlist())
+ mydepgraph.display(
+ mydepgraph.altlist(reversed=("--tree" in myopts)))
mergecount=0
for x in mydepgraph.altlist():
- if x[3]!="nomerge":
+ 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."
- print
+ if "--quiet" not in myopts:
+ show_blocker_docs_link()
sys.exit(1)
if mergecount==0:
- if portage.settings["AUTOCLEAN"] and "yes"==portage.settings["AUTOCLEAN"]:
- prompt="Nothing to merge; do you want me to auto-clean packages?"
+ if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
+ prompt="Nothing to merge; would you like to auto-clean packages?"
else:
print
print "Nothing to merge; quitting."
print
sys.exit(0)
elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
- prompt="Do you want me to fetch the source files for these packages?"
+ prompt="Would you like to fetch the source files for these packages?"
else:
- prompt="Do you want me to merge these packages?"
+ prompt="Would you like to merge these packages?"
print
if userquery(prompt)=="No":
print
print
sys.exit(0)
# Don't ask again (e.g. when auto-cleaning packages after merge)
- myopts.remove("--ask")
+ del myopts["--ask"]
if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
if ("--resume" in myopts):
- mydepgraph.display(portage.mtimedb["resume"]["mergelist"])
+ validate_merge_list(trees, mtimedb["resume"]["mergelist"])
+ mymergelist = mtimedb["resume"]["mergelist"]
+ if "--skipfirst" in myopts:
+ mymergelist = mymergelist[1:]
+ if len(mymergelist) == 0:
+ print colorize("INFORM", "emerge: It seems we have nothing to resume...")
+ sys.exit(0)
+ mydepgraph.display(mymergelist)
else:
- mydepgraph.display(mydepgraph.altlist())
+ mydepgraph.display(
+ mydepgraph.altlist(reversed=("--tree" in myopts)))
else:
if ("--buildpkgonly" in myopts):
- if not mydepgraph.digraph.hasallzeros():
+ if not mydepgraph.digraph.hasallzeros(ignore_priority=digraph.MEDIUM):
print "\n!!! --buildpkgonly requires all dependencies to be merged."
print "!!! Cannot merge requested packages. Merge deps and try again.\n"
sys.exit(1)
if ("--resume" in myopts):
- favorites=portage.mtimedb["resume"]["favorites"]
- mydepgraph.merge(portage.mtimedb["resume"]["mergelist"])
+ 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
+ retval = mergetask.merge(
+ mtimedb["resume"]["mergelist"], favorites, mtimedb)
+ if retval != os.EX_OK:
+ sys.exit(retval)
else:
- if "resume" in portage.mtimedb and \
- "mergelist" in portage.mtimedb["resume"] and \
- len(portage.mtimedb["resume"]["mergelist"]) > 1:
- portage.mtimedb["resume_backup"] = portage.mtimedb["resume"]
- del portage.mtimedb["resume"]
- portage.commit_mtimedb()
- portage.mtimedb["resume"]={}
- portage.mtimedb["resume"]["myopts"]=myopts
- portage.mtimedb["resume"]["favorites"]=favorites
+ 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=portage.portdb.findname(pkgline[2])
- tmpsettings = portage.config(clone=portage.settings)
- retval=portage.doebuild(y,"digest",portage.root,tmpsettings,edebug,("--pretend" in myopts),tree="porttree")
+ 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():
pkglist.append(pkg)
else:
pkglist = mydepgraph.altlist()
- mydepgraph.merge(pkglist)
-
- if portage.mtimedb.has_key("resume"):
- del portage.mtimedb["resume"]
- if portage.settings["AUTOCLEAN"] and "yes"==portage.settings["AUTOCLEAN"]:
+ mergetask = MergeTask(settings, trees, myopts)
+ retval = mergetask.merge(pkglist, favorites, mtimedb)
+ if retval != os.EX_OK:
+ sys.exit(retval)
+
+ if mtimedb.has_key("resume"):
+ del mtimedb["resume"]
+ if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
print ">>> Auto-cleaning packages..."
- unmerge("clean", ["world"])
- post_emerge()
+ vartree = trees[settings["ROOT"]]["vartree"]
+ unmerge(settings, myopts, vartree, "clean", ["world"],
+ ldpath_mtimes)
+ else:
+ portage.writemsg_stdout(colorize("WARN", "WARNING:")
+ + " AUTOCLEAN is disabled. This can cause serious"
+ + " problems due to overlapping packages.\n")
+
+def multiple_actions(action1, action2):
+ sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
+ sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
+ sys.exit(1)
+
+def parse_opts(tmpcmdline):
+ myaction=None
+ myopts = {}
+ myfiles=[]
+
+ global actions, options, shortmapping
+
+ longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
+ argument_options = {
+ "--with-bdeps": {
+ "help":"include unnecessary build time dependencies",
+ "type":"choice",
+ "choices":("y", "n")
+ }
+ }
+
+ from optparse import OptionParser
+ parser = OptionParser()
+ if parser.has_option("--help"):
+ parser.remove_option("--help")
+
+ for action_opt in actions:
+ parser.add_option("--" + action_opt, action="store_true",
+ dest=action_opt.replace("-", "_"), default=False)
+ for myopt in options:
+ parser.add_option(myopt, action="store_true",
+ dest=myopt.lstrip("--").replace("-", "_"), default=False)
+ for shortopt, longopt in shortmapping.iteritems():
+ parser.add_option("-" + shortopt, action="store_true",
+ dest=longopt.lstrip("--").replace("-", "_"), default=False)
+ for myalias, myopt in longopt_aliases.iteritems():
+ parser.add_option(myalias, action="store_true",
+ dest=myopt.lstrip("--").replace("-", "_"), default=False)
+
+ for myopt, kwargs in argument_options.iteritems():
+ parser.add_option(myopt,
+ dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
+
+ myoptions, myargs = parser.parse_args(args=tmpcmdline)
+
+ for myopt in options:
+ v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
+ if v:
+ myopts[myopt] = True
+
+ for myopt in argument_options:
+ v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
+ if v is not None:
+ myopts[myopt] = v
+
+ for action_opt in actions:
+ v = getattr(myoptions, action_opt.replace("-", "_"))
+ if v:
+ if myaction:
+ multiple_actions(myaction, action_opt)
+ sys.exit(1)
+ myaction = action_opt
+
+ for x in myargs:
+ if x in actions:
+ if x not in ["system", "world"]:
+ print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
+ if myaction:
+ multiple_actions(myaction, x)
+ sys.exit(1)
+ myaction=x
+ else:
+ myfiles.append(x)
+
+ return myaction, myopts, myfiles
+
+def validate_ebuild_environment(trees):
+ for myroot in trees:
+ mysettings = trees[myroot]["vartree"].settings
+ if not mysettings.get("ARCH", None):
+ print >> sys.stderr, bad("\a!!! ARCH is not set... " + \
+ "Are you missing the '%setc/make.profile' symlink?" % \
+ mysettings["PORTAGE_CONFIGROOT"])
+ print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
+ "Is your portage tree complete?\n")
+ sys.exit(9)
+ del myroot, mysettings
+
+def load_emerge_config(trees=None):
+ kwargs = {}
+ for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
+ kwargs[k] = os.environ.get(envvar, "/")
+ 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")
+
+ # Set color output
+ if "--nocolor" in myopts:
+ settings["NOCOLOR"] = "true"
+ settings.backup_changes("NOCOLOR")
+
+def emerge_main():
+ # 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
+ portage.global_updates(settings, trees, mtimedb["updates"])
+ mtimedb.commit()
+ # Reload the whole config from scratch.
+ settings, trees, mtimedb = load_emerge_config(trees=trees)
+ portdb = trees[settings["ROOT"]]["porttree"].dbapi
+
+ ldpath_mtimes = mtimedb["ldpath"]
+ xterm_titles = "notitles" not in settings.features
+
+ if settings.get("NOCOLOR","").lower() in ("yes","true"):
+ nocolor()
+ elif (not sys.stdout.isatty()) and \
+ settings.get("NOCOLOR","").lower() != "no":
+ # revdep-rebuild exports NOCOLOR=false, so for now, don't allow
+ # NOCOLOR=false to override the isatty() check. This can be fixed
+ # in revdep-rebuild by using the --nocolor option when appropriate
+ # instead of exporting NOCOLOR.
+ nocolor()
+
+ tmpcmdline = []
+ if "--ignore-default-opts" not in tmpcmdline:
+ tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
+ tmpcmdline.extend(sys.argv[1:])
+ myaction, myopts, myfiles = parse_opts(tmpcmdline)
+
+ for myroot in trees:
+ mysettings = trees[myroot]["vartree"].settings
+ mysettings.unlock()
+ adjust_config(myopts, mysettings)
+ mysettings.lock()
+ del myroot, mysettings
+
+ spinner = stdout_spinner()
+ if "candy" in settings.features:
+ spinner.update = spinner.update_scroll
+
+ portage.deprecated_profile_check()
+
+ 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
+
+ #Freeze the portdbapi for enhanced performance:
+ for myroot in trees:
+ trees[myroot]["porttree"].dbapi.freeze()
+ del myroot
+
+ if "moo" in myfiles:
+ print """
+
+ Larry loves Gentoo (""" + os.uname()[0] + """)
+
+ _______________________
+< Have you mooed today? >
+ -----------------------
+ \ ^__^
+ \ (oo)\_______
+ (__)\ )\/\
+ ||----w |
+ || ||
+
+"""
+
+ if (myaction in ["world", "system"]) and myfiles:
+ print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
+ sys.exit(1)
+
+ for x in myfiles:
+ ext = os.path.splitext(x)[1]
+ if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
+ print "emerging by path implies --oneshot... adding --oneshot to options."
+ print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
+ break
+
+ if ("--tree" in myopts) and ("--columns" in myopts):
+ print "emerge: can't specify both of \"--tree\" and \"--columns\"."
+ sys.exit(1)
+
+ if ("--quiet" in myopts):
+ spinner.update = spinner.update_quiet
+ portage_util.noiselimit = -1
+
+ # Always create packages if FEATURES=buildpkg
+ # Imply --buildpkg if --buildpkgonly
+ if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
+ if "--buildpkg" not in myopts:
+ myopts["--buildpkg"] = True
+
+ # Also allow -S to invoke search action (-sS)
+ if ("--searchdesc" in myopts):
+ if myaction and myaction != "search":
+ myfiles.append(myaction)
+ if "--search" not in myopts:
+ myopts["--search"] = True
+ myaction = "search"
+
+ # Always try and fetch binary packages if FEATURES=getbinpkg
+ if ("getbinpkg" in settings.features):
+ myopts["--getbinpkg"] = True
+
+ if "--skipfirst" in myopts and "--resume" not in myopts:
+ myopts["--resume"] = True
+
+ if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
+ myopts["--usepkgonly"] = True
+
+ if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
+ myopts["--getbinpkg"] = True
+
+ if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
+ myopts["--usepkg"] = True
+
+ # Also allow -K to apply --usepkg/-k
+ if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
+ myopts["--usepkg"] = True
+
+ # Also allow -l to apply --pretend/-p, but if already in --ask mode
+ if ("--changelog" in myopts) and not (("--pretend" in myopts) or ("--ask" in myopts)):
+ print ">>> --changelog implies --pretend... adding --pretend to options."
+ myopts["--pretend"] = 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":
+ 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"]
+
+ # Set color output
+ if "--nocolor" in myopts or \
+ settings["NOCOLOR"] in ("yes","true"):
+ nocolor()
+
+ 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:
+ emergehelp.help(myaction, myopts, havecolor)
+ sys.exit(0)
+
+ if portage.wheelgid == portage.portage_gid:
+ print "emerge: wheel group use is being deprecated. Please update group and passwd to"
+ print " include the portage user as noted above, and then use group portage."
+
+ if "--debug" in myopts:
+ print "myaction", myaction
+ print "myopts", myopts
+
+ if not myaction and not myfiles and "--resume" not in myopts:
+ emergehelp.help(myaction, myopts, 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"):
+ if portage.secpass >= 1:
+ if "--fetchonly" not in myopts and \
+ "--fetch-all-uri" not in myopts and \
+ myaction not in ("metadata", "regen"):
+ print "emerge: root access required."
+ sys.exit(1)
+ else:
+ print "emerge: root access required."
+ sys.exit(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=string.join(myopts, " ")
+ if myaction:
+ myelogstr+=" "+myaction
+ if myfiles:
+ myelogstr+=" "+string.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 ["sync","metadata"] and "--help" not in myopts:
+ if "--pretend" in myopts:
+ print "emerge: \"sync\" actions do not support \"--pretend.\""
+ sys.exit(1)
+ if "sync" == myaction:
+ action_sync(settings, trees, mtimedb, myopts, myaction)
+ else:
+ action_metadata(settings, portdb, myopts)
+ elif myaction=="regen":
+ validate_ebuild_environment(trees)
+ action_regen(settings, portdb)
+ # HELP action
+ elif "config"==myaction:
+ if "--pretend" in myopts:
+ sys.stderr.write("emerge: The --config action " + \
+ "does not support --pretend.\n")
+ return 1
+ validate_ebuild_environment(trees)
+ action_config(settings, trees, myopts, myfiles)
+
+ # INFO action
+ elif "info"==myaction:
+ action_info(settings, trees, myopts, myfiles)
+
+ # SEARCH action
+ elif "search"==myaction:
+ validate_ebuild_environment(trees)
+ action_search(settings, portdb, trees["/"]["vartree"],
+ myopts, myfiles, spinner)
+ elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
+ validate_ebuild_environment(trees)
+ vartree = trees[settings["ROOT"]]["vartree"]
+ if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
+ ldpath_mtimes, raise_on_missing=False):
+ if "--pretend" not in myopts:
+ post_emerge(settings, mtimedb, 0)
+
+ elif "depclean"==myaction:
+ validate_ebuild_environment(trees)
+ action_depclean(settings, trees, ldpath_mtimes,
+ myopts, spinner)
+ if "--pretend" not in myopts:
+ post_emerge(settings, mtimedb, 0)
+ # "update", "system", or just process files:
+ else:
+ validate_ebuild_environment(trees)
+ action_build(settings, trees, mtimedb,
+ myopts, myaction, myfiles, spinner)
+ if "--pretend" not in myopts:
+ post_emerge(settings, mtimedb, 0)
+
+if __name__ == "__main__":
+ retval = emerge_main()
+ sys.exit(retval)