Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 37600 Details for
Bug 2938
unmerge should have a reverse dependency safety check
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Unified diff against 2.0.51_pre20
emerge-unmerge-rdep-v5.diff (text/plain), 10.27 KB, created by
Stephen Bennett (RETIRED)
on 2004-08-17 08:08:01 UTC
(
hide
)
Description:
Unified diff against 2.0.51_pre20
Filename:
MIME Type:
Creator:
Stephen Bennett (RETIRED)
Created:
2004-08-17 08:08:01 UTC
Size:
10.27 KB
patch
obsolete
>--- emerge.orig 2004-08-17 11:23:33.482194936 +0100 >+++ emerge 2004-08-17 11:52:31.465981240 +0100 >@@ -11,7 +11,7 @@ > from stat import * > from output import * > >-import portage >+import portage, portage_dep > import portage_util > import portage_locks > import portage_exception >@@ -35,7 +35,7 @@ > 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 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 >@@ -1820,6 +1820,220 @@ > else: > sys.exit(0) > >+# Helper function; I can't seem to find another function to do this... >+def cpv_satisfies_dep(cpv, atom): >+ # hack. Move along now. >+ #print "cpv_satisfies_dep:", cpv, atom >+ return ( len(portage.match_from_list(atom, [cpv])) > 0 ) >+ >+ >+class revdepgraph: >+ "A reverse dependency graph. What depends upon this package?" >+ >+ def __init__(self): >+ 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.digraph=portage.digraph() >+ >+ def potential_revdeps(self, cpv): >+ " Returns a list of tuples (cpv, depstring) that /might/ depend upon cpv. " >+ " Only considers run-time dependencies (RDEPEND). " >+ vardbapi=portage.db[self.myroot]["vartree"].dbapi >+ mycp=portage.pkgsplit(cpv)[0] >+ myprovide=vardbapi.aux_get(cpv, ["PROVIDE"])[0].split() >+ >+ myret=[] >+ for x in vardbapi.cpv_all(): >+ #myrawdep=string.join(vardbapi.aux_get(x,["DEPEND","RDEPEND","PDEPEND"]), " ") >+ myrawdep=string.join(vardbapi.aux_get(x,self.depvars), " ") >+ if string.find(myrawdep, mycp) != -1: >+ myret.append( (x,myrawdep) ) >+ for p in myprovide: >+ if string.find(myrawdep, p) != -1: >+ myret.append( (x,myrawdep) ) >+ #print "potential revdeps for "+cpv+":",map(lambda x:x[0],myret) >+ return myret >+ >+ def parse_dep(self, atom, cpv, others): >+ """ Returns 1 if cpv and no package in others will satisfy atom, 0 otherwise. >+ atom is either a DEPEND atom, or a list beginning with '||'. """ >+ if type(atom) is list: >+ # We have a '||' construct. >+ mylist = atom[:] >+ head = mylist.pop(0) >+ if head == "||": >+ # Does cpv satisfy any of the alternatives? If not, return 0. >+ if True not in map(lambda x:cpv_satisfies_dep(cpv,x), mylist): >+ return 0 >+ # cpv satisfies the || dep. Now check the others. >+ for p in others: >+ if True in map(lambda x:cpv_satisfies_dep(cpv,x), mylist): >+ # Another packages satisfies it. >+ return 0 >+ return 1 >+ else: >+ portage.writemsg("revdepgraph: parse_dep: don't understand " + str(atom) + ".\n") >+ raise ValueError, str(atom) >+ else: >+ #print "atom: " + atom >+ if portage.pkgsplit(portage.dep_getcpv(atom)): >+ mycp = portage.pkgsplit( portage.dep_getcpv(atom) )[0] >+ else: >+ mycp = atom >+ if mycp in portage.settings.virtuals.keys(): >+ #print "testing virtual",mycp >+ myop = portage.get_operator(atom) >+ if not myop: >+ # A virtual. Yay. >+ vardbapi = portage.db[self.myroot]["vartree"].dbapi >+ myprovide = vardbapi.aux_get(cpv, ["PROVIDE"])[0].split() >+ #print "myprovide:",myprovide >+ if mycp not in myprovide: >+ #print "mycp not in myprovide" >+ return 0 >+ for p in others: >+ myprovide = vardbapi.aux_get(p, ["PROVIDE"])[0].split() >+ if mycp in myprovide: >+ #print p,"satisfies virtual",mycp >+ return 0 >+ return 1 >+ else: >+ # A virtual with an operator. Even better. >+ vardbapi = portage.db[self.myroot]["vartree"].dbapi >+ myprovide = vardbapi.aux_get(cpv, ["PROVIDE"])[0].split() >+ if mycp not in myprovide: >+ return 0 >+ # It provides the right virtual; does it have the right version number? >+ mycpver,mycprev = portage.pkgsplit(cpv)[1:3] >+ # This is probably cleaner than switching through all the operators here... >+ if not cpv_satisfies_dep(mycp+"-"+mycpver+"-"+mycprev, atom): >+ return 0 >+ for p in others: >+ myprovide = vardbapi.aux_get(cpv, ["PROVIDE"])[0].split() >+ if mycp not in myprovide: >+ continue >+ myver,myrev = portage.pkgsplit(p)[1:3] >+ if cpv_satisfies_dep(mycp+"-"+myver+"-"+myrev, atom): >+ return 0 >+ return 1 >+ >+ else: >+ # A simple depend atom. >+ #print "Simple atom", atom >+ if not cpv_satisfies_dep(cpv, atom): >+ return 0 >+ for p in others: >+ if cpv_satisfies_dep(p, atom): >+ return 0 >+ return 1 >+ # Stick this here just in case... >+ return 0 >+ >+ def dep_flatten(self, dep): >+ " Flattens out every sublist not beginning with '||'. " >+ #print "attempting to flatten:", dep >+ returnme = [] >+ for x in dep: >+ #print "x:", x >+ if type(x) is list and len(x)>0 and x[0] != '||': >+ returnme = returnme + self.dep_flatten(x) >+ elif type(x) is not list: >+ returnme.append(x) >+ return returnme >+ >+ def workaround_broken_use_dep(self, myrawdep): >+ #return string.join(map((lambda x: (x[0]=='!' and x[-1]!='?') and x+'?' or x), string.split(myrawdep))) >+ #print "workaround: myrawdep=",myrawdep >+ mysplit=myrawdep.split() >+ for x in range(0, len(mysplit)-1): >+ if mysplit[x][0]=='!' and mysplit[x][-1]!='?' and mysplit[x+1]=='(': >+ mysplit[x] = mysplit[x]+'?' >+ #print mysplit >+ return string.join(mysplit) >+ >+ def direct_revdeps(self, cpv): >+ " Returns a list of first-level reverse dependencies on a given package. " >+ #print "calculating revdeps for " + cpv >+ vardbapi=portage.db[self.myroot]["vartree"].dbapi >+ myinstcpvs = vardbapi.cpv_all() >+ while cpv in myinstcpvs: >+ myinstcpvs.remove(cpv) >+ >+ myrevdeps = [] >+ >+ for myp,myrawdep in self.potential_revdeps(cpv): >+ # Check the rdepend string. Does it really require this package? >+ #print "checking " + myp >+ myuse = vardbapi.aux_get(myp, ["USE"])[0].split() >+ #print "mydep=", myrawdep >+ # use_reduce doesn't handle '!flag ( package )'; workaround >+ mydep = self.workaround_broken_use_dep(myrawdep) >+ #print "mydep=", mydep >+ mydep = portage_dep.paren_reduce(mydep) >+ mydep = portage_dep.dep_opconvert(mydep) >+ mydep = portage_dep.use_reduce(mydep,myuse) >+ #print "mydep=", mydep >+ # At this point we need to flatten out any sublist not beginning with '||'. >+ mydep = self.dep_flatten(mydep) >+ #print "mydep=", mydep >+ for myatom in mydep: >+ #print "Checking atom", myatom >+ if self.parse_dep(myatom, cpv, myinstcpvs): >+ # This package requires cpv. Add it to the list. >+ #print "Found revdep " + myp + " for " + cpv >+ myrevdeps.append(myp) >+ break >+ >+ return myrevdeps >+ >+ def create(self, cpv, myparent=None, addme=1, buildtimedeps=0): >+ """ Creates the digraph. This function is a good deal simpler than the normal depgraph creation, >+ since there are so many fewer possible scenarios to worry about. """ >+ #jbigkey = string.join(mybigkey) >+ #if self.digraph.hasnode(jbigkey+" unmerge"): >+ # return 1 >+ if self.digraph.hasnode(cpv): >+ return 1 >+ >+ if buildtimedeps: >+ self.depvars=["DEPEND","RDEPEND","PDEPEND"] >+ else: >+ self.depvars=["RDEPEND"] >+ update_spinner() >+ >+ #print "mybigkey: ", mybigkey >+ #mytype,myroot,mykey = mybigkey >+ #self.myroot = myroot >+ self.myroot = portage.root >+ #if mytype not in ["unmerge"]: >+ #portage.writemsg("Using revdeps for something other than unmerge?\n") >+ >+ # Check that mykey is valid... >+ if not portage.pkgsplit(cpv): >+ portage.writemsg("Invalid package key: " + cpv + "\n") >+ sys.exit(1) >+ >+ vardbapi = portage.db[self.myroot]["vartree"].dbapi >+ >+ if addme: >+ #print "adding '"+cpv+"'; parent=",myparent >+ #print self.digraph.allnodes() >+ self.digraph.addnode(cpv, myparent) >+ >+ for mydep in self.direct_revdeps(cpv): >+ self.create( mydep, cpv, 1 ) >+ >+ >+ def getpackages(self): >+ #return map(lambda x: string.split(x)[2], self.digraph.allnodes()) >+ return self.digraph.allnodes() >+ >+ > def unmerge(unmerge_action, unmerge_files): > candidate_catpkgs=[] > global_unmerge=0 >@@ -1906,6 +2120,14 @@ > > pkgmap={} > numselected=0 >+ if unmerge_action=="unmerge" and "--nodeps" not in myopts: >+ # Print the calculating deps message here, instead of once per package. >+ print >+ portage.writemsg("Calculating reverse dependencies ") >+ # Also create the revdepgraph here once, so that we can reuse it. Should be significantly >+ # more efficient when unmerging multiple packages. >+ myrdepgraph=revdepgraph() >+ > for x in candidate_catpkgs: > #cycle through all our candidate deps and determine what will and will not get unmerged > try: >@@ -1930,6 +2152,8 @@ > if not pkgmap.has_key(mykey): > pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] } > if unmerge_action=="unmerge": >+ if "--nodeps" in myopts: >+ # We're not interested in revdeps, so just add this package to the pkgmap. > for y in mymatch: > if y not in pkgmap[mykey]["selected"]: > pkgmap[mykey]["selected"].append(y) >@@ -1940,7 +2164,11 @@ > print yellow("\a!!! This could be damaging to your system.\n") > if "--pretend" not in myopts: > countdown(10,red("Press Ctrl-C to Stop")) >- >+ else: >+ # Add this package to the revdepgraph. >+ for y in mymatch: >+ myrdepgraph.create(y) >+ > else: > #unmerge_action in ["prune", clean"] > slotmap={} >@@ -1966,6 +2194,20 @@ > pkgmap[mykey]["selected"].append(slotmap[myslot][ckey]) > numselected=numselected+1 > #ok, now the last-merged package is protected, and the rest are selected >+ >+ if unmerge_action=="unmerge" and "--nodeps" not in myopts: >+ # Above, we didn't actually add packages to pkgmap, so we need to do that here. >+ print myrdepgraph.getpackages() >+ for x in myrdepgraph.getpackages(): >+ print x >+ mycp = portage.pkgsplit(x)[0] >+ if not pkgmap.has_key(mycp): >+ pkgmap[mycp]={"selected":[],"protected":[],"omitted":[]} >+ pkgmap[mycp]["selected"].append(x) >+ numselected = numselected+1 >+ >+ sys.stdout.write("\b\b ...done!\n\n") >+ > if global_unmerge and not numselected: > print "\n>>> No outdated packages were found on your system.\n" > return 0
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 2938
:
37600
|
39666
|
125536