if not hasattr(__builtins__, "set"):
from sets import Set as set
from itertools import chain, izip
+from UserDict import DictMixin
+
+try:
+ import cPickle
+except ImportError:
+ import pickle as cPickle
class stdout_spinner(object):
scroll_msgs = [
continue
slot_counters[myslot_atom] = mycounter
self.dbapi.cpv_inject(cpv, metadata=metadata)
+ real_dbapi.flush_cache()
finally:
if vdb_lock:
portage_locks.unlockdir(vdb_lock)
if updates:
mydb.aux_update(mycpv, updates)
+class BlockerCache(DictMixin):
+ """This caches blockers of installed packages so that dep_check does not
+ have to be done for every single installed package on every invocation of
+ emerge. The cache is invalidated whenever it is detected that something
+ has changed that might alter the results of dep_check() calls:
+ 1) the set of installed packages (including COUNTER) has changed
+ 2) the old-style virtuals have changed
+ """
+ class BlockerData(object):
+ def __init__(self, counter, atoms):
+ self.counter = counter
+ self.atoms = atoms
+
+ def __init__(self, myroot, vardb):
+ self._vardb = vardb
+ self._installed_pkgs = set(vardb.cpv_all())
+ self._virtuals = vardb.settings.getvirtuals()
+ self._cache_filename = os.path.join(myroot,
+ portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
+ self._cache_version = "1"
+ self._cache_data = None
+ self._modified = False
+ self._load()
+
+ def _load(self):
+ try:
+ f = open(self._cache_filename)
+ mypickle = cPickle.Unpickler(f)
+ mypickle.find_global = None
+ self._cache_data = mypickle.load()
+ f.close()
+ del f
+ except (IOError, OSError, EOFError, cPickle.UnpicklingError):
+ pass
+ cache_valid = self._cache_data and \
+ isinstance(self._cache_data, dict) and \
+ self._cache_data.get("version") == self._cache_version and \
+ self._cache_data["virtuals"] == self._virtuals and \
+ set(self._cache_data["blockers"]) == self._installed_pkgs
+ if cache_valid:
+ for pkg in self._installed_pkgs:
+ if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
+ self[pkg].counter:
+ cache_valid = False
+ break
+ if not cache_valid:
+ self._cache_data = {"version":self._cache_version}
+ self._cache_data["blockers"] = {}
+ self._cache_data["virtuals"] = self._virtuals
+ self._modified = False
+
+ def flush(self):
+ """If the current user has permission and the internal blocker cache
+ been updated, save it to disk and mark it unmodified. This is called
+ by emerge after it has proccessed blockers for all installed packages.
+ Currently, the cache is only written if the user has superuser
+ privileges (since that's required to obtain a lock), but all users
+ have read access and benefit from faster blocker lookups (as long as
+ the entire cache is still valid). The cache is stored as a pickled
+ dict object with the following format:
+
+ {
+ version : "1",
+ "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
+ "virtuals" : vardb.settings.getvirtuals()
+ }
+ """
+ if self._modified and \
+ secpass >= 2:
+ try:
+ f = portage_util.atomic_ofstream(self._cache_filename)
+ cPickle.dump(self._cache_data, f, -1)
+ f.close()
+ portage_util.apply_secpass_permissions(
+ self._cache_filename, gid=portage.portage_gid, mode=0644)
+ except (IOError, OSError), e:
+ pass
+ self._modified = False
+
+ def __setitem__(self, cpv, blocker_data):
+ """
+ Update the cache and mark it as modified for a future call to
+ self.flush().
+
+ @param cpv: Package for which to cache blockers.
+ @type cpv: String
+ @param blocker_data: An object with counter and atoms attributes.
+ @type blocker_data: BlockerData
+ """
+ self._cache_data["blockers"][cpv] = \
+ (blocker_data.counter, blocker_data.atoms)
+ self._modified = True
+
+ def __getitem__(self, cpv):
+ """
+ @rtype: BlockerData
+ @returns: An object with counter and atoms attributes.
+ """
+ return self.BlockerData(*self._cache_data["blockers"][cpv])
def show_invalid_depstring_notice(parent_node, depstring, error_msg):
self.args_keys = []
self.blocker_digraph = digraph()
self.blocker_parents = {}
+ self._slot_collision_info = []
self._altlist_cache = {}
self._pprovided_args = []
priority=priority)
return 1
else:
+ # A slot collision has occurred. Sometimes this coincides
+ # with unresolvable blockers, so the slot collision will be
+ # shown later if there are no unresolvable blockers.
e_parents = self._parent_child_digraph.parent_nodes(
existing_node)
myparents = []
if myparent:
myparents.append(myparent)
- self._show_slot_collision_notice(
- ((jbigkey, myparents),
- (existing_node, e_parents)))
- return 0
+ self._slot_collision_info.append(
+ ((jbigkey, myparents), (existing_node, e_parents)))
+
+ # Now add this node to the graph so that self.display()
+ # can work with it show use flags and --tree output.
+ self.useFlags[myroot][mykey] = myuse
+ self._parent_child_digraph.add(jbigkey, myparent)
+ if rev_dep and myparent:
+ self.digraph.add(myparent, jbigkey,
+ priority=priority)
+ else:
+ self.digraph.add(jbigkey, myparent,
+ priority=priority)
+ # The slot collision has rendered the graph invalid, so
+ # there's no need to process dependencies of this node.
+ return 1
self._slot_node_map[myroot][slot_atom] = jbigkey
self.pkg_node_map[myroot][mykey] = jbigkey
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():
+ cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
+ blocker_cache = BlockerCache(myroot, vardb)
+ for pkg in cpv_all_installed:
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()
+ if matching_node and \
+ matching_node[3] == "nomerge":
+ continue
+ # If this node has any blockers, create a "nomerge"
+ # node for it so that they can be enforced.
+ self.spinner.update()
+ blocker_data = blocker_cache.get(pkg)
+ if blocker_data:
+ blocker_atoms = blocker_data.atoms
+ else:
dep_vals = vardb.aux_get(pkg, dep_keys)
myuse = vardb.aux_get(pkg, ["USE"])[0].split()
depstr = " ".join(dep_vals)
return False
blocker_atoms = [myatom for myatom in atoms \
if myatom.startswith("!")]
+ counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
+ blocker_cache[pkg] = \
+ blocker_cache.BlockerData(counter, blocker_atoms)
if blocker_atoms:
# Don't store this parent in pkg_node_map, because it's
# not needed there and it might overwrite a "merge"
myparents = set()
self.blocker_parents[blocker] = myparents
myparents.add(myparent)
+ blocker_cache.flush()
+ del blocker_cache
for blocker in self.blocker_parents.keys():
mytype, myroot, mydep = blocker
# Validate blockers that depend on merge order.
if not self.blocker_digraph.empty():
self.altlist()
+ if self._slot_collision_info:
+ # The user is only notified of a slot collision if there are no
+ # unresolvable blocks.
+ for x in self.altlist():
+ if x[0] == "blocks":
+ return True
+ self._show_slot_collision_notice(self._slot_collision_info[0])
+ return False
return True
def altlist(self, reversed=False):
unset_vars = []
myvars.sort()
for x in myvars:
- if settings.has_key(x):
- print x+'="'+settings[x]+'"'
+ if x in settings:
+ if x != "USE":
+ print '%s="%s"' % (x, settings[x])
+ else:
+ use = set(settings["USE"].split())
+ use_expand = settings["USE_EXPAND"].split()
+ use_expand.sort()
+ for varname in use_expand:
+ flag_prefix = varname.lower() + "_"
+ for f in list(use):
+ if f.startswith(flag_prefix):
+ use.remove(f)
+ print 'USE="%s"' % " ".join(use),
+ for varname in use_expand:
+ myval = settings.get(varname)
+ if myval:
+ print '%s="%s"' % (varname, myval),
+ print
else:
unset_vars.append(x)
if unset_vars:
if [[ -s ${T}/debug.sources ]] ; then
[[ -d ${ED}${sources_dir} ]] || mkdir -p "${ED}${sources_dir}"
cat "${T}"/debug.sources | (cd "${WORKDIR}"; LANG=C sort -z -u | \
- rsync -aL0 --files-from=- "${WORKDIR}/" "${ED}${sources_dir}/" )
+ rsync -rtL0 --files-from=- "${WORKDIR}/" "${ED}${sources_dir}/" )
fi
fi
-.TH "EMERGE" "1" "Dec 2005" "Portage 2.1" "Portage"
+.TH "EMERGE" "1" "Dec 2006" "Portage 2.1" "Portage"
.SH "NAME"
emerge \- Command\-line interface to the Portage system
.SH "SYNOPSIS"
.TP
.BR emerge
-[\fIoptions\fR] [\fIaction\fR] [\fIebuild\fR | \fItbz2file\fR | \fIset\fR | \fIdependency\fR] ...
+[\fIoptions\fR] [\fIaction\fR] [\fIebuild\fR | \fItbz2file\fR | \fIset\fR | \fIatom\fR] ...
.TP
.BR emerge
\fB\-\-sync\fR | \fB\-\-info\fR | \fB\-\-version\fR
.SH "EBUILDS, TBZ2S, SETS AND DEPENDENCIES"
\fBemerge\fR primarily installs packages. You can specify
packages to install in one of four main ways: an \fIebuild\fR,
-a \fItbz2file\fR, a \fIset\fR, or a \fIdependency\fR.
+a \fItbz2file\fR, a \fIset\fR, or a \fIatom\fR.
.LP
.TP
.BR ebuild
\fBFILES\fR below for more information.] Note that a \fIset\fR
is generally used in conjunction with \fB\-\-update\fR.
.TP
-.BR dependency
-A \fIdependency\fR describes bounds on a package that you wish to install.
-\fISee portage(5) for the details on these 'atoms'.\fR For example,
+.BR atom
+An \fIatom\fR describes bounds on a package that you wish to install.
+\fISee portage(5) for the details on atom syntax.\fR For example,
\fB>=dev\-lang/python\-2.2.1\-r2\fR matches the latest available version of
Python greater than or equal to 2.2.1\-r2. Similarly,
\fB<dev\-lang/python\-2.0\fR matches the latest available version of Python
before 2.0. Note that in many shells you will need to escape characters such
-as '<' and '='; use single\- or double\-quotes around the \fIdependency\fR
+as '<' and '='; use single\- or double\-quotes around the \fIatom\fR
to get around escaping problems.
.SH "ACTIONS"
.TP
If no action is specified, the action is to merge in the specified
packages, satisfying any dependencies that they may have. The
arguments can be \fIebuilds\fR, \fItbz2s\fR, \fIsets\fR, or
-\fIdependencies\fR. \fBNote that you need to use the \-\-usepkg
+\fIatoms\fR. \fBNote that you need to use the \-\-usepkg
option if you want to install a tbz2\fR. The packages are added
to the \fBworld\fR file at the end, so that they are considered for
-later updating.
+later updating.
.TP
.BR "\-\-clean " (\fB\-c\fR)
-Cleans the system by removing packages that will not affect the
-functionality of the system. The arguments can be \fIebuilds\fR,
-\fIsets\fR, or \fIdependencies\fR. For example, \fBemerge
---clean binutils\fR cleans out old versions of binutils;
-\fBemerge \-\-clean net\-www/mozilla\-0.9.9\-r2\fR cleans out that
-specific version of Mozilla. This is generally safe to use.
-\fBNote that\fR \-\-clean \fBdoes not remove unslotted packages.\fR
+Cleans up the system by examining the installed packages and removing older
+packages. This is accomplished by looking at each installed package and separating
+the installed versions by \fBslot\fR. Clean will \fBremove all but the most recently
+installed version in each \fbslot\fR. Clean should not remove unslotted packages.
+Note: Most recently installed means most \fBrecent\fR, not highest version.
.TP
.BR "\-\-config "
Run package specific actions needed to be executed after the emerge process
with the \fI\-\-verbose\fR option.
.TP
.BR \-\-metadata
-Causes portage to process all the metacache files as is normally done on the
-tail end of an rsync update using \fBemerge \-\-sync\fR. The processing
-creates the cache database that portage uses for pre\-parsed lookups of
-package data.
+Transfers metadata cache from ${PORTDIR}/metadata/cache/ to
+/var/cache/edb/dep/ as is normally done on the
+tail end of an rsync update using \fBemerge \-\-sync\fR. This process
+populates the cache database that portage uses for pre-parsed lookups of
+package data. It does not populate cache for the overlays listed in
+PORTDIR_OVERLAY. In order to generate cache for overlays, use \fB\-\-regen\fR.
.TP
.BR "\-\-prune " (\fB\-P\fR)
-\fBWARNING: This action can remove important packages!\fR Tries to remove
-all but the last version installed. Since the command currently does not
-handle multiple versions of the same package properly, beware! This does not
-check dependencies, so it may also remove packages necessary for the proper
-operation of your system. \fBUse\fR \-\-clean \fBinstead unless you really
-know what you're doing\fR. Its arguments can be \fIebuilds\fR,
-\fIsets\fR, or \fIdependencies\fR \-\- see \fB\-\-clean\fR above for
-examples. You have been warned!
+\fBWARNING: This action can remove important packages!\fR Prune looks at each
+installed package and attempts to \fBremove\fR all but the \fBmost recently
+installed version. \fRPrune ignores \fBslots\fR, if you require a slot\-aware
+Prune use \fB emerge \-\-clean\fR. Prune may inadvertently remove important
+packages from your system. Use \fB\-\-clean\fR instead unless you really
+know what you're doing.
.TP
.BR \-\-regen
Causes portage to check and update the dependency cache of all ebuilds in the
all matching packages. This does no checking of dependencies, so
it may remove packages necessary for the proper operation of your
system. Its arguments can be \fIebuilds\fR, \fIsets\fR, or
-\fIdependencies\fR \-\- see \fB\-\-clean\fR above for examples.
+\fIatoms\fR.
.TP
.BR "\-\-update " (\fB\-u\fR)
Updates packages to the best version available, which may not always be the
disabled lists into one list and sorts the whole list alphabetically.
.TP
.BR "\-\-ask " (\fB\-a\fR)
-Before performing the merge, display what ebuilds and tbz2s will be installed,
-in the same format as when using \fB\-\-pretend\fR; then ask whether to
-continue with the merge or abort. Using \fB\-\-ask\fR is more efficient than
-using \fB\-\-pretend\fR and then executing the same command without
-\fB\-\-pretend\fR, as dependencies will only need to be calculated once.
+Before performing the action, display what will take place (server info for
+\fB\-\-sync\fR, \fB\-\-pretend\fR output for merge, and so forth), then ask
+whether to proceed with the action or abort. Using \fB\-\-ask\fR is more
+efficient than using \fB\-\-pretend\fR and then executing the same command
+without \fB\-\-pretend\fR, as dependencies will only need to be calculated once.
\fBWARNING: If the "Enter" key is pressed at the prompt (with no other input),
it is interpreted as acceptance of the first choice. Note that the input
buffer is not cleared prior to the prompt, so an accidental press of the
.TP
.BR "\-\-debug " (\fB\-d\fR)
Tells emerge to run the emerge command in \fB\-\-debug\fR mode. In this
-mode the bash build environment will run with the \-x option,
-causing it to output verbose debugging information to stdout.
-\fB\-\-debug\fR is great for finding bash syntax errors.
+mode the bash build environment will run with the \-x option, causing
+it to output verbose debugging information to stdout. This also enables
+a plethora of other output (mostly dependency resolution messages).
.TP
.BR "\-\-deep " (\fB\-D\fR)
This flag forces
.TP
.BR "\-\-newuse " (\fB\-N\fR)
Tells emerge to include installed packages where USE flags have changed since
-compilation. An asterisk marks when a USE flag has changed since the package
-was compiled.
+compilation. USE flag changes include:
+
+A USE flag was added to a package.
+A USE flag was removed from a package.
+A USE flag was turned on for a package.
+A USE flag was turned off for a package.
+
+USE flags may be toggled by your profile as well as your USE and package.use
+settings.
.TP
.BR "\-\-noconfmem"
Causes portage to disregard merge records indicating that a config file
.BR "\-\-noreplace " (\fB\-n\fR)
Skips the packages specified on the command\-line that have already
been installed. Without this option, any packages, ebuilds, or deps
-you specify on the command\-line *will* cause Portage to remerge
+you specify on the command\-line \fBwill\fR cause Portage to remerge
the package, even if it is already installed. Note that Portage will
not remerge dependencies by default.
.TP
terminal device is determined to be a TTY. This flag disables it regardless.
.TP
.BR "\-\-oneshot " (\fB\-1\fR)
-Emerge as normal, but do not add the packages to the world profile
+Emerge as normal, but do not add the packages to the world file
for later updating.
.TP
.BR "\-\-onlydeps " (\fB\-o\fR)
\fBPORTAGE_CONFIGROOT\fR = \fI[path]\fR
Use \fBPORTAGE_CONFIGROOT\fR to specify the location for various portage
configuration files
-(see \fBFILES\fR for a detailed list).
+(see \fBFILES\fR for a detailed list of configuration files).
.br
Defaults to /.
.SH "OUTPUT"
active.
.LP
You also want to typically use \fB\-\-update\fR, which ignores packages that
-are already fully updated but upgrades those that are not.
+are already fully updated but updates those that are not.
.LP
When you install a package with uninstalled dependencies and do
not explicitly state those dependencies in the list of parameters,
print " run with the '--verbose' flag."
print
print " "+green("--metadata")
- print " Causes portage to process all the metacache files as is normally "
- print " done on the tail end of an rsync update using "+bold("emerge --sync")+"."
- print " This processing creates the cache database that portage uses for"
- print " pre-parsed lookups of package data."
+ print " Transfers metadata cache from ${PORTDIR}/metadata/cache/ to"
+ print " /var/cache/edb/dep/ as is normally done on the tail end of an"
+ print " rsync update using " + bold("emerge --sync") + ". This process populates the"
+ print " cache database that portage uses for pre-parsed lookups of"
+ print " package data. It does not populate cache for the overlays"
+ print " listed in PORTDIR_OVERLAY. In order to generate cache for"
+ print " overlays, use " + bold("--regen") + "."
print
print " "+green("--prune")+" ("+green("-P")+" short option)"
print " "+turquoise("WARNING: This action can remove important packages!")
os.close(pr)
mybytes = "".join(mybytes)
global auxdbkeys
- dbkey.update(izip(auxdbkeys, mybytes.split("\n")))
+ for k, v in izip(auxdbkeys, mybytes.splitlines()):
+ dbkey[k] = v
retval = os.waitpid(mypids[0], 0)[1]
# If it got a signal, return the signal that was sent, but
# shift in order to distinguish it from a return value. (just
# Check if the set of atoms will result in a downgrade of
# an installed package. If they will then don't prefer them
# over other atoms.
+ is_downgrade = False
if all_installed and all_available:
for atom in atoms:
mykey = dep_getkey(atom)
- if mykey.startswith("virtual/"):
- # New-style virtuals have zero cost to install.
- continue
inst_pkgs = vardb.match(mykey)
+ if not inst_pkgs:
+ # This must be a new-style virtual that isn't really
+ # installed yet (they have zero cost to install).
+ continue
avail_pkg = best(mydbapi.match(atom))
avail_slot = mydbapi.aux_get(avail_pkg, ["SLOT"])[0]
avail_split = catpkgsplit(avail_pkg)[1:]
- is_okay = False
for pkg in inst_pkgs:
if avail_slot != vardb.aux_get(pkg, ["SLOT"])[0]:
continue
- if pkgcmp(avail_split, catpkgsplit(pkg)[1:]) >= 0:
- is_okay = True
+ if pkgcmp(avail_split, catpkgsplit(pkg)[1:]) < 0:
+ is_downgrade = True
break
- if not is_okay:
- all_installed = False
+ if is_downgrade:
break
- if all_installed:
+ if all_installed and not is_downgrade:
preferred.append((atoms, all_available))
else:
other.append((atoms, all_available))
if vartree is None:
vartree = globals()["db"][root]["vartree"]
self.vartree = vartree
+ self._aux_cache_keys = set(["SLOT", "COUNTER", "PROVIDE", "USE",
+ "IUSE", "DEPEND", "RDEPEND", "PDEPEND"])
+ self._aux_cache = None
+ self._aux_cache_version = "1"
+ self._aux_cache_filename = os.path.join(self.root,
+ CACHE_PATH.lstrip(os.path.sep), "vdb_metadata.pickle")
def cpv_exists(self,mykey):
"Tells us whether an actual ebuild exists on disk (no masking)"
def cpv_counter(self,mycpv):
"This method will grab the COUNTER. Returns a counter value."
+ try:
+ return long(self.aux_get(mycpv, ["COUNTER"])[0])
+ except KeyError, ValueError:
+ pass
cdir=self.root+VDB_PATH+"/"+mycpv
cpath=self.root+VDB_PATH+"/"+mycpv+"/COUNTER"
def findname(self, mycpv):
return self.root+VDB_PATH+"/"+str(mycpv)+"/"+mycpv.split("/")[1]+".ebuild"
+ def flush_cache(self):
+ """If the current user has permission and the internal aux_get cache has
+ been updated, save it to disk and mark it unmodified. This is called
+ by emerge after it has loaded the full vdb for use in dependency
+ calculations. Currently, the cache is only written if the user has
+ superuser privileges (since that's required to obtain a lock), but all
+ users have read access and benefit from faster metadata lookups (as
+ long as at least part of the cache is still valid)."""
+ if self._aux_cache is not None and \
+ self._aux_cache["modified"] and \
+ secpass >= 2:
+ valid_nodes = set(self.cpv_all())
+ for cpv in self._aux_cache["packages"].keys():
+ if cpv not in valid_nodes:
+ del self._aux_cache["packages"][cpv]
+ del self._aux_cache["modified"]
+ try:
+ f = atomic_ofstream(self._aux_cache_filename)
+ cPickle.dump(self._aux_cache, f, -1)
+ f.close()
+ portage_util.apply_secpass_permissions(
+ self._aux_cache_filename, gid=portage_gid, mode=0644)
+ except (IOError, OSError), e:
+ pass
+ self._aux_cache["modified"] = False
+
def aux_get(self, mycpv, wants):
+ """This automatically caches selected keys that are frequently needed
+ by emerge for dependency calculations. The cached metadata is
+ considered valid if the mtime of the package directory has not changed
+ since the data was cached. The cache is stored in a pickled dict
+ object with the following format:
+
+ {version:"1", "packages":{cpv1:(mtime,{k1,v1, k2,v2, ...}), cpv2...}}
+
+ If an error occurs while loading the cache pickle or the version is
+ unrecognized, the cache will simple be recreated from scratch (it is
+ completely disposable).
+ """
+ if not self._aux_cache_keys.intersection(wants):
+ return self._aux_get(mycpv, wants)
+ if self._aux_cache is None:
+ try:
+ f = open(self._aux_cache_filename)
+ mypickle = cPickle.Unpickler(f)
+ mypickle.find_global = None
+ self._aux_cache = mypickle.load()
+ f.close()
+ del f
+ except (IOError, OSError, EOFError, cPickle.UnpicklingError):
+ pass
+ if not self._aux_cache or \
+ not isinstance(self._aux_cache, dict) or \
+ self._aux_cache.get("version") != self._aux_cache_version:
+ self._aux_cache = {"version":self._aux_cache_version}
+ self._aux_cache["packages"] = {}
+ self._aux_cache["modified"] = False
+ mydir = os.path.join(self.root, VDB_PATH, mycpv)
+ mydir_stat = None
+ try:
+ mydir_stat = os.stat(mydir)
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ raise
+ raise KeyError(mycpv)
+ mydir_mtime = long(mydir_stat.st_mtime)
+ pkg_data = self._aux_cache["packages"].get(mycpv)
+ mydata = {}
+ cache_valid = False
+ if pkg_data:
+ cache_mtime, metadata = pkg_data
+ cache_valid = cache_mtime == mydir_mtime
+ if cache_valid and set(metadata) != self._aux_cache_keys:
+ # Allow self._aux_cache_keys to change without a cache version
+ # bump.
+ cache_valid = False
+ if cache_valid:
+ mydata.update(metadata)
+ pull_me = set(wants).difference(self._aux_cache_keys)
+ else:
+ pull_me = self._aux_cache_keys.union(wants)
+ if pull_me:
+ # pull any needed data and cache it
+ aux_keys = list(pull_me)
+ mydata.update(izip(aux_keys, self._aux_get(mycpv, aux_keys)))
+ if not cache_valid:
+ cache_data = {}
+ for aux_key in self._aux_cache_keys:
+ cache_data[aux_key] = mydata[aux_key]
+ self._aux_cache["packages"][mycpv] = (mydir_mtime, cache_data)
+ self._aux_cache["modified"] = True
+ return [mydata[x] for x in wants]
+
+ def _aux_get(self, mycpv, wants):
mydir = os.path.join(self.root, VDB_PATH, mycpv)
if not os.path.isdir(mydir):
raise KeyError(mycpv)
def getslot(self,mycatpkg):
"Get a slot for a catpkg; assume it exists."
- myslot = ""
try:
- myslot=string.join(grabfile(self.root+VDB_PATH+"/"+mycatpkg+"/SLOT"))
- except SystemExit, e:
- raise
- except Exception, e:
- pass
- return myslot
+ return self.dbapi.aux_get(mycatpkg, ["SLOT"])[0]
+ except KeyError:
+ return ""
def hasnode(self,mykey,use_cache):
"""Does the particular node (cat/pkg key) exist?"""
self.eclassdb = eclass_cache.cache(self.porttree_root,
overlays=self.mysettings["PORTDIR_OVERLAY"].split())
- self.metadb = {}
self.metadbmodule = self.mysettings.load_best_module("portdbapi.metadbmodule")
#if the portdbapi is "frozen", then we assume that we can cache everything (that no updates to it are happening)
self.auxdb.clear()
def flush_cache(self):
- self.metadb = {}
- self.auxdb = {}
+ for x in self.auxdb.values():
+ x.sync()
def finddigest(self,mycpv):
try: