missing += 1
print "Missing binary for:",xs[2]
- self.validate_blockers()
+ if not self.validate_blockers():
+ return False, myfavorites
# We're true here unless we are missing binaries.
return (not missing,myfavorites)
correct merge order such that mutually blocking packages are never
installed simultaneously."""
+ #if "deep" in self.myparams:
+ if True:
+ # Pull in blockers from all installed packages that haven't already
+ # been pulled into the depgraph. This is not enabled by default
+ # due to the performance penalty that is incurred by all the
+ # additional dep_check calls that are required.
+ dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
+ for myroot in self.trees:
+ pkg_node_map = self.pkg_node_map[myroot]
+ vardb = self.trees[myroot]["vartree"].dbapi
+ portdb = self.trees[myroot]["porttree"].dbapi
+ pkgsettings = self.pkgsettings[myroot]
+ final_db = self.mydbapi[myroot]
+ for pkg in self.trees[myroot]["vartree"].dbapi.cpv_all():
+ blocker_atoms = None
+ matching_node = pkg_node_map.get(pkg, None)
+ if not matching_node or \
+ matching_node[3] == "merge":
+ # If this node has any blockers, create a "nomerge"
+ # node for it so that they can be enforced.
+ self.spinner.update()
+ try:
+ dep_vals = portdb.aux_get(pkg, dep_keys)
+ ptype = "ebuild"
+ except KeyError:
+ if myroot not in self.global_updates:
+ self.global_updates[myroot] = \
+ grab_global_updates(pkgsettings["PORTDIR"])
+ perform_global_updates(
+ pkg, vardb, self.global_updates[myroot])
+ dep_vals = vardb.aux_get(pkg, dep_keys)
+ ptype = "installed"
+ myuse = vardb.aux_get(pkg, ["USE"])[0]
+ depstr = " ".join(dep_vals)
+ # It is crucial to pass in final_db here in order to
+ # optimize dep_check calls by eliminating atoms via
+ # dep_wordreduce and dep_eval calls.
+ success, atoms = portage.dep_check(depstr, final_db,
+ pkgsettings, myuse=myuse, trees=self.trees,
+ myroot=myroot)
+ if not success:
+ print "\n\n"
+ print "Error occurred while processing",pkg
+ print str(atoms)
+ return False
+ blocker_atoms = [myatom for myatom in atoms \
+ if myatom.startswith("!")]
+ if blocker_atoms:
+ # Don't store this parent in pkg_node_map, because it's
+ # not needed there and it might overwrite a "merge"
+ # node with the same cpv.
+ myparent = (ptype, myroot, pkg, "nomerge")
+ for myatom in blocker_atoms:
+ blocker = ("blocks", myroot, myatom[1:])
+ myparents = \
+ self.blocker_parents.get(blocker, None)
+ if not myparents:
+ myparents = set()
+ self.blocker_parents[blocker] = myparents
+ myparents.add(myparent)
+
for blocker in self.blocker_parents.keys():
mytype, myroot, mydep = blocker
initial_db = self.trees[myroot]["vartree"].dbapi
# Validate blockers that depend on merge order.
if not self.blocker_digraph.empty():
self.altlist()
+ return True
def altlist(self, reversed=False):
if reversed in self._altlist_cache:
except ValueError:
missing_atoms.append(mydep)
- self.validate_blockers()
+ if not self.validate_blockers():
+ return False
if world_problems:
print >> sys.stderr, "\n!!! Problems have been detected with your world file"
pkg_key, mydb=vardb, settings=pkgsettings)
print "["+x[0]+" "+addl+"]",red(resolved),
block_parents = self.blocker_parents[tuple(x)]
- block_parents = [pnode[2] for pnode in block_parents]
+ block_parents = set([pnode[2] for pnode in block_parents])
block_parents = ", ".join(block_parents)
if resolved!=x[2]:
print bad("(\"%s\" is blocking %s)") % \
try:
# Prefer live ebuild metadata when available.
aux_vals = portdb.aux_get(cpv, fakedb_auxkeys)
+ # SLOT always comes from the vardb, for multislot.
+ aux_vals[-1] = vardb.aux_get(cpv, ["SLOT"])[0]
live_ebuild = True
except KeyError:
aux_vals = vardb.aux_get(cpv, fakedb_auxkeys)
return mydep
if mydep[0]=="*":
mydep=mydep[1:]
- prefix=""
- postfix=""
- if mydep[-1]=="*":
- mydep=mydep[:-1]
- postfix="*"
- if mydep[:2] in [ ">=", "<=" ]:
- prefix=mydep[:2]
- mydep=mydep[2:]
- elif mydep[:1] in "=<>~!":
- prefix=mydep[:1]
- mydep=mydep[1:]
- colon = mydep.rfind(":")
- if colon != -1:
- postfix = mydep[colon:]
- mydep = mydep[:colon]
+ orig_dep = mydep
+ mydep = dep_getcpv(orig_dep)
+ myindex = orig_dep.index(mydep)
+ prefix = orig_dep[:myindex]
+ postfix = orig_dep[myindex+len(mydep):]
return prefix + cpv_expand(
mydep, mydb=mydb, use_cache=use_cache, settings=settings) + postfix
mykey=myslash[0]+"/"+mysplit[0]
else:
mykey=mycpv
- if mydb:
+ if mydb and virts and mykey in virts:
writemsg("mydb.__class__: %s\n" % (mydb.__class__), 1)
if type(mydb)==types.InstanceType:
- if (not mydb.cp_list(mykey,use_cache=use_cache)) and virts and virts.has_key(mykey):
+ if not mydb.cp_list(mykey, use_cache=use_cache):
writemsg("virts[%s]: %s\n" % (str(mykey),virts[mykey]), 1)
mykey_orig = mykey[:]
for vkey in virts[mykey]:
if settings is None:
settings = globals()["settings"]
self.settings = settings
+ self._match_cache = {}
+
+ def _clear_cache(self):
+ if self._match_cache:
+ self._match_cache = {}
+
+ def match(self, origdep, use_cache=1):
+ result = self._match_cache.get(origdep, None)
+ if result is not None:
+ return result[:]
+ result = dbapi.match(self, origdep, use_cache=use_cache)
+ self._match_cache[origdep] = result
+ return result[:]
def cpv_exists(self,mycpv):
return self.cpvdict.has_key(mycpv)
def cpv_inject(self, mycpv, metadata=None):
"""Adds a cpv from the list of available packages."""
+ self._clear_cache()
mycp=cpv_getkey(mycpv)
self.cpvdict[mycpv] = metadata
myslot = None
def cpv_remove(self,mycpv):
"""Removes a cpv from the list of available packages."""
+ self._clear_cache()
mycp=cpv_getkey(mycpv)
if self.cpvdict.has_key(mycpv):
del self.cpvdict[mycpv]
return [metadata.get(x, "") for x in wants]
def aux_update(self, cpv, values):
+ self._clear_cache()
self.cpvdict[cpv].update(values)
class bindbapi(fakedbapi):
if settings is None:
settings = globals()["settings"]
self.settings = settings
+ self._match_cache = {}
def match(self, *pargs, **kwargs):
if self.bintree and not self.bintree.populated:
return operator
+_dep_getcpv_cache = {}
+
def dep_getcpv(mydep):
"""
Return the category-package-version with any operators/slot specifications stripped off
@rtype: String
@return: The depstring with the operator removed
"""
+ global _dep_getcpv_cache
+ retval = _dep_getcpv_cache.get(mydep, None)
+ if retval is not None:
+ return retval
+ mydep_orig = mydep
if mydep and mydep[0] == "*":
mydep = mydep[1:]
if mydep and mydep[-1] == "*":
mydep = mydep[1:]
colon = mydep.rfind(":")
if colon != -1:
- return mydep[:colon]
+ mydep = mydep[:colon]
+ _dep_getcpv_cache[mydep_orig] = mydep
return mydep
def dep_getslot(mydep):
bestm = x
return bestm
+_match_from_list_cache = {}
+
def match_from_list(mydep, candidate_list):
"""
Searches list for entries that matches the package.
@return: A list of package atoms that match the given package atom
"""
+ global _match_from_list_cache
+ mylist = _match_from_list_cache.get((mydep, tuple(candidate_list)), None)
+ if mylist is not None:
+ return mylist[:]
+
from portage_util import writemsg
if mydep[0] == "!":
mydep = mydep[1:]
else:
raise KeyError("Unknown operator: %s" % mydep)
+ _match_from_list_cache[(mydep, tuple(candidate_list))] = mylist
return mylist