#!/usr/bin/python -O # Copyright 1999-2003 Gentoo Technologies, Inc. # Distributed under the terms of the GNU General Public License v2 # $Header: /home/cvsroot/gentoo-src/portage/bin/emerge,v 1.264 2004/02/08 21:24:15 nakano Exp $ import os,sys os.environ["PORTAGE_CALLER"]="emerge" sys.path = ["/usr/lib/portage/pym"]+sys.path import emergehelp,xpak,string,re,commands,time,shutil,traceback,atexit,signal,socket,types from stat import * from output import * import portage if (not sys.stdout.isatty()) or (portage.settings["NOCOLOR"] in ["yes","true"]): nocolor() def normpath(mystr): if mystr and (mystr[0]=='/'): return os.path.normpath("///"+mystr) else: return os.path.normpath(mystr) def getch(): """Gets a single character from standard input. Does not echo to the screen.""" try: import msvcrt char = msvcrt.getch() except ImportError: import sys, tty, termios fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) char = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) return char def userchoice(choices): """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. choice: a List of Strings. choice_color: a Function taking and returning a String Returns the number of the response.""" for i in range(1, len(choices) + 1) : print green("\t[" + `i` + "] ") + red(choices[i - 1]) while 1: choice = getch() try: choice = int(choice) except ValueError: continue if choice > len(choices) : continue return choice - 1 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. prompt: a String. responses: a List of Strings. colours: a List of Functions taking and returning a String, used to process the responses for display. Typically these will be functions like red() but could be e.g. lambda x: "DisplayString". If responses is omitted, defaults to ["Yes, "No"], [green, red]. If only colours is omitted, defaults to [bold, ...]. Returns a member of the List responses. (If called without optional arguments, returns "Yes" or "No".) KeyboardInterrupt is converted to SystemExit to avoid tracebacks being printed.""" if responses is None: responses, colours = ["Yes", "No"], [green, red] elif colours is None: colours=[bold] colours=(colours*len(responses))[:len(responses)] print bold(prompt), try: while True: response=raw_input("["+string.join([colours[i](responses[i]) for i in range(len(responses))],"/")+"] ") for key in responses: if response.upper()==key[:len(response)].upper(): return key for key in responses: if response.upper()==key[:len(response)].upper(): return key print "Sorry, response '%s' not understood." % response, except KeyboardInterrupt: print "Interrupted." sys.exit(1) if portage.settings.has_key("PORTAGE_NICENESS"): try: os.nice(int(portage.settings["PORTAGE_NICENESS"])) except Exception,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')] spinner="\|/-\|/-" spinpos=0 #number of ebuilds merged merged=0 params=["selective", "deep", "self", "recurse", "empty"] actions=[ "clean", "config", "depclean", "help", "info", "inject", "metadata", "prune", "regen", "rsync", "search", "sync", "system", "unmerge", "world", ] options=[ "--ask", "--buildpkg", "--buildpkgonly", "--changelog", "--columns", "--debug", "--deep", "--digest", "--emptytree", "--fetchonly", "--getbinpkg", "--getbinpkgonly", "--help", "--noconfmem", "--nodeps", "--noreplace", "--nospinner", "--oneshot", "--onlydeps", "--pretend", "--quiet", "--resume", "--searchdesc", "--selective", "--skipfirst", "--tree", "--update", "--upgradeonly", "--usepkg", "--usepkgonly", "--verbose", "--version" ] shortmapping={ "a":"--ask", "b":"--buildpkg", "B":"--buildpkgonly", "c":"--clean", "C":"--unmerge", "d":"--debug", "D":"--deep", "e":"--emptytree", "f":"--fetchonly", "g":"--getbinpkg", "G":"--getbinpkgonly", "h":"--help", "i":"--inject", "k":"--usepkg", "K":"--usepkgonly", "l":"--changelog", "n":"--noreplace", "o":"--onlydeps", "O":"--nodeps", "p":"--pretend", "P":"--prune", "q":"--quiet", "s":"--search", "S":"--searchdesc", 't':"--tree", "u":"--update", "U":"--upgradeonly", "v":"--verbose", "V":"--version" } myaction=None myopts=[] myfiles=[] edebug=0 # process short actions and options tmpcmdline=sys.argv[1:] #tmpcmdline.extend(portage.settings["EMERGE_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 command arguments for x in cmdline: if not x: continue if len(x)>=2 and x[0:2]=="--": if x in options: myopts.append(x) elif x[2:] in actions: if x[2:]=="rsync": print print red("*** 'rsync' has been deprecated.") print red("*** Please use 'sync' instead.") x="--sync" 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 '"+x+"'") if x=="rsync": #print red("*** Please use '--sync' instead.") x="sync" #else: #print red("*** Please use '--"+x+"' instead.") if myaction: print print red("!!!")+green(" Multiple actions requested... Please choose one only.") #print red("!!! '")+darkgreen("--"+myaction)+"' "+red("or")+" '"+darkgreen("--"+x)+"'" 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 (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) if ("--tree" in myopts) and ("--columns" in myopts): print "emerge: can't specify both of \"--tree\" and \"--columns\"." sys.exit(1) # 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") # 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 ("--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") # Also allow -U to apply --update/-u if ("--upgradeonly" in myopts) and not ("--update" in myopts): print ">>> --upgradeonly implies --update... adding --update to options." myopts.append("--update") # Also allow -l to apply --pretend/-p if ("--changelog" in myopts) and not ("--pretend" 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.stdout.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() # Python will try to compile the python modules, so we should do # it outside of a sandbox first. tmpsettings = portage.config(clone=portage.settings) portage.spawn("/usr/lib/portage/bin/portageq pkgdir &> /dev/null", tmpsettings, free=1) def emergelog(mystr): if "notitles" not in portage.features: xtermTitle(mystr) try: mylogfile=open("/var/log/emerge.log", "a") mylogfile.write(str(time.time())[:10]+": "+mystr+"\n") mylogfile.flush() mylogfile.close() os.chmod("/var/log/emerge.log", S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) os.chown("/var/log/emerge.log", portage.portage_uid, portage.portage_gid) 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() atexit.register(emergeexit) def emergeexitsig(signum, frame): sys.exit(100+signum) signal.signal(signal.SIGINT, emergeexitsig) def countdown(secs=5, doing="Starting"): if secs: print ">>> Waiting",secs,"seconds before starting..." print ">>> (Control-C to abort)...\n"+doing+" in: ", ticks=range(secs) ticks.reverse() for sec in ticks: sys.stdout.write(red(str(sec+1)+" ")) sys.stdout.flush() time.sleep(1) print # formats a size given in bytes nicely def format_size(mysize): if type(mysize) != types.IntType: return mysize mystr=str(mysize/1024) mycount=len(mystr) while (mycount > 3): mycount-=3 mystr=mystr[:mycount]+","+mystr[mycount:] return mystr+" kB" def getgccversion(): """ 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 = '`which 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." ) gcc_distcc_broken_error = green( '!!! Using `which gcc` to gcc locate version, 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]" else: gccver = gcc_ver_prefix + gccout[1] return gccver if os.path.isfile(gcc_config_config): try: gccver = gcc_ver_prefix + open(gcc_config_config).read().strip().split('-')[-1] 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 gccver = fallback() return gccver def getportageversion(): try: profilever=os.path.basename(os.path.normpath(os.readlink("/etc/make.profile"))) except: profilever="unavailable" glibcver=[] for x in portage.vardbapi(portage.root).match("glibc"): xs=portage.pkgsplit(x) if glibcver: glibcver+=","+xs[1]+"-"+xs[2] else: glibcver=xs[1]+"-"+xs[2] if glibcver==[]: glibcver="unavailable" gccver = getgccversion() unameout=os.uname()[2] return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", glibc-"+glibcver+", "+unameout+")" def help(): # Move all the help stuff out of this file. emergehelp.help(myaction,myopts,havecolor) # check if root user is the current user for the actions where emerge needs this if ("--pretend" in myopts) or (myaction=="search"): if not portage.secpass: if portage.wheelgid==portage.portage_gid: print "emerge: wheel group membership required for \"--pretend\" and search." 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." else: print "emerge: portage group membership required for \"--pretend\" and search." sys.exit(1) elif "--version" in myopts: print getportageversion() sys.exit(0) elif "--help" in myopts: help() sys.exit(0) elif portage.secpass!=2: if myaction in ["search", "help", "info", "regen"]: pass elif (not myaction) and (not myfiles): pass elif ("--pretend" in myopts) and (myaction in ["world","system","clean","prune","unmerge"]): pass else: if "--debug" in myopts: print "myaction",myaction print "myopts",myopts 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: 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 update_spinner(): global spinner, spinpos if sys.stdout.isatty() and not ("--nospinner" in myopts): sys.stdout.write("\b"+spinner[spinpos]) spinpos=(spinpos+1)%8 sys.stdout.flush() # search functionality class search: # # class constants # VERSION_SHORT=1 VERSION_RELEASE=2 # # public interface # def __init__(self): """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"] def execute(self,searchkey): """Performs the search for the supplied search key""" global myopts self.searchkey=searchkey self.packagematches = [] if "--searchdesc" in myopts: self.searchdesc=1 self.matches = {"pkg":[], "desc":[]} else: self.searchdesc=0 self.matches = {"pkg":[]} print "Searching... ", 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() package_parts=package.split("/") masked=0 if self.searchre.search(package_parts[1]): if not portage.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) if not full_package: #no match found; we don't want to query description full_package=portage.best(portage.portdb.xmatch("match-all",package)) if not full_package: continue else: masked=1 try: full_desc = portage.portdb.aux_get(full_package,["DESCRIPTION"])[0] except KeyError: print "emerge: search: aux_get() failed, skipping" continue if self.searchre.search(full_desc): self.matches["desc"].append([full_package,masked]) self.mlen=0 for mtype in self.matches.keys(): self.matches[mtype].sort() self.mlen += len(self.matches[mtype]) def output(self): """Outputs the results of the search.""" print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]" print "[ Applications found : "+white(str(self.mlen))+" ]" print " " for mtype in self.matches.keys(): for match,masked in self.matches[mtype]: if mtype=="pkg": catpack=match full_package = portage.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)) 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"]) except KeyError: print "emerge: search: aux_get() failed, skipping" continue if masked: print green("*")+" "+white(match)+" "+red("[ Masked ]") else: print green("*")+" "+white(match) myversion = self.getVersion(full_package, search.VERSION_RELEASE) mysum = [0,0] mycat = match.split("/")[0] mypkg = match.split("/")[1] mydigest = portage.db["/"]["porttree"].dbapi.finddigest(mycat+"/"+mypkg + "-" + myversion) try: myfile = open(mydigest,"r") for line in myfile.readlines(): mysum[0] += int(line.split(" ")[3]) myfile.close() mystr = str(mysum[0]/1024) mycount=len(mystr) while (mycount > 3): mycount-=3 mystr=mystr[:mycount]+","+mystr[mycount:] mysum[0]=mystr+" kB" except Exception, e: if edebug: print "!!! Exception:",e mysum[0]=" [no/bad digest]" if "--quiet" not in myopts: print " ", darkgreen("Latest version available:"),myversion print " ", self.getInstallationStatus(mycat+'/'+mypkg) print " ", darkgreen("Size of downloaded files:"),mysum[0] print " ", darkgreen("Homepage:")+" ",homepage print " ", darkgreen("Description:"),desc print " ", darkgreen("License:")+" ",license print print # # private interface # def getInstallationStatus(self,package): installed_package = self.installcache.dep_bestmatch(package) result = "" version = self.getVersion(installed_package,search.VERSION_RELEASE) if len(version) > 0: result = darkgreen("Latest version installed:")+" "+version else: result = darkgreen("Latest version installed:")+" [ Not Installed ]" return result def getVersion(self,full_package,detail): if len(full_package) > 1: package_parts = portage.catpkgsplit(full_package) if detail == search.VERSION_RELEASE and package_parts[3] != 'r0': result = package_parts[2]+ "-" + package_parts[3] else: result = package_parts[2] else: result = "" return result #build our package digraph def getlist(mode): if mode=="system": mylines=portage.settings.packages elif mode=="world": try: myfile=open(portage.root+"var/cache/edb/world","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=[] mynewlines=[] for x in mylines: myline=string.join(string.split(x)) if not len(myline): continue elif myline[0]=="#": continue elif mode=="system": if myline[0]!="*": continue myline=myline[1:] mynewlines.append(myline.strip()) return mynewlines def 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 = {} self.missingbins=[] self.myaction=myaction self.digraph=portage.digraph() self.orderedkeys=[] #the following is so we have an empty vartree (used in emerge update calculations) self.fakedbapi=portage.fakedbapi() #self.fakedbapi.cpv_inject("sys-libs/glibc-2.3") self.outdatedpackages=[] self.mydbapi={} if "empty" in myparams: #for --update, we want to rebuild an entire empty tree of dependencies, and then we won't merge was is already merged. self.mydbapi["/"]=self.fakedbapi else: self.mydbapi["/"]=portage.db["/"]["vartree"].dbapi if portage.root!="/": if "empty" in myparams: self.mydbapi[portage.root]=self.fakedbapi else: self.mydbapi[portage.root]=portage.db[portage.root]["vartree"].dbapi if "--usepkg" in myopts: try: portage.db["/"]["bintree"].populate(("--getbinpkg" in myopts), ("--getbinpkgonly" in myopts)) except Exception, e: sys.stderr.write(red("!!! Failed to get all metadata:\n")+" "+str(e)+"\n") sys.exit(1) 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)""" #stuff to add: #SLOT-aware emerge #IUSE-aware emerge #"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 return 1 update_spinner() mytype,myroot,mykey=mybigkey # select the correct /var database that we'll be checking against vardbapi=portage.db[myroot]["vartree"].dbapi if addme: # 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 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=string.split(self.pkgsettings["USE"], " ") self.applied_useflags[mykey] = myuse merging=1 # this is where we add the node to the list of packages to merge if addme: 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. merging=0 elif ("selective" in myparams) and vardbapi.cpv_exists(mykey): merging=0 else: #onlydeps mode; don't merge merging=2 if 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): return 1 elif "recurse" not in myparams: return 1 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["CDEPEND"]=string.join(string.split(edepend["CDEPEND"])," ") 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["CDEPEND"]=string.join(mytbz2.getelements("CDEPEND")," ") edepend["SLOT"] =mytbz2.getfile("SLOT",mypkgparts[2]) elif mytype=="ebuild": try: for x in ["DEPEND","RDEPEND","PDEPEND","CDEPEND"]: edepend[x]=string.join(portage.portdb.aux_get(mykey,[x]), " ") except (KeyError,IOError): print "emerge: create(): aux_get() error on",mykey+"; aborting..." sys.exit(1) mydep={} 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 elif not self.select_dep(myroot,mydep[myroot],myparent=mp,myuse=myuse): 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): 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=[] for x in myfiles: if x[-5:]==".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 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.basename(x)[:-5] if not self.create(["binary",portage.root,mykey],None,"--onlydeps" not in myopts): return (0,myfavorites) elif not "--oneshot" in myopts: myfavorites.append(mykey) elif x[-7:]==".ebuild": mykey=os.path.basename(os.path.abspath(x+"/../.."))+"/"+os.path.basename(x)[:-7] if not self.create(["ebuild",portage.root,mykey],None,"--onlydeps" not in myopts): return (0,myfavorites) elif not "--oneshot" in myopts: myfavorites.append(mykey) else: try: mykey=portage.dep_expand(x,portage.portdb) except ValueError, errpkgs: print "\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify" print "!!! one of the following fully-qualified ebuild names instead:\n" if "--ask" in myopts: choice = userchoice(errpkgs[0]) mykey = errpkgs[0][choice] print else : for i in errpkgs[0]: print " " + green(i) print sys.exit(1) # select needs to return 0 on dep_check failure if "--debug" in myopts: self.mysd = self.select_dep(portage.root,mykey,arg=x) else: try: self.mysd = self.select_dep(portage.root,mykey,arg=x) except Exception, e: print "\n!!! Problem in",mykey,"dependencies." print "!!!",e sys.exit(1) if not self.mysd: return (0,myfavorites) elif not "--oneshot" in myopts: myfavorites.append(mykey) self.missingbins=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 self.missingbins == 0: print self.missingbins+=1 print "Missing binary for:",xs[2] # We're true here unless we are missing binaries. return (not self.missingbins,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 myslot=portage.portdb.aux_get(pkgver,["SLOT"])[0] alleb=portage.portdb.xmatch("match-all",pkg) while alleb: cand=portage.portdb.xmatch("bestmatch-list",pkg,mylist=alleb) if not cand: break curslot=portage.portdb.aux_get(cand,["SLOT"])[0] if (curslot==myslot) and vardbapi.cpv_exists(cand): # installed, is this package newer? if portage.pkgcmp(portage.catpkgsplit(pkgver)[1:], portage.catpkgsplit(cand)[1:]) < 0: return cand break alleb.remove(cand) def select_dep(self,myroot,depstring,myparent=None,arg=None,myuse=None): "given a dependency string, create the appropriate depgraph and return 1 on success and 0 on failure" if "--debug" in 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) if not mycheck[0]: return 0 mymerge=mycheck[1] else: #we're processing a command-line argument; unconditionally merge it even if it's already merged mymerge=[depstring] if "--debug" in myopts: print "Candidates:",mymerge for x in mymerge: myk=None binpkguseflags=None if x[0]=="!": # if this package is myself, don't append it to block list. if (myparent): if myparent.split()[2] in portage.portdb.xmatch("match-all", x[1:]): continue myk=["blocks",myroot,x[1:]] else: #We are not processing a blocker but a normal dependency myeb_pkg=None if ("--usepkg" in myopts): myeb_pkg=portage.db[portage.root]["bintree"].dep_bestmatch(x) myeb=None if ("--usepkgonly" not in myopts): myeb=portage.portdb.xmatch("bestmatch-visible",x) if (not myeb) and (not myeb_pkg): if not arg: xinfo='"'+x+'"' else: xinfo='"'+arg+'"' if myparent: xfrom = '(dependency required by '+green('"'+myparent.split()[2]+'"')+red(' ['+myparent.split()[0]+"])") alleb=portage.portdb.xmatch("match-all",x) if alleb: if "--usepkgonly" not in myopts: print "\n!!! "+red("all ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.") print "!!! "+red("possible candidates are:") for p in alleb: try: mreasons = portage.getmaskingstatus(p) print "- "+p+" (masked by: "+string.join(mreasons, ", ")+")" except: pass if myparent: print "!!! "+red(xfrom) else: print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo) print "!!! Either add a suitable binary package or compile from an ebuild." else: print "\nemerge: there are no masked or unmasked ebuilds to satisfy "+xinfo+"." return 0 if "--debug" in myopts: print "ebuild:",myeb print "binpkg:",myeb_pkg 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 --usepkg but not --usepkgonly, we only want to select the binary # if it is the same version as the latest unmasked ebuild. if portage.pkgcmp(myeb_s, myeb_pkg_s) == 0: myeb_pkg = None else: myeb = None if "--upgradeonly" in myopts: # Check that there isn't a newer version of this package already installed cand = None if myeb: cand=self.is_newer_ver_installed(myroot,x,myeb) elif myeb_pkg: cand=self.is_newer_ver_installed(myroot,x,myeb_pkg) if cand: myeb=cand 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 I'm using 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): 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): return 0 if "--debug" in myopts: print "Exiting...",myparent return 1 def altlist(self): 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: print "!!! Error: circular dependencies:" print for x in mygraph.dict.keys(): for y in mygraph.dict[x][1]: print y,"depends on",x 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) return retlist def xcreate(self,mode="system"): global syslist if mode=="system": mylist=syslist else: #world mode worldlist=getlist("world") sysdict=genericdict(syslist) worlddict=genericdict(worldlist) #we're effectively upgrading sysdict to contain all new deps from worlddict for x in worlddict.keys(): #only add the world node if the package is: #actually installed -- this prevents the remerging of already unmerged packages when we do a world --update; #actually available -- this prevents emerge from bombing out due to no match being found (we want a silent ignore) if "empty" in myparams: if portage.db["/"]["vartree"].dbapi.match(x): sysdict[x]=worlddict[x] elif portage.db[portage.root]["vartree"].dbapi.match(x): #package is installed sysdict[x]=worlddict[x] else: print "\n*** Package in world file is not installed: "+x mylist=[] for x in sysdict.keys(): mylist.append(sysdict[x]) for mydep in mylist: myeb=portage.portdb.xmatch("bestmatch-visible",mydep) if not myeb: #this is an unavailable world entry; just continue continue if "--upgradeonly" in myopts: cand=self.is_newer_ver_installed(portage.root,mydep,myeb) if cand: myeb=cand #THIS NEXT BUNCH OF CODE NEEDS TO BE REPLACED TO SUPPORT WORLD ANTI-DEPS #if mydep2[0]=="!":, etc. if "--usepkg" in myopts: mypk=portage.db[portage.root]["bintree"].dep_bestmatch(mydep) if myeb==mypk: myk=["binary",portage.root,mypk] elif "--usepkgonly" in myopts: if not mypk: self.missingbins += [myeb] myk=["binary",portage.root,myeb] else: myk=["binary",portage.root,mypk] else: myk=["ebuild",portage.root,myeb] else: myk=["ebuild",portage.root,myeb] if not self.create(myk): print print "!!! Problem with",myk[0],myk[2] print "!!! Possibly a DEPEND/*DEPEND problem." print return 0 return 1 def match(self,mydep,myroot=portage.root,mykey=None): # support mutual exclusive deps mydep2=mydep if mydep2[0]=="!": mydep2=mydep[1:] if mydep[0]=="!": #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) if not myeb: if not mykey: print "\n!!! Error: couldn't find match for",mydep else: print "\n!!! Error: couldn't find match for",mydep,"in",mykey print sys.exit(1) if "--usepkg" in myopts: mypk=portage.db[portage.root]["bintree"].dep_bestmatch(mydep) if myeb==mypk: myk="binary "+portage.root+" "+mypk else: myk="ebuild "+myroot+" "+myeb else: myk="ebuild "+myroot+" "+myeb return myk def display(self,mylist): changelogs=[] p=[] totalsize=0 if "--verbose" in myopts: overlays = string.split(portage.settings['PORTDIR_OVERLAY']) overlays = map(os.path.normpath, overlays) if "--tree" in myopts: mylist.reverse() mygraph=self.digraph.copy() 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 display_overlays=False for x in mylist: fetch=" " if x[0]=="blocks": addl=""+red("B")+" "+fetch+" " resolved=portage.db[x[1]]["vartree"].resolve_key(x[2]) print "["+x[0]+" "+addl+"]",red(resolved), if resolved!=x[2]: if x[3]: print red("(\""+x[2]+"\" from pkg "+x[3]+")") else: print red("(\""+x[2]+"\")") else: if x[3]: print red("(from pkg "+x[3]+")") else: print else: if (x[0]!="binary") and ("fetch" in string.split(portage.portdb.aux_get(x[2],["RESTRICT"])[0])): fetch = red("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]): addl=" "+yellow("R")+fetch+" " elif (not "--emptytree" in myopts) and portage.db[x[1]]["vartree"].exists_specific_cat(x[2]): mynewslot=portage.portdb.aux_get(x[2],["SLOT"])[0] 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) if myinslotlist: myoldbest=portage.best(myinslotlist) addl=" "+fetch if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0: # Downgrade in slot addl+=turquoise("U")+blue("D") else: # Update in slot addl+=turquoise("U")+" " else: # New slot, mark it new. addl=" "+green("N")+" "+fetch+" " if "--changelog" in myopts: changelogs.extend(self.calc_changelog( portage.portdb.findname(x[2]), portage.db["/"]["vartree"].dep_bestmatch('/'.join(portage.catpkgsplit(x[2])[:2])), x[2] )) else: addl=" "+green("N")+" "+fetch+" " if myoldbest: myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2] if myoldbest[-3:]=="-r0": myoldbest=myoldbest[:-3] myoldbest=blue("["+myoldbest+"]") verboseadd="" if "--verbose" in myopts: # iuse verbose try: iuse_split = string.split(portage.portdb.aux_get(x[2],["IUSE"])[0], " ") except: portage.writemsg("!!! Error getting IUSE (report this to bugs.gentoo.org)\n") portage.writemsg("!!! %s\n" % x) iuse_split = [] iuse_split.sort() iuse="" for ebuild_iuse in iuse_split: if not ebuild_iuse: continue if ebuild_iuse in self.applied_useflags[x[2]]: iuse=iuse+red("+"+ebuild_iuse)+" " elif ebuild_iuse in portage.settings.usemask: iuse=iuse+blue("-("+ebuild_iuse+")")+" " else: iuse=iuse+blue("-"+ebuild_iuse)+" " verboseadd+=iuse+" " # size verbose mysize=0 if x[0] == "ebuild" and x[-1]!="nomerge": mysize=portage.portdb.getsize(x[2], debug=edebug) if type(mysize) == types.IntType: totalsize+=mysize verboseadd+=format_size(mysize)+" " # overlay verbose file_name=portage.portdb.findname(x[2]) 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)+"]")+" " display_overlays=True 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 oldlp=mywidth-30 newlp=oldlp-30 indent="" if ("--tree" in myopts): indent=" "*mygraph.depth(string.join(x)) if x[1]!="/": if "--columns" in myopts: myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0]) if (newlp-len(myprint)) > 0: myprint=myprint+(" "*(newlp-len(myprint))) myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] " if (oldlp-len(myprint)) > 0: myprint=myprint+" "*(oldlp-len(myprint)) myprint=myprint+myoldbest myprint=myprint+darkgreen(" to "+x[1])+" "+verboseadd else: myprint="["+x[0]+" "+addl+"] "+darkgreen(x[2])+" "+myoldbest+" "+darkgreen("to "+x[1])+" "+verboseadd else: if "--columns" in myopts: myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0]) if (newlp-len(myprint)) > 0: myprint=myprint+(" "*(newlp-len(myprint))) myprint=myprint+green(" ["+xs[1]+xs[2]+"] ") if (oldlp-len(myprint)) > 0: myprint=myprint+(" "*(oldlp-len(myprint))) myprint=myprint+myoldbest+" "+verboseadd else: if x[3]=="nomerge": myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd else: myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd p.append(myprint) 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: if mylist.index(x)>> Recording",myfavkey,"in \"world\" favorites file..." if not "--fetchonly" in myopts: portage.writedict(myfavdict,portage.root+"var/cache/edb/world",writekey=0) 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) mergecount=0 for x in mymergelist: mergecount+=1 myroot=x[1] pkgindex=2 if x[0]=="blocks": pkgindex=3 y=portage.portdb.findname(x[pkgindex]) if not "--pretend" in myopts: print ">>> emerge ("+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") #buildsyspkg: Check if we need to _force_ binary package creation issyspkg = ("buildsyspkg" in myfeat) \ and mysysdict.has_key(portage.cpv_getkey(x[2])) \ and not ("--buildpkg" in myopts) if x[0] in ["ebuild","blocks"]: if (x[0]=="blocks") and ("--fetchonly" not in myopts): raise Exception, "Merging a blocker" elif ("--fetchonly" in myopts): retval=portage.doebuild(y,"fetch",myroot,self.pkgsettings,edebug,("--pretend" in myopts),fetchonly=1) if 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 emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+x[pkgindex]+"::"+y+")") retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1) if retval: sys.exit(1) emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Packaging ("+x[pkgindex]+"::"+y+")") retval=portage.doebuild(y,"package",myroot,self.pkgsettings,edebug) if retval: sys.exit(1) #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]) emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging ("+x[pkgindex]+"::"+y+")") 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: emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+x[pkgindex]+"::"+y+")") retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1) if retval: sys.exit(1) emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Merging ("+x[pkgindex]+"::"+y+")") retval=portage.doebuild(y,"merge",myroot,self.pkgsettings,edebug) if retval: sys.exit(1) #dynamically update our database elif x[0]=="binary": #merge the tbz2 if portage.db[portage.root]["bintree"].isremote(x[2]): emergelog(" --- ("+str(mergecount)+" of "+str(len(mymergelist))+") Fetching Binary ("+x[pkgindex]+"::"+y+")") portage.db[portage.root]["bintree"].gettbz2(x[2]) if ("--fetchonly" in myopts): continue mytbz2=portage.db[portage.root]["bintree"].getname(x[2]) emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging Binary ("+x[pkgindex]+"::"+y+")") retval=portage.pkgmerge(mytbz2,x[1],self.pkgsettings) if retval==None: sys.exit(1) #need to check for errors if "--buildpkgonly" not in myopts: portage.db[x[1]]["vartree"].inject(x[2]) myfavkey=portage.cpv_getkey(x[2]) if (not "--fetchonly" in myopts) and (myfavkey in favorites): myfavs=portage.grabfile(myroot+"var/cache/edb/world") 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]+")") portage.writedict(myfavdict,myroot+"var/cache/edb/world",writekey=0) if ("noclean" not in portage.features) and (x[0] != "binary"): emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Post-Build Cleaning ("+x[pkgindex]+"::"+y+")") retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1) if retval: sys.exit(1) if ("--pretend" not in myopts) and ("--fetchonly" not in myopts): # Clean the old package that we have merged over top of it. if self.pkgsettings["AUTOCLEAN"]=="yes": xsplit=portage.pkgsplit(x[2]) emergelog(" >>> AUTOCLEAN: "+xsplit[0]) retval=unmerge("clean", [xsplit[0]]) if not retval: emergelog(" --- AUTOCLEAN: Nothing unmerged.") # Figure out if we need a restart. mysplit=portage.pkgsplit(x[2]) if mysplit[0]=="sys-apps/portage": myver=mysplit[1]+"-"+mysplit[2] if myver[-3:]=='-r0': myver=myver[:-3] if myver!=portage.VERSION: if len(mymergelist) > mergecount: myargv=sys.argv myr=0 for myra in range(len(myargv)): if myargv[myr][0:len("portage")]=="portage": del myargv[myr] myr-=1 if myargv[myr][0:len("sys-apps/portage")]=="sys-apps/portage": del myargv[myr] myr-=1 myr+=1 emergelog(" *** RESTARTING emerge via exec() after change of portage version.") portage.portageexit() os.execv("/usr/lib/portage/bin/emerge", myargv) if ("--pretend" not in myopts) and ("--fetchonly" not in myopts): emergelog(" ::: completed emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[2]+" to "+x[1]) # Unsafe for parallel merges del portage.mtimedb["resume"]["mergelist"][0] emergelog(" *** 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): if (mergecount>0): if retval: portage.env_update() #by doing an exit this way, --fetchonly can continue to try to #fetch everything even if a particular download fails. if "--fetchonly" in 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) def unmerge(unmerge_action, unmerge_files): candidate_catpkgs=[] global_unmerge=0 mysettings = portage.config(clone=portage.settings) if not unmerge_files or "world" in unmerge_files or "system" in unmerge_files: if "unmerge"==unmerge_action: print print bold("emerge unmerge")+" can only be used with specific package names, not with "+bold("world")+" or" print bold("system")+" targets." print return 0 else: global_unmerge=1 localtree=portage.db[portage.root]["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")) else: #we've got command-line arguments if not unmerge_files: print "\nNo packages to unmerge have been provided.\n" return 0 for x in unmerge_files: arg_parts=x.split('/') if (x[0] not in [".","/"]) and (arg_parts[-1][-7:] != ".ebuild"): #possible cat/pkg or dep; treat as such candidate_catpkgs.append(x) elif unmerge_action in ["prune","clean"]: print "\n!!! Prune and clean do not accept individual ebuilds as arguments;\n skipping.\n" continue else: # it appears that the user is specifying an installed ebuild and we're in "unmerge" mode, so it's # ok. if not os.path.exists(x): print "\n!!! The path '"+x+"' doesn't exist.\n" return 0 absx = os.path.abspath(x) sp_absx = absx.split("/") if sp_absx[-1][-7:] == ".ebuild": del sp_absx[-1] absx = string.join(sp_absx,"/") sp_absx_len = len(sp_absx) vdb_path = portage.root+portage.VDB_PATH vdb_len = len(vdb_path) sp_vdb = vdb_path.split("/") sp_vdb_len = len(sp_vdb) if not os.path.exists(absx+"/CONTENTS"): print "!!! Not a valid db dir: "+str(absx) return 0 if sp_absx_len <= sp_vdb_len: # The Path is shorter... so it can't be inside the vdb. print spabsx print absx print "\n!!!",x,"cannot be inside "+(portage.root+portage.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" return 0 print "="+string.join(sp_absx[sp_vdb_len:],"/") candidate_catpkgs.append("="+string.join(sp_absx[sp_vdb_len:],"/")) if ("--pretend" in myopts) or ("--ask" in myopts): print darkgreen("\n>>> These are the packages that I would unmerge:") pkgmap={} numselected=0 for x in candidate_catpkgs: #cycle through all our candidate deps and determine what will and will not get unmerged try: mymatch=localtree.dep_match(x) except KeyError: mymatch=None except ValueError, errpkgs: print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify" print "!!! one of the following fully-qualified ebuild names instead:\n" for i in errpkgs[0]: print " " + green(i) print sys.exit(1) if not mymatch and x[0] not in "<>=~": #add a "=" if missing mymatch=localtree.dep_match("="+x) if not mymatch: 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 not pkgmap.has_key(mykey): pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] } if unmerge_action=="unmerge": for y in mymatch: if not y in pkgmap[mykey]["selected"]: pkgmap[mykey]["selected"].append(y) numselected=numselected+len(mymatch) else: #unmerge_action in ["prune", clean"] slotmap={} for mypkg in mymatch: if unmerge_action=="clean": myslot=localtree.getslot(mypkg) else: #since we're pruning, we don't care about slots and put all the pkgs in together myslot=0 if not slotmap.has_key(myslot): slotmap[myslot]={} slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg for myslot in slotmap.keys(): counterkeys=slotmap[myslot].keys() counterkeys.sort() if not counterkeys: continue counterkeys.sort() pkgmap[mykey]["protected"].append(slotmap[myslot][counterkeys[-1]]) del counterkeys[-1] #be pretty and get them in order of merge: for ckey in counterkeys: pkgmap[mykey]["selected"].append(slotmap[myslot][ckey]) numselected=numselected+1 #ok, now the last-merged package is protected, and the rest are selected if global_unmerge and not numselected: print "\n>>> No outdated packages were found on your system.\n" return 0 if not numselected: print "\n>>>",unmerge_action+": No packages selected for removal.\n" return 0 for x in pkgmap.keys(): for y in localtree.dep_match(x): if y not in pkgmap[x]["omitted"] and \ y not in pkgmap[x]["selected"] and \ y not in pkgmap[x]["protected"]: pkgmap[x]["omitted"].append(y) if global_unmerge and not pkgmap[x]["selected"]: #avoid cluttering the preview printout with stuff that isn't getting unmerged continue print "\n "+white(x) for mytype in ["selected","protected","omitted"]: print string.rjust(mytype,12)+":", if pkgmap[x][mytype]: for mypkg in pkgmap[x][mytype]: mysplit=portage.catpkgsplit(mypkg) if mysplit[3]=="r0": myversion=mysplit[2] else: myversion=mysplit[2]+"-"+mysplit[3] if mytype=="selected": print red(myversion), else: print green(myversion), else: print "none", print print "\n>>>",red("'Selected'"),"packages are slated for removal." print ">>>",green("'Protected'"),"and",green("'omitted'"),"packages will not be removed.\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": # enter pretend mode for correct formatting of results __main__.myopts+=["--pretend"] print print "Quitting." print return 0 #the real unmerging begins, after a short delay.... if mysettings["CLEAN_DELAY"]: secs=string.atoi(mysettings["CLEAN_DELAY"]) else: secs=5 countdown(secs, ">>> Unmerging") for x in pkgmap.keys(): for y in pkgmap[x]["selected"]: print ">>> Unmerging "+y+"..." emergelog("=== 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) else: emergelog(" >>> unmerge success: "+y) #run ldconfig, etc... portage.env_update() if not numselected: return 0 else: return 1 def post_emerge(retval=0): os.chdir("/") global myopts print if "--pretend" in myopts: sys.exit(retval) emergelog(" *** exiting successfully.") root=portage.root infodirs=[] infodirs.extend(string.split(portage.settings["INFOPATH"], ":")) infodirs.extend(string.split(portage.settings["INFODIR"], ":")) if os.path.exists("/usr/bin/install-info"): regen_infodirs=[] for z in infodirs: if z=='': continue inforoot=normpath(root+z) if os.path.isdir(inforoot): try: infomtime=os.stat(inforoot)[ST_MTIME] 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 regen_infodirs.append(inforoot) else: regen_infodirs.append(inforoot) if not regen_infodirs: print " "+green("*")+" GNU info directory index is up-to-date." else: print " "+green("*")+" Regenerating GNU info directory index..." icount=0 badcount=0 for inforoot in regen_infodirs: if inforoot=='': continue try: os.rename(inforoot+"/dir",inforoot+"/dir.old") except: pass if not os.path.isdir(inforoot): continue for x in os.listdir(inforoot): if (x[0] == ".") or (x in ["dir","dir.old"]): continue myso=commands.getstatusoutput("LANG=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1] existsstr="already exists, for file `" if myso!="": if re.search(existsstr,myso): # Already exists... Don't increment the count for this. pass else: badcount=badcount+1 if "--verbose" in myopts: print myso icount=icount+1 #update mtime so we can potentially avoid regenerating. portage.mtimedb["info"][inforoot]=os.stat(inforoot)[ST_MTIME] if badcount: if "--verbose" not in myopts: print " "+yellow("*")+" Processed",icount,"info files:",badcount,"errors; run with "+green("emerge --verbose")+" to view errors." else: print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors." else: print " "+green("*")+" Processed",icount,"info files." if portage.settings["CONFIG_PROTECT"]: #number of directories with some protect files in them procount=0 for x in string.split(portage.settings["CONFIG_PROTECT"]): 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." 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." print sys.exit(retval) # general options that should be taken into account before any action if "--debug" in myopts: edebug=1 if myaction in ["sync","rsync","metadata"] and (not "--help" in myopts): if "--pretend" in myopts: print "emerge: \"sync\" actions do not support \"--pretend.\"" sys.exit(1) emergelog(" === "+str(myaction)) myportdir=portage.settings["PORTDIR"] 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"]) os.umask(0022) if myaction == "metadata": print "skipping sync" updatecache_flg = True tmpservertimestampfile = None elif syncuri[:8]=="rsync://": if not os.path.exists("/usr/bin/rsync"): print "!!! /usr/bin/rsync does not exist, so rsync support is disabled." print "!!! Type \"emerge net-misc/rsync\" to enable rsync support." sys.exit(1) mytimeout=180 if portage.settings.has_key("RSYNC_TIMEOUT"): try: mytimeout=int(portage.settings["RSYNC_TIMEOUT"]) except: pass rsync_flags = [ "--recursive", # Recurse directories "--links", # Consider symlinks "--safe-links", # Ignore links outside of tree "--perms", # Preserve permissions "--times", # Preserive mod times "--compress", # Compress the data transmitted "--force", # Force deletion on non-empty dirs "--whole-file", # Don't do block transfers, only entire files "--delete", # Delete files that aren't in the master tree "--delete-after", # Delete only after everything else is done "--stats", # Show final statistics about what was transfered "--timeout="+str(mytimeout), # IO timeout if not done in X seconds "--exclude='distfiles/*'", # Exclude distfiles from consideration "--exclude='local/*'", # Exclude local from consideration "--exclude='packages/*'", # Exclude packages from consideration ] if "--quiet" in myopts: rsync_flags.append("--quiet") # Shut up a lot else: rsync_flags.append("--progress") # Progress meter for each file if "--verbose" in myopts: rsync_flags.append("--verbose") # More noise? Not really sure what if "--debug" in myopts: rsync_flags.append("--checksum") # Force checksum on all files if portage.settings.has_key("RSYNC_EXCLUDEFROM"): if os.path.exists(portage.settings["RSYNC_EXCLUDEFROM"]): rsync_flags.append("--exclude-from="+portage.settings["RSYNC_EXCLUDEFROM"]) else: print "!!! RSYNC_EXCLUDEFROM specified, but file does not exist." if portage.settings.has_key("RSYNC_RATELIMIT"): rsync_flags.append("--bwlimit="+portage.settings["RSYNC_RATELIMIT"]) rsynccommand = "/usr/bin/rsync " + string.join(rsync_flags, " ") servertimestampdir = portage.settings["PORTAGE_CACHEDIR"]+"/" servertimestampfile = portage.settings["PORTAGE_CACHEDIR"]+"/timestamp.chk" tmpservertimestampdir = portage.settings["PORTAGE_TMPDIR"]+"/" tmpservertimestampfile = portage.settings["PORTAGE_TMPDIR"]+"/timestamp.chk" # We only use the backup if a timestamp exists in the portdir. content=None if os.path.exists(myportdir+"/metadata/timestamp.chk"): content=portage.grabfile(servertimestampfile) if (not content): content=portage.grabfile(myportdir+"/metadata/timestamp.chk") if (content): mytimestamp=time.mktime(time.strptime(content[0], "%a, %d %b %Y %H:%M:%S +0000")) else: mytimestamp=0 if not os.path.exists(servertimestampdir): os.mkdir(servertimestampdir) os.chown(servertimestampdir, os.getuid(), portage.portage_gid) os.chmod(servertimestampdir, 02775) #exitcode=0 try: maxretries=int(portage.settings["RSYNC_RETRIES"]) except: maxretries=3 #default number of retries retries=0 hostname, port=re.split("rsync://([^:/]*)(:[0-9]+)?", syncuri)[1:3]; if port==None: port="" updatecache_flg=True ips=[] while (1): if ips: del ips[0] if ips==[]: try: ips=socket.gethostbyname_ex(hostname)[2] except Exception, e: print "Notice:",str(e) dosyncuri=syncuri if ips: try: dosyncuri=string.replace(syncuri, "//"+hostname+port+"/", "//"+ips[0]+port+"/", 1) except Exception, e: print "Notice:",str(e) dosyncuri=syncuri if (retries==0): if "--ask" in myopts: if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No": print print "Quitting." print sys.exit(0) emergelog(">>> starting rsync with "+dosyncuri) print ">>> starting rsync with "+dosyncuri+"..." else: emergelog(">>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)) print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri) print ">>> checking server timestamp ..." mycommand=rsynccommand+" "+dosyncuri+"/metadata/timestamp.chk "+tmpservertimestampdir exitcode=portage.spawn(mycommand,portage.settings,free=1) if (exitcode==0): try: servertimestamp = time.mktime(time.strptime(portage.grabfile(tmpservertimestampfile)[0], "%a, %d %b %Y %H:%M:%S +0000")) except: servertimestamp = 0 if (servertimestamp != 0) and (servertimestamp == mytimestamp): emergelog(">>> Cancelling sync -- Already current.") print print ">>>" print ">>> Timestamps on the server and in the local repository are the same." print ">>> Cancelling all further sync action. You are already up to date." print ">>>" print sys.exit(0) elif (servertimestamp != 0) and (servertimestamp < mytimestamp): emergelog(">>> Server out of date: %s" % dosyncuri) print print ">>>" print ">>> SERVER OUT OF DATE: %s" % dosyncuri print ">>>" print elif (servertimestamp == 0) or (servertimestamp > mytimestamp): # actual sync mycommand=rsynccommand+" "+dosyncuri+"/* "+myportdir exitcode=portage.spawn(mycommand,portage.settings,free=1) if exitcode in [0,1,2,3,4,11,14,20,21]: break elif exitcode in [0,1,2,3,4,11,14,20,21]: break retries=retries+1 if retries<=maxretries: print ">>> retry ..." time.sleep(11) else: # over retries # exit loop updatecache_flg=False break if (exitcode==0): emergelog("=== Sync completed with %s" % dosyncuri) elif (exitcode>0): print if exitcode==1: print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure") print darkred("!!!")+green(" that your SYNC statement is proper.") print darkred("!!!")+green(" SYNC="+portage.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"]) elif exitcode==20: print darkred("!!!")+green(" Rsync was killed before it finished.") else: print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep") print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable") print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a") print darkred("!!!")+green(" temporary problem unless complications exist with your network") print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.") print sys.exit(exitcode) elif syncuri[:6]=="cvs://": if not os.path.exists("/usr/bin/cvs"): print "!!! /usr/bin/cvs does not exist, so rsync support is disabled." print "!!! Type \"emerge dev-util/cvs\" to enable CVS support." sys.exit(1) cvsroot=syncuri[6:] cvsdir=os.path.dirname(myportdir) if not os.path.exists(myportdir+"/CVS"): #initial checkout print ">>> starting initial cvs checkout with "+syncuri+"..." if 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 gentoo-x86 -P",portage.settings,free=1): print "!!! cvs checkout error; exiting." sys.exit(1) if cvsdir!=myportdir: portage.movefile(cvsdir,portage.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)) else: print "!!! rsync setting: ",syncuri,"not recognized; exiting." sys.exit(1) if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg: print "\n>>> Updating Portage cache... ", os.umask(0002) cachedir = os.path.normpath(portage.settings["PORTAGE_CACHEDIR"]) 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 os.path.exists(cachedir): portage.spawn("rm -Rf "+cachedir+"/*",portage.settings,free=1) else: os.mkdir(cachedir) # save timestamp.chk for next timestamp check. try: if tmpservertimestampfile != None: portage.movefile(tmpservertimestampfile, servertimestampfile) except Exception, e: print "!!! Failed to save current timestamp." print "!!!",e portage.portdb.flush_cache() try: os.umask(002) os.chown(cachedir, os.getuid(), portage.portage_gid) os.chmod(cachedir, 02775) except: pass mynodes=portage.portdb.cp_all() mynodes.sort() for x in mynodes: myxsplit=x.split("/") mymatches=portage.portdb.xmatch("match-all",x) mymatches.sort() for y in mymatches: update_spinner() try: ignored=portage.portdb.aux_get(y,[],metacachedir=myportdir+"/metadata/cache",debug=("cachedebug" in portage.features)) except: print "\nFailed cache update:",y sys.stdout.write("\b\b ...done!\n\n") sys.stdout.flush() 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")) if(mybestpv != mypvs): print print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended" print red(" * ")+"that you update portage now, before any other packages are updated." print red(" * ")+"Please do so and then update "+bold("ALL")+" of your configuration files." print elif myaction=="regen": emergelog(" === regen") #regenerate cache entries print "Regenerating cache entries... " sys.stdout.flush() mynodes=portage.portdb.cp_all() for x in mynodes: mymatches=portage.portdb.xmatch("match-all",x) if not "--quiet" in myopts: print "processing",x for y in mymatches: try: foo=portage.portdb.aux_get(y,["DEPEND"],debug=1) except: print "\nerror processing",y+", continuing..." print "done!" # HELP action elif "config"==myaction: emergelog(" === config") print print "Currently, \'config\' is a help option only." print # INFO action elif "info"==myaction: unameout=commands.getstatusoutput("/bin/uname -mrp")[1] print getportageversion() print "=================================================================" print "System uname: "+unameout os.system("cat /etc/gentoo-release") output=commands.getstatusoutput("`which distcc` --version") if not output[0]: print str(string.split(output[1],"\n",1)[0]), if "distcc" in portage.features: print "[enabled]" else: print "[disabled]" output=commands.getstatusoutput("`which ccache` -V") if not output[0]: print str(string.split(output[1],"\n",1)[0]), if "ccache" in portage.features: print "[enabled]" else: print "[disabled]" ac_vers = string.join(portage.db["/"]["vartree"].dbapi.match("sys-devel/autoconf"), ",") am_vers = string.join(portage.db["/"]["vartree"].dbapi.match("sys-devel/automake"), ",") print "Autoconf: " + ac_vers print "Automake: " + am_vers if "--verbose" in myopts: myvars=portage.settings.keys() else: myvars=['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK', 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR', 'PORTDIR_OVERLAY', 'USE', 'COMPILER', 'CHOST', 'CFLAGS', 'CXXFLAGS','ACCEPT_KEYWORDS', 'MAKEOPTS', 'AUTOCLEAN', 'SYNC', 'FEATURES'] myvars.sort() for x in myvars: print x+'="'+portage.settings[x]+'"' #print portage.settings.keys() print # SEARCH action elif "search"==myaction: if not myfiles: print "emerge: no search terms provided." else: searchinstance = search() for mysearch in myfiles: try: searchinstance.execute(mysearch) except re.error, comment: print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment ) sys.exit(1) searchinstance.output() elif "inject"==myaction: if not myfiles: print "emerge: please specify at least one cat/pkg-ver to inject." sys.exit(1) if "--pretend" in myopts: print "emerge: the \"inject\" action does not support \"--pretend.\"" sys.exit(1) for x in myfiles: if x[0] in [">","<","=","!"]: print "!!! '"+x+"' is an invalid specification." print "!!! Must be 'category/package-version' with no other symbols." print continue mycps=portage.catpkgsplit(x) if (not mycps) or (mycps[0]=="null"): print "!!!",x,"is not a specific cat/pkg-version, skipping..." continue if portage.db["/"]["vartree"].exists_specific(x): print "!!! Not injecting",x+"; Package already exists." else: if "--ask" in myopts: if userquery("Do you want to inject the package %s?" % x)=="No": print print "Quitting." print sys.exit(0) portage.db["/"]["vartree"].dbapi.cpv_inject(x) print ">>> Injected",x+"." emergelog(" === inject: "+x) elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction: if 1==unmerge(myaction, myfiles): post_emerge() elif "depclean"==myaction: # Kill packages that aren't explicitly merged or are required as a # dependency of another package. World file is explicit. print print red("*** WARNING ***")+" : DEPCLEAN CAN SERIOUSLY IMPAIR YOUR SYSTEM. USE CAUTION." print red("*** WARNING ***")+" : (Cancel: CONTROL-C) -- ALWAYS VERIFY ALL PACKAGES IN THE" print red("*** WARNING ***")+" : CANDIDATE LIST FOR SANITY BEFORE ALLOWING DEPCLEAN TO" print red("*** WARNING ***")+" : UNMERGE ANY PACKAGES." print red("*** WARNING ***")+" :" print red("*** WARNING ***")+" : USE FLAGS MAY HAVE AN EXTREME EFFECT ON THE OUTPUT." print red("*** WARNING ***")+" : SOME LIBRARIES MAY BE USED BY PACKAGES BUT ARE NOT" print red("*** WARNING ***")+" : CONSIDERED TO BE A DEPEND DUE TO USE FLAG SETTINGS." print red("*** WARNING ***")+" :" print red("*** WARNING ***")+" : Packages in the list that are desired may be added" print red("*** WARNING ***")+" : directly to the world file to cause them to be ignored" print red("*** WARNING ***")+" : by depclean and maintained in the future. BREAKAGES DUE" print red("*** WARNING ***")+" : TO UNMERGING AN ==IN-USE LIBRARY== MAY BE REPAIRED BY" print red("*** WARNING ***")+" : MERGING *** THE PACKAGE THAT COMPLAINS *** ABOUT THE" print red("*** WARNING ***")+" : MISSING LIBRARY." print if ("--pretend" not in myopts) and ("--ask" not in myopts): countdown(10, ">>> Depclean") emergelog(" >>> depclean") mydepgraph=depgraph(myaction,myopts) syslist=getlist("system") worldlist=getlist("world") print "Calculating",myaction,"dependencies ", if not mydepgraph.xcreate("world"): print "\n!!! Failed to create deptree." sys.exit(1) 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() myvarlist=portage.vardbapi(portage.root).cp_all() if not syslist: print "!!! You have no system list. Cannot determine system from world." if not worldlist: print "!!! You have no world file. Cannot determine explicit merges." if not myvarlist: print "!!! You have no installed package tree (%s). This is a problem." % portage.VDB_PATH if not alldeps: print "!!! You have no dependencies. Impossible. Bug." if not (syslist and worldlist and myvarlist and alldeps): print 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(15, "*** Continuing") continue 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 if len(cleanlist): unmerge("unmerge", cleanlist) 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)) 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: favorites=[] syslist=getlist("system") if (("--pretend" in myopts) and not ("--fetchonly" in myopts)) or ("--ask" in myopts): if "--tree" in myopts: print print darkgreen("These are the packages that I would merge, in reverse order:") print else: print print darkgreen("These are the packages that I would merge, in order:") print if ("--resume" in myopts) and portage.mtimedb.has_key("resume"): myresumeopts=portage.mtimedb["resume"]["myopts"][:] if "--skipfirst" in myresumeopts: myresumeopts.remove("--skipfirst") for myopt in myopts: if myopt not in myresumeopts: myresumeopts.append(myopt) myopts=myresumeopts mydepgraph=depgraph("resume",myopts) if "--resume" not in myopts: myopts+=["--resume"] 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) if myaction in ["system","world"]: print "Calculating",myaction,"dependencies ", if not mydepgraph.xcreate(myaction): print "!!! Depgraph creation failed." sys.exit(1) 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 print "Calculating dependencies ", retval,favorites=mydepgraph.select_files(myfiles) if not retval: print "\n!!! Error calculating dependencies. Please correct." sys.exit(1) print "\b\b ...done!" if ("--usepkgonly" in myopts) and mydepgraph.missingbins: sys.stderr.write(red("The following binaries are not available for merging...\n")) if mydepgraph.missingbins: for x in mydepgraph.missingbins: sys.stderr.write(" "+str(x)+"\n") sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n") sys.exit(1) if "--ask" in myopts: if "--resume" in myopts: mydepgraph.display(portage.mtimedb["resume"]["mergelist"]) prompt="Do you want me to resume merging these packages?" else: mydepgraph.display(mydepgraph.altlist()) mergecount=0 for x in mydepgraph.altlist(): if x[3]!="nomerge": mergecount+=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?" else: print print "Nothing to merge; quitting." print sys.exit(0) elif "--fetchonly" in myopts: prompt="Do you want me to fetch the source files for these packages?" else: prompt="Do you want me to merge these packages?" print if userquery(prompt)=="No": print print "Quitting." print sys.exit(0) # Don't ask again (e.g. when auto-cleaning packages after merge) myopts.remove("--ask") if ("--pretend" in myopts) and ("--fetchonly" not in myopts): if ("--resume" in myopts): mydepgraph.display(portage.mtimedb["resume"]["mergelist"]) else: mydepgraph.display(mydepgraph.altlist()) else: if ("--buildpkgonly" in myopts): if not mydepgraph.digraph.hasallzeros(): 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"]) else: portage.mtimedb["resume"]={} portage.mtimedb["resume"]["myopts"]=myopts portage.mtimedb["resume"]["favorites"]=favorites if ("--digest" in myopts) and not ("--fetchonly" 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)) mydepgraph.merge(mydepgraph.altlist()) if portage.mtimedb.has_key("resume"): del portage.mtimedb["resume"] if portage.settings["AUTOCLEAN"] and "yes"==portage.settings["AUTOCLEAN"]: print ">>> Auto-cleaning packages ..." unmerge("clean", ["world"]) post_emerge()