diff -Naurd ./ChangeLog ../portage-2.0.46-r4.new/ChangeLog --- ./ChangeLog 2002-12-24 20:52:34.000000000 +0000 +++ ../portage-2.0.46-r4.new/ChangeLog 2002-12-27 14:48:16.000000000 +0000 @@ -1,6 +1,13 @@ # ChangeLog for Portage; the Gentoo Linux ports system # Copyright 2002 Gentoo Technologies, Inc.; Distributed under the GPL v2 +*portage-2.0.48 (27 Dec 2002): Feature: --retry + + 27 Dec 2002; Yannick Le Saint emergehelp.py, portage.py, emerge + + --firstfail: exit as soon as one merge failed + --retry: retry merging packages if it might help + *portage-2.0.46-r3 (24 Dec 2002): Backport of fixes in 2.0.47_pre2 *portage-2.0.47_pre2 (24 Dec 2002): Feature: userpriv compiles diff -Naurd ./bin/emerge ../portage-2.0.46-r4.new/bin/emerge --- ./bin/emerge 2002-12-24 20:14:01.000000000 +0000 +++ ../portage-2.0.46-r4.new/bin/emerge 2002-12-27 15:52:43.000000000 +0000 @@ -15,8 +15,8 @@ merged=0 params=["selective", "deep", "self", "recurse", "empty"] actions=["clean", "config", "help", "info", "prune", "rsync", "search", "sync", "system", "unmerge", "world", "inject", "regen", "depclean"] -options=["--autoclean", "--deep", "--selective", "--buildpkg", "--debug", "--nodeps", "--emptytree", "--fetchonly", "--changelog", -"--noreplace", "--onlydeps", "--pretend", "--usepkg", "--usepkgonly", "--searchdesc", "--verbose", "--update", "--help", "--oneshot", "--version"] +options=["--autoclean", "--deep", "--selective", "--buildpkg", "--debug", "--nodeps", "--emptytree", "--fetchonly", "--changelog", "--firstfail", +"--noreplace", "--onlydeps", "--pretend", "--retry", "--usepkg", "--usepkgonly", "--searchdesc", "--verbose", "--update", "--help", "--oneshot", "--version"] shortmapping={"a":"--autoclean", "b":"--buildpkg", "c":"clean", "C":"unmerge", "e":"--emptytree", "d":"--debug", "f":"--fetchonly", "h":"--help", "k":"--usepkg", "K":"--usepkgonly", "n":"--noreplace", "o":"--onlydeps", "p":"--pretend", "P":"prune", "s":"search", @@ -427,8 +427,17 @@ #IUSE-aware emerge #"no downgrade" emerge jbigkey=string.join(mybigkey) + #this conditional is needed to prevent infinite recursion on already-processed deps if self.digraph.hasnode(jbigkey+" merge") or self.digraph.hasnode(jbigkey+" nomerge"): - #this conditional is needed to prevent infinite recursion on already-processed deps + # just make sure myparent is registered + if myparent==None: return 1 + for mymergetype in ["merge", "nomerge"]: + existingkey=jbigkey+" "+mymergetype + if not self.digraph.hasnode(existingkey): continue + if myparent in self.digraph.parents(existingkey): return 1 + self.digraph.addnode(existingkey,myparent) + return 1 + print "should not reach this point" return 1 update_spinner() @@ -848,7 +857,7 @@ def outdated(self): return self.outdatedpackages - def merge(self,mylist): + def merge(self,mylist,mydigraph=None): returnme=0 #check for blocking dependencies for x in mylist: @@ -861,101 +870,135 @@ if mylist[x][3]!="nomerge": mymergelist.append(mylist[x]) - mergecount=0 - for x in mymergelist: - mergecount+=1 - myroot=x[1] - #the last argument in the portage.doebuild() tells doebuild to *not* do dep checking - #(emerge is already handling that) - y=portage.portdb.findname(x[2]) - if not "--pretend" in myopts: - print ">>> emerge ("+str(mergecount)+" of "+str(len(mymergelist))+")",x[2],"to",x[1] - emergelog(" >>> emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[2]+" to "+x[1]) - if x[0]=="ebuild": - if "--fetchonly" in myopts: - retval=portage.doebuild(y,"fetch",myroot,edebug,("--pretend" in myopts)) - if retval: - print - print "!!! Fetch for",y,"failed, continuing..." - print - returnme=1 - elif "--buildpkg" in myopts: - #create pkg, then merge pkg - retval=portage.doebuild(y,"clean",myroot,edebug) - if retval: - sys.exit(1) - retval=portage.doebuild(y,"package",myroot,edebug) - if retval: - sys.exit(1) - #dynamically update our database - portage.db[portage.root]["bintree"].inject(x[2]) + mygraph=None # dependencies not satisfied yet + if mydigraph!=None: mygraph=mydigraph.copy() + mybuiltlist=[] # packages successfully built (in order) + trycount=0 # number of `try to merge' done + passcount=0 # pass number + passmergecount=0 # number of packages merged in this pass + # package key filter: should be merged packages only + merge_only_filter=lambda p: string.split(p)[3] == "merge" + # each pass, packages not successfully built yet are built + # it takes care of dependencies though + while 1: + passmergecount=0 + for x in mymergelist: + if mygraph!=None and not x[2] in map((lambda xkey: string.split(xkey)[2]), mygraph.allroots(merge_only_filter)): continue + if "--verbose" in myopts: + print "merge starting: "+x[2] + sys.stdout.flush() + trycount+=1 + myroot=x[1] + #the last argument in the portage.doebuild() tells doebuild to *not* do dep checking + #(emerge is already handling that) + y=portage.portdb.findname(x[2]) + if not "--pretend" in myopts: + print ">>> emerge ("+str(trycount)+" of "+str(len(mymergelist))+")",x[2],"to",x[1] + emergelog(" >>> emerge ("+str(trycount)+" of "+str(len(mymergelist))+") "+x[2]+" to "+x[1]) + if x[0]=="ebuild": + if "--fetchonly" in myopts: + retval=portage.doebuild(y,"fetch",myroot,edebug,("--pretend" in myopts)) + if retval: + print + print "!!! Fetch for",y,"failed, continuing..." + print + returnme=1 + elif "--buildpkg" in myopts: + #create pkg, then merge pkg + retval=portage.doebuild(y,"clean",myroot,edebug) + if retval: + if "--firstfail" in myopts: sys.exit(1) + else: continue + retval=portage.doebuild(y,"package",myroot,edebug) + if retval: + if "--firstfail" in myopts: sys.exit(1) + else: continue + #dynamically update our database + portage.db[portage.root]["bintree"].inject(x[2]) + mytbz2=portage.db[portage.root]["bintree"].getname(x[2]) + retval=portage.pkgmerge(mytbz2,myroot) + if retval==None: + if "--firstfail" in myopts: sys.exit(1) + else: continue + else: + retval=portage.doebuild(y,"clean",myroot,edebug) + if retval: + if "--firstfail" in myopts: sys.exit(1) + else: continue + retval=portage.doebuild(y,"merge",myroot,edebug) + if retval: + if "--firstfail" in myopts: sys.exit(1) + else: continue + #dynamically update our database + elif x[0]=="binary": + #merge the tbz2 mytbz2=portage.db[portage.root]["bintree"].getname(x[2]) - retval=portage.pkgmerge(mytbz2,myroot) + retval=portage.pkgmerge(mytbz2,x[1]) if retval==None: sys.exit(1) - else: + #need to check for errors + 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..." + portage.writedict(myfavdict,myroot+"var/cache/edb/world",writekey=0) + + if "--autoclean" in myopts: retval=portage.doebuild(y,"clean",myroot,edebug) if retval: sys.exit(1) - retval=portage.doebuild(y,"merge",myroot,edebug) - if retval: - sys.exit(1) - #dynamically update our database - elif x[0]=="binary": - #merge the tbz2 - mytbz2=portage.db[portage.root]["bintree"].getname(x[2]) - retval=portage.pkgmerge(mytbz2,x[1]) - if retval==None: - sys.exit(1) - #need to check for errors - 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..." - portage.writedict(myfavdict,myroot+"var/cache/edb/world",writekey=0) - - if "--autoclean" in myopts: - retval=portage.doebuild(y,"clean",myroot,edebug) - 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 portage.settings["AUTOCLEAN"] and (portage.settings["AUTOCLEAN"]=="yes"): - xsplit=portage.pkgsplit(x[2]) - emergelog(" >>> AUTOCLEAN: "+xsplit[0]) - if not unmerge("clean", [xsplit[0]]): - emergelog(" --- AUTOCLEAN: Nothing unmerged.") - emergelog(" ::: completed emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[2]+" to "+x[1]) - - mysplit=portage.pkgsplit(x[2]) - if mysplit[0]=="sys-apps/portage": - if mysplit[1]+"-"+mysplit[2]!=portage.VERSION: - if len(mymergelist) > mergecount: - myargv=sys.argv - myr=0 - for myra in range(len(myargv)): - print "Considering:",myargv[myr] - if myargv[myr][0:len("portage")]=="portage": - print "deleted:",myargv[myr] - del myargv[myr] - myr-=1 - if myargv[myr][0:len("sys-apps/portage")]=="sys-apps/portage": - print "deleted:",myargv[myr] - del myargv[myr] - myr-=1 - myr+=1 - emergelog(" *** RESTARTING emerge via exec() after change of portage version.") - os.execv("/usr/lib/portage/bin/emerge", myargv) + + if ("--pretend" not in myopts) and ("--fetchonly" not in myopts): + # Clean the old package that we have merged over top of it. + if portage.settings["AUTOCLEAN"] and (portage.settings["AUTOCLEAN"]=="yes"): + xsplit=portage.pkgsplit(x[2]) + emergelog(" >>> AUTOCLEAN: "+xsplit[0]) + if not unmerge("clean", [xsplit[0]]): + emergelog(" --- AUTOCLEAN: Nothing unmerged.") + emergelog(" ::: completed emerge ("+str(trycount)+" of "+str(len(mymergelist))+") "+x[2]+" to "+x[1]) + + mysplit=portage.pkgsplit(x[2]) + if mysplit[0]=="sys-apps/portage": + if mysplit[1]+"-"+mysplit[2]!=portage.VERSION: + if len(mymergelist) > trycount: + myargv=sys.argv + myr=0 + for myra in range(len(myargv)): + print "Considering:",myargv[myr] + if myargv[myr][0:len("portage")]=="portage": + print "deleted:",myargv[myr] + del myargv[myr] + myr-=1 + if myargv[myr][0:len("sys-apps/portage")]=="sys-apps/portage": + print "deleted:",myargv[myr] + del myargv[myr] + myr-=1 + myr+=1 + emergelog(" *** RESTARTING emerge via exec() after change of portage version.") + os.execv("/usr/lib/portage/bin/emerge", myargv) + mybuiltlist.append(x) + if mygraph!=None: mygraph.delnode(string.join(x)) + passmergecount+=1 + if len(mybuiltlist)==len(mymergelist): break + if "--retry" in myopts and passmergecount!=0: + passcount+=1 + continue + print "Some packages have not been built:" + for p in mymergelist: + if p in mybuiltlist: + print " "+p[2]+" successfully built" + else: + print " "+p[2]+" building failure" + sys.exit(1) - if ("--pretend" not in myopts) and (mergecount>0): + if ("--pretend" not in myopts) and (trycount>0): portage.env_update() @@ -1532,13 +1575,16 @@ print "Calculating dependencies ", retval,favorites=mydepgraph.select_files(myfiles) if not retval: - print "\n!!! Error calculating dependancies. Please correct." + print "\n!!! Error calculating dependencies. Please correct." sys.exit(1) print "\b\b ...done!" if ("--pretend" in myopts) and not ("--fetchonly" in myopts): mydepgraph.display(mydepgraph.altlist()) else: - mydepgraph.merge(mydepgraph.altlist()) + if "--retry" in myopts and not "--firstfail" in myopts: + mydepgraph.merge(mydepgraph.altlist(), mydepgraph.digraph) + else: + mydepgraph.merge(mydepgraph.altlist()) if portage.settings["AUTOCLEAN"] and "yes"==portage.settings["AUTOCLEAN"]: print ">>> Auto-cleaning packages ..." unmerge("clean", ["world"]) diff -Naurd ./bin/emergehelp.py ../portage-2.0.46-r4.new/bin/emergehelp.py --- ./bin/emergehelp.py 2002-12-24 10:05:48.000000000 +0000 +++ ../portage-2.0.46-r4.new/bin/emergehelp.py 2002-12-27 14:53:09.000000000 +0000 @@ -127,6 +127,9 @@ print " used in combination with --pretend all the SRC_URIs will be" print " displayed multiple mirrors per line, one line per file." print + print " "+green("--firstfail") + print " Stop merging as soon as any merge fails" + print print " "+green("--nodeps") print " Merge specified packages, but don't merge any dependencies." print " Note that the build may fail if deps aren't satisfied." @@ -158,6 +161,11 @@ print " When pretending, also display the ChangeLog entries for packages" print " that will be upgraded." print + print " "+green("--retry") + print " ignored if firstfail option is on" + print " retry to merge previously failed packages if i have managed to" + print " merge some packages (may fix some broken dependencies)" + print print " "+green("--searchdesc")+" ("+green("-S")+" short option)" print " Matches the search string against the description field as well" print " the package's name. Take caution as the descriptions are also" diff -Naurd ./pym/portage.py ../portage-2.0.46-r4.new/pym/portage.py --- ./pym/portage.py 2002-12-25 06:35:42.000000000 +0000 +++ ../portage-2.0.46-r4.new/pym/portage.py 2002-12-27 15:47:11.000000000 +0000 @@ -262,6 +262,22 @@ zerolist.append(x) return zerolist + def parents(self,mykey): + """ return parents of given node (None if given node does not exist""" + if self.dict.has_key(mykey): + return self.dict[mykey][1] + else: + return None + + def allroots(self,filterfunc=(lambda e: 1)): + """return all nodes having no dependency + dependencies having filterfunc() giving false are ignored""" + ret=dict(map((lambda p: [p, 1]), self.dict.keys())) + for dependency in filter(filterfunc, self.dict.keys()): + for depend_by in self.dict[dependency][1]: + ret[depend_by]=0 + return filter((lambda k: ret[k]==1), ret.keys()) + def empty(self): if len(self.dict)==0: return 1 @@ -277,6 +293,13 @@ mygraph.okeys=self.okeys[:] return mygraph + def __str__(self): + """useful for debugging""" + ret="" + for mykey in self.dict.keys(): + ret = ret+ str(mykey)+" => "+str(self.dict[mykey])+"\n" + return ret + # valid end of version components; integers specify offset from release version # pre=prerelease, p=patchlevel (should always be followed by an int), rc=release candidate # all but _p (where it is required) can be followed by an optional trailing integer