if not hasattr(__builtins__, "set"):
from sets import Set as set
-from itertools import izip
+from itertools import chain, izip
class stdout_spinner(object):
scroll_msgs = [
self.settings.treeVirtuals = portage_util.map_dictlist_vals(
portage.getCPFromCPV, self.get_all_provides())
+def grab_global_updates(portdir):
+ from portage_update import grab_updates, parse_updates
+ updpath = os.path.join(portdir, "profiles", "updates")
+ try:
+ rawupdates = grab_updates(updpath)
+ except portage_exception.DirectoryNotFound:
+ rawupdates = []
+ upd_commands = []
+ for mykey, mystat, mycontent in rawupdates:
+ commands, errors = parse_updates(mycontent)
+ upd_commands.extend(commands)
+ return upd_commands
+
+def perform_global_updates(mycpv, mydb, mycommands):
+ from portage_update import update_dbentries
+ aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
+ aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
+ updates = update_dbentries(mycommands, aux_dict)
+ if updates:
+ mydb.aux_update(mycpv, updates)
+
class depgraph:
pkg_tree_map = {
self.spinner = spinner
self.pkgsettings = {}
self.pkg_node_map = {}
+ self.mydbapi = {}
+ self.useFlags = {}
self.trees = {}
for myroot in trees:
self.trees[myroot] = {}
self.pkgsettings[myroot] = portage.config(
clone=self.trees[myroot]["vartree"].settings)
self.pkg_node_map[myroot] = {}
+ vardb = self.trees[myroot]["vartree"].dbapi
+ # This fakedbapi instance will model the state that the vdb will
+ # have after new packages have been installed.
+ fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
+ self.mydbapi[myroot] = fakedb
+ for pkg in vardb.cpv_all():
+ myslot = vardb.aux_get(pkg, ["SLOT"])[0]
+ fakedb.cpv_inject(pkg, metadata={"SLOT":myslot})
+ del vardb, fakedb
+ self.useFlags[myroot] = {}
+ if "--usepkg" in self.myopts:
+ self.trees[myroot]["bintree"].populate(
+ "--getbinpkg" in self.myopts,
+ "--getbinpkgonly" in self.myopts)
del trees
- self.useFlags = {}
- self.useFlags[self.target_root] = {}
- if self.target_root != "/":
- self.useFlags["/"] = {}
self.missingbins=[]
self.digraph=portage.digraph()
self.orderedkeys=[]
self.outdatedpackages=[]
- self.mydbapi={}
- self.mydbapi["/"] = portage.fakedbapi(settings=settings)
- vardb = self.trees["/"]["vartree"].dbapi
- fakedb = self.mydbapi["/"]
- if "empty" not in self.myparams or self.target_root != "/":
- for pkg in vardb.cpv_all():
- myslot = vardb.aux_get(pkg, ["SLOT"])[0]
- fakedb.cpv_inject(pkg, metadata={"SLOT":myslot})
- if self.target_root != "/":
- self.mydbapi[self.target_root] = \
- portage.fakedbapi(settings=settings)
- vardb = self.trees[self.target_root]["vartree"].dbapi
- fakedb = self.mydbapi[self.target_root]
- if "empty" not in self.myparams:
- for pkg in vardb.cpv_all():
- myslot = vardb.aux_get(pkg, ["SLOT"])[0]
- fakedb.cpv_inject(pkg, metadata={"SLOT":myslot})
- if "--usepkg" in self.myopts:
- self.trees["/"]["bintree"].populate(
- "--getbinpkg" in self.myopts, "--getbinpkgonly" in self.myopts)
- if self.target_root != "/":
- self.trees[self.target_root]["bintree"].populate(
- "--getbinpkg" in self.myopts,
- "--getbinpkgonly" in self.myopts)
self.args_keys = []
self.global_updates = {}
self.blocker_digraph = digraph()
#IUSE-aware emerge -> USE DEP aware depgraph
#"no downgrade" emerge
"""
- jbigkey = " ".join(mybigkey) + " merge"
+ jbigkey = tuple(chain(mybigkey, ["merge"]))
mytype, myroot, mykey = mybigkey
if self.digraph.hasnode(jbigkey):
if addme and jbigkey != myparent:
# don't create a bogus circular dependency in self.altlist().
self.pkg_node_map[myroot][mykey] = jbigkey
if rev_dep and myparent:
- ptype, proot, pkey, pstatus = myparent.split()
+ ptype, proot, pkey, pstatus = myparent
self.pkg_node_map[proot][pkey] = myparent
self.digraph.addnode(myparent, jbigkey, priority=priority)
else:
self.digraph.addnode(jbigkey, myparent, priority=priority)
return 1
- jbigkey = " ".join(mybigkey) + " nomerge"
+ jbigkey = tuple(chain(mybigkey, ["nomerge"]))
if self.digraph.hasnode(jbigkey):
self.pkg_node_map[myroot][mykey] = jbigkey
if rev_dep and myparent:
- ptype, proot, pkey, pstatus = myparent.split()
+ ptype, proot, pkey, pstatus = myparent
self.pkg_node_map[proot][pkey] = myparent
self.digraph.addnode(myparent, jbigkey, priority=priority)
else:
self.spinner.update()
if mytype == "blocks":
if addme and "--buildpkgonly" not in self.myopts and myparent:
- mybigkey[1] = myparent.split()[1]
+ mybigkey[1] = myparent[1]
self.blocker_parents.setdefault(
- " ".join(mybigkey), set()).add(myparent)
+ tuple(mybigkey), set()).add(myparent)
return 1
if not arg and myroot == self.target_root:
arg = portage.best_match_to_list(mykey, self.args_keys)
""" At this point, we have either hit a blocker and returned, found the package in the
depgraph already and returned, or we are here. Whether we are merging or not; we must
add the package to the depgraph; so we do that here. """
- jbigkey = " ".join(mybigkey)
+ jbigkey = tuple(mybigkey)
self.pkg_node_map[myroot][mykey] = jbigkey
if rev_dep and myparent:
- ptype, proot, pkey, pstatus = myparent.split()
+ ptype, proot, pkey, pstatus = myparent
self.pkg_node_map[proot][pkey] = myparent
self.digraph.addnode(myparent, jbigkey,
priority=priority)
""" We have retrieve the dependency information, now we need to recursively
process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
- mp=string.join(mybigkey)
+ mp = tuple(mybigkey)
try:
if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
missing=0
if "--usepkgonly" in self.myopts:
- for x in self.digraph.all_nodes():
- xs = x.split()
+ for xs in self.digraph.all_nodes():
if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
if missing == 0:
print
# virtuals, which are preferenced in dep_zapdeps by looking only at
# the depstring, vdb, and available packages.
- p_type, p_root, p_key, p_status = myparent.split()
+ p_type, p_root, p_key, p_status = myparent
if p_status == "merge":
# Update old-style virtuals if this package provides any.
# These are needed for dep_virtual calls inside dep_check.
This is done on the fly for single packages only when
necessary, since it can be time consuming to run this
on all installed packages."""
- from portage_update import grab_updates, \
- parse_updates, update_dbentries
if myroot not in self.global_updates:
- updpath = os.path.join(
- pkgsettings["PORTDIR"], "profiles", "updates")
- try:
- rawupdates = grab_updates(updpath)
- except portage_exception.DirectoryNotFound:
- rawupdates = []
- upd_commands = []
- for mykey, mystat, mycontent in rawupdates:
- commands, errors = parse_updates(mycontent)
- upd_commands.extend(commands)
- del updpath, rawupdates
- self.global_updates[myroot] = upd_commands
- upd_commands = self.global_updates[myroot]
- aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
- aux_vals = vardb.aux_get(myeb_inst, aux_keys)
- aux_dict = dict(izip(aux_keys, aux_vals))
- updates = update_dbentries(upd_commands, aux_dict)
- if updates:
- vardb.aux_update(myeb_inst, updates)
- del binpkguseflags, myeb_inst, upd_commands, \
- aux_keys, aux_vals, aux_dict, updates
+ self.global_updates[myroot] = \
+ grab_global_updates(pkgsettings["PORTDIR"])
+ perform_global_updates(
+ myeb_inst, vardb, self.global_updates[myroot])
if not matched_packages:
if raise_on_missing:
else:
xinfo='"'+arg+'"'
if myparent:
- xfrom = '(dependency required by '+green('"'+myparent.split()[2]+'"')+red(' ['+myparent.split()[0]+"]")+')'
+ xfrom = '(dependency required by '+ \
+ green('"%s"' % myparent[2]) + \
+ red(' [%s]' % myparent[0]) + ')'
alleb = portdb.xmatch("match-all", x)
if alleb:
if "--usepkgonly" not in self.myopts:
installed simultaneously."""
for blocker in self.blocker_parents.keys():
- mytype, myroot, mydep = blocker.split()
+ mytype, myroot, mydep = blocker
vardb = self.trees[myroot]["vartree"].dbapi
blocked_pkgs = vardb.match(mydep)
blocked_after_update = self.mydbapi[myroot].match(mydep)
continue
for parent in list(self.blocker_parents[blocker]):
- ptype, proot, pcpv, pstatus = parent.split()
+ ptype, proot, pcpv, pstatus = parent
pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
sys.exit(1)
for node in selected_nodes:
- retlist.append(node.split())
+ retlist.append(list(node))
mygraph.remove(node)
if not reversed and not circular_blocks and myblockers.contains(node):
"""This node may have invalidated one or more blockers."""
""" Add any unresolved blocks so that they can be displayed."""
for blocker in self.blocker_parents:
- retlist.append(blocker.split())
+ retlist.append(list(blocker))
self._altlist_cache[reversed] = retlist[:]
return retlist
return 1
- def match(self, mydep, myroot=None, mykey=None):
- # support mutual exclusive deps
- if myroot is None:
- myroot = self.target_root
- mydep2=mydep
- if mydep2[0]=="!":
- mydep2=mydep[1:]
-
- 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 = self.trees[myroot]["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 self.myopts:
- mypk = self.trees[myroot]["bintree"].dep_bestmatch(mydep)
- if myeb==mypk:
- myk = " ".join(("binary", myroot, mypk))
- else:
- myk = " ".join(("ebuild", myroot, myeb))
- else:
- myk="ebuild "+myroot+" "+myeb
-
- return myk
-
def display(self,mylist,verbosity=None):
if verbosity is None:
verbosity = ("--quiet" in self.myopts and 1 or \
for x in mylist:
if "blocks" == x[0]:
continue
- graph_key = " ".join(x)
+ graph_key = tuple(x)
if "--tree" in self.myopts:
depth = len(tree_nodes)
while depth and graph_key not in \
for i in xrange(len(mylist)-1,-1,-1):
if "blocks" == mylist[i][0]:
continue
- graph_key = " ".join(mylist[i])
+ graph_key = tuple(mylist[i])
if mylist[i][-1] != "nomerge":
last_merge_depth = node_depth[graph_key]
continue
if node_depth[graph_key] >= last_merge_depth or \
i < len(mylist) - 1 and \
- node_depth[graph_key] >= node_depth[" ".join(mylist[i+1])]:
+ node_depth[graph_key] >= node_depth[tuple(mylist[i+1])]:
del mylist[i]
del node_depth[graph_key]
del tree_nodes
resolved = portage.key_expand(
pkg_key, mydb=vardb, settings=pkgsettings)
print "["+x[0]+" "+addl+"]",red(resolved),
- block_parents = self.blocker_parents[" ".join(x)]
- block_parents = [pnode.split()[2] for pnode in block_parents]
+ block_parents = self.blocker_parents[tuple(x)]
+ block_parents = [pnode[2] for pnode in block_parents]
block_parents = ", ".join(block_parents)
if resolved!=x[2]:
print bad("(\"%s\" is blocking %s)") % \
oldlp=mywidth-30
newlp=oldlp-30
- indent = " " * node_depth[" ".join(x)]
+ indent = " " * node_depth[tuple(x)]
if myoldbest:
myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
fake_vardb = portage.fakedbapi(settings=settings)
fakedb_auxkeys = aux_keys[:]
fakedb_auxkeys.append("SLOT")
+ global_updates = None
for cpv in myvarlist:
try:
# Prefer live ebuild metadata when available.
aux_vals = portdb.aux_get(cpv, fakedb_auxkeys)
+ live_ebuild = True
except KeyError:
aux_vals = vardb.aux_get(cpv, fakedb_auxkeys)
+ live_ebuild = False
fake_vardb.cpv_inject(
cpv, metadata=dict(izip(fakedb_auxkeys, aux_vals)))
+ if not live_ebuild:
+ if global_updates is None:
+ global_updates = grab_global_updates(settings["PORTDIR"])
+ perform_global_updates(cpv, fake_vardb, global_updates)
+
# HACK: Ensure that installed packages are preferenced by dep_check().
trees[settings["ROOT"]]["porttree"].dbapi = fake_vardb
if myslot and mycp in self.cpdict:
# If necessary, remove another package in the same SLOT.
for cpv in self.cpdict[mycp]:
- if mycpv != cpv and myslot == self.cpvdict[cpv]:
- self.cpv_remove(cpv)
- break
+ if mycpv != cpv:
+ other_metadata = self.cpvdict[cpv]
+ if other_metadata:
+ if myslot == other_metadata.get("SLOT", None):
+ self.cpv_remove(cpv)
+ break
if mycp not in self.cpdict:
self.cpdict[mycp] = []
if not mycpv in self.cpdict[mycp]:
if not self.bintree.populated:
self.bintree.populate()
tbz2path = self.bintree.getname(cpv)
- mylock = portage_locks.lockfile(tbz2path, wantnewlockfile=1)
- try:
- if not os.path.exists(tbz2path):
- raise KeyError(cpv)
- mytbz2 = xpak.tbz2(tbz2path)
- mydata = mytbz2.get_data()
- mydata.update(values)
- mytbz2.recompose_mem(xpak.xpak_mem(mydata))
- finally:
- portage_locks.unlockfile(mylock)
+ if not os.path.exists(tbz2path):
+ raise KeyError(cpv)
+ mytbz2 = xpak.tbz2(tbz2path)
+ mydata = mytbz2.get_data()
+ mydata.update(values)
+ mytbz2.recompose_mem(xpak.xpak_mem(mydata))
def cp_list(self, *pargs, **kwargs):
if not self.bintree.populated:
return self.root+VDB_PATH+"/"+str(mycpv)+"/"+mycpv.split("/")[1]+".ebuild"
def aux_get(self, mycpv, wants):
- global auxdbkeys
+ mydir = os.path.join(self.root, VDB_PATH, mycpv)
+ if not os.path.isdir(mydir):
+ raise KeyError(mycpv)
results = []
for x in wants:
- myfn = self.root+VDB_PATH+"/"+str(mycpv)+"/"+str(x)
try:
- myf = open(myfn, "r")
- myd = myf.read()
- myf.close()
- myd = re.sub("[\n\r\t]+"," ",myd)
- myd = re.sub(" +"," ",myd)
- myd = string.strip(myd)
- except (IOError, OSError):
+ myf = open(os.path.join(mydir, x), "r")
+ try:
+ myd = myf.read()
+ finally:
+ myf.close()
+ myd = " ".join(myd.split())
+ except IOError:
myd = ""
- results.append(myd)
- if "EAPI" in wants:
- idx = wants.index("EAPI")
- if not results[idx]:
- results[idx] = "0"
+ if x == "EAPI" and not myd:
+ results.append("0")
+ else:
+ results.append(myd)
return results
def aux_update(self, cpv, values):
cat, pkg = cpv.split("/")
mylink = dblink(cat, pkg, self.root, self.settings,
- treetype="vartree", vartree=self.vartree)
- try:
- mylink.lockdb()
- except portage_exception.DirectoryNotFound:
+ treetype="vartree", vartree=self.vartree)
+ if not mylink.exists():
raise KeyError(cpv)
- try:
- if not mylink.exists():
- raise KeyError(cpv)
- for k, v in values.iteritems():
- mylink.setfile(k, v)
- finally:
- mylink.unlockdb()
+ for k, v in values.iteritems():
+ mylink.setfile(k, v)
def counter_tick(self,myroot,mycpv=None):
return self.counter_tick_core(myroot,incrementing=1,mycpv=mycpv)