eecho() { echo "${argv0}: error: $*" 1>&2 ; }
argv0=$0
-if ! type portageq > /dev/null ; then
+if ! type -P portageq > /dev/null ; then
eecho "could not find 'portageq'; aborting"
exit 1
fi
vecho "Checking signature ..."
- if type -p gpg > /dev/null; then
+ if type -P gpg > /dev/null; then
gpg --homedir "${PORTAGE_GPG_DIR}" --verify "$signature" "$file" && r=0
else
eecho "cannot check signature: gpg binary not found"
vecho "Syncing local tree ..."
# tarsync-0.2.1 doesn't seem to support lzma compression.
- if [ "${file##*.}" != "lzma" ] && type -P tarsync &> /dev/null; then
+ if [ "${file##*.}" != "lzma" ] && type -P tarsync > /dev/null; then
if ! tarsync $(vvecho -v) -s 1 -o portage -g portage -e /distfiles -e /packages -e /local "${file}" "${PORTDIR}"; then
eecho "tarsync failed; tarball is corrupt? (${file})"
return 1
# Free disk space
rm -f "${file}"
- chown ${PORTAGE_USER:-portage}:${PORTAGE_GROUP:-portage} portage &> /dev/null && \
+ chown ${PORTAGE_USER:-portage}:${PORTAGE_GROUP:-portage} portage > /dev/null 2>&1 && \
chown -R ${PORTAGE_USER:-portage}:${PORTAGE_GROUP:-portage} portage
-
cd portage
rsync -av --progress --stats --delete --delete-after \
--exclude='/distfiles' --exclude='/packages' \
local mirror
local compressions=""
- type lzcat > /dev/null && compressions="${compressions} lzma"
- type bzcat > /dev/null && compressions="${compressions} bz2"
- type zcat > /dev/null && compressions="${compressions} gz"
+ type -P lzcat > /dev/null && compressions="${compressions} lzma"
+ type -P bzcat > /dev/null && compressions="${compressions} bz2"
+ type -P zcat > /dev/null && compressions="${compressions} gz"
if [[ -z ${compressions} ]] ; then
eecho "unable to locate any decompressors (lzcat or bzcat or zcat)"
exit 1
# [whitespacing for filenames],
# [whitespacing for line numbers])
dump_trace() {
- local funcname="" sourcefile="" lineno="" n e s="yes"
+ local funcname="" sourcefile="" lineno="" s="yes" n p
declare -i strip=${1:-1}
local filespacing=$2 linespacing=$3
# that the user will not be interested in. Therefore, the stack trace
# should only show calls that come after qa_call().
(( n = ${#FUNCNAME[@]} - 1 ))
+ (( p = ${#BASH_ARGV[@]} ))
while (( n > 0 )) ; do
[ "${FUNCNAME[${n}]}" == "qa_call" ] && break
+ (( p -= ${BASH_ARGC[${n}]} ))
(( n-- ))
done
- (( n == 0 )) && (( n = ${#FUNCNAME[@]} - 1 ))
+ if (( n == 0 )) ; then
+ (( n = ${#FUNCNAME[@]} - 1 ))
+ (( p = ${#BASH_ARGV[@]} ))
+ fi
eerror "Call stack:"
- for (( p = ${#BASH_ARGV[@]} ; n > ${strip} ; n-- )) ; do
+ while (( n > ${strip} )) ; do
funcname=${FUNCNAME[${n} - 1]}
sourcefile=$(basename ${BASH_SOURCE[${n}]})
lineno=${BASH_LINENO[${n} - 1]}
(( p -= ${BASH_ARGC[${n} - 1]} ))
fi
eerror " $(printf "%${filespacing}s" "${sourcefile}"):$(printf "%${linespacing}s" "${lineno}"): <call ${funcname}${args:+ ${args}}>"
+ (( n-- ))
done
}
return 1
;;
esac
- echo -e "$*" >> "${T}/logging/${EBUILD_PHASE:-other}.${messagetype}"
+ echo -e "${messagetype} $*" >> "${T}/logging/${EBUILD_PHASE:-other}"
return 0
}
myflag = myflag[1:]
myiuse.add(myflag)
- inherited_java_eclass = "java-pkg" in inherited
+ inherited_java_eclass = "java-pkg-2" in inherited or \
+ "java-pkg-opt-2" in inherited
operator_tokens = set(["||", "(", ")"])
type_list, badsyntax = [], []
for mytype in ("DEPEND", "RDEPEND", "PDEPEND", "LICENSE", "PROVIDE"):
f.add_flowing_data(x)
f.end_paragraph(1)
-class CompositeDbapi(object):
+class DepcheckCompositeDB(object):
def __init__(self, depgraph, root):
self._depgraph = depgraph
self._root = root
else:
if pkg.installed and "selective" not in self._depgraph.myparams:
try:
- self._depgraph._iter_args_for_pkg(pkg).next()
- except StopIteration:
- pass
- except portage.exception.InvalidDependString:
- pass
- else:
+ arg = self._depgraph._iter_atoms_for_pkg(pkg).next()
+ except (StopIteration, portage.exception.InvalidDependString):
+ arg = None
+ if arg:
ret = []
if ret is None:
self._cpv_tree_map[pkg.cpv] = \
self._filtered_trees[myroot]["vartree"] = self.trees[myroot]["vartree"]
def filtered_tree():
pass
- filtered_tree.dbapi = CompositeDbapi(self, myroot)
+ filtered_tree.dbapi = DepcheckCompositeDB(self, myroot)
self._filtered_trees[myroot]["porttree"] = filtered_tree
dbs = []
portdb = self.trees[myroot]["porttree"].dbapi
self._select_package = self._select_pkg_highest_available
self._highest_pkg_cache = {}
self._installed_pkg_cache = {}
+ # All Package instances
+ self._pkg_cache = {}
def _show_slot_collision_notice(self):
"""Show an informational message advising the user to mask one of the
return 0
return 1
- def _greedy_slot_atoms(self, root, atom):
- """Generate SLOT atoms for the highest available match and
- any matching installed SLOTs that are also available."""
- vardb = self.roots[root].trees["vartree"].dbapi
- mykey = portage.dep_getkey(atom)
- myslots = set()
- for cpv in vardb.match(mykey):
- myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
- for myslot in myslots:
- yield "%s:%s" % (mykey, myslot)
-
- def _iter_args_for_pkg(self, pkg):
- # TODO: add multiple $ROOT support
- if pkg.root != self.target_root:
- return
- atom_arg_map = self._atom_arg_map
- for atom in self._set_atoms.iterAtomsForPackage(pkg):
- for arg in atom_arg_map[(atom, pkg.root)]:
- if isinstance(arg, PackageArg) and \
- arg.package != pkg:
- continue
- yield arg
-
def _iter_atoms_for_pkg(self, pkg):
# TODO: add multiple $ROOT support
if pkg.root != self.target_root:
return
atom_arg_map = self._atom_arg_map
for atom in self._set_atoms.iterAtomsForPackage(pkg):
+ atom_cp = portage.dep_getkey(atom)
+ if atom_cp != pkg.cp:
+ have_new_virt = False
+ for db, pkg_type, built, installed, db_keys in \
+ self._filtered_trees[pkg.root]["dbs"]:
+ if db.cp_list(atom_cp):
+ have_new_virt = True
+ break
+ if have_new_virt:
+ continue
for arg in atom_arg_map[(atom, pkg.root)]:
if isinstance(arg, PackageArg) and \
arg.package != pkg:
This will raise an InvalidDependString exception if PROVIDE is invalid.
"""
any_arg = None
- for arg in self._iter_args_for_pkg(pkg):
+ for arg, atom in self._iter_atoms_for_pkg(pkg):
if isinstance(arg, PackageArg):
return arg
any_arg = arg
greedy_atoms.append(arg)
if not isinstance(arg, (AtomArg, PackageArg)):
continue
- for greedy_atom in self._greedy_slot_atoms(myroot, arg.atom):
+ atom_cp = portage.dep_getkey(arg.atom)
+ slots = set()
+ for cpv in vardb.match(atom_cp):
+ slots.add(vardb.aux_get(cpv, ["SLOT"])[0])
+ for slot in slots:
greedy_atoms.append(
- AtomArg(arg=arg.arg, atom=greedy_atom,
+ AtomArg(arg=arg.arg, atom="%s:%s" % (atom_cp, slot),
root_config=root_config))
args = greedy_atoms
del greedy_atoms
cpv_list = db.xmatch("match-all", atom)
else:
cpv_list = db.match(atom)
+ if not cpv_list:
+ continue
+ pkg_status = "merge"
+ if installed or onlydeps:
+ pkg_status = "nomerge"
# descending order
cpv_list.reverse()
for cpv in cpv_list:
cpv in vardb.match(atom):
break
reinstall_for_flags = None
- try:
- metadata = dict(izip(db_keys,
- db.aux_get(cpv, db_keys)))
- except KeyError:
- continue
- if not built:
- if "?" in metadata["LICENSE"]:
+ cache_key = (pkg_type, root, cpv, pkg_status)
+ calculated_use = True
+ pkg = self._pkg_cache.get(cache_key)
+ if pkg is None:
+ calculated_use = False
+ try:
+ metadata = dict(izip(self._mydbapi_keys,
+ db.aux_get(cpv, self._mydbapi_keys)))
+ except KeyError:
+ continue
+ if not built and ("?" in metadata["LICENSE"] or \
+ "?" in metadata["PROVIDE"]):
+ # This is avoided whenever possible because
+ # it's expensive. It only needs to be done here
+ # if it has an effect on visibility.
pkgsettings.setcpv(cpv, mydb=metadata)
metadata["USE"] = pkgsettings["PORTAGE_USE"]
- else:
- metadata["USE"] = ""
+ calculated_use = True
+ pkg = Package(built=built, cpv=cpv,
+ installed=installed, metadata=metadata,
+ onlydeps=onlydeps, root=root, type_name=pkg_type)
+ self._pkg_cache[pkg] = pkg
myarg = None
if root == self.target_root:
try:
- myarg = self._get_arg_for_pkg(
- Package(type_name=pkg_type, root=root,
- cpv=cpv, metadata=metadata,
- built=built, installed=installed,
- onlydeps=onlydeps))
+ myarg = self._iter_atoms_for_pkg(pkg).next()
+ except StopIteration:
+ pass
except portage.exception.InvalidDependString:
if not installed:
# masked by corruption
continue
- pkg = Package(built=built, cpv=cpv, installed=installed,
- metadata=metadata, type_name=pkg_type)
if not installed:
if myarg:
found_available_arg = True
if not visible(pkgsettings, pkg):
continue
+ if not built and not calculated_use:
+ # This is avoided whenever possible because
+ # it's expensive.
+ pkgsettings.setcpv(cpv, mydb=pkg.metadata)
+ pkg.metadata["USE"] = pkgsettings["PORTAGE_USE"]
if pkg.cp == atom_cp:
if highest_version is None:
highest_version = pkg
# will always end with a break statement below
# this point.
if find_existing_node:
- slot_atom = "%s:%s" % (
- portage.cpv_getkey(cpv), metadata["SLOT"])
- e_pkg = self._slot_pkg_map[root].get(slot_atom)
+ e_pkg = self._slot_pkg_map[root].get(pkg.slot_atom)
if not e_pkg:
break
cpv_slot = "%s:%s" % \
("--newuse" in self.myopts or \
"--reinstall" in self.myopts):
iuses = set(filter_iuse_defaults(
- metadata["IUSE"].split()))
- old_use = metadata["USE"].split()
- mydb = metadata
+ pkg.metadata["IUSE"].split()))
+ old_use = pkg.metadata["USE"].split()
+ mydb = pkg.metadata
if myeb and not usepkgonly:
mydb = portdb
if myeb:
("--newuse" in self.myopts or \
"--reinstall" in self.myopts) and \
cpv in vardb.match(atom):
- pkgsettings.setcpv(cpv, mydb=metadata)
+ pkgsettings.setcpv(cpv, mydb=pkg.metadata)
forced_flags = set()
forced_flags.update(pkgsettings.useforce)
forced_flags.update(pkgsettings.usemask)
vardb.aux_get(cpv, ["IUSE"])[0].split()))
cur_use = pkgsettings["PORTAGE_USE"].split()
cur_iuse = set(filter_iuse_defaults(
- metadata["IUSE"].split()))
+ pkg.metadata["IUSE"].split()))
reinstall_for_flags = \
self._reinstall_for_flags(
forced_flags, old_use, old_iuse,
not must_reinstall and \
cpv in vardb.match(atom):
break
- # Metadata accessed above is cached internally by
- # each db in order to optimize visibility checks.
- # Now that all possible checks visibility checks
- # are complete, it's time to pull the rest of the
- # metadata (including *DEPEND). This part is more
- # expensive, so avoid it whenever possible.
- metadata.update(izip(self._mydbapi_keys,
- db.aux_get(cpv, self._mydbapi_keys)))
if not built:
- pkgsettings.setcpv(cpv, mydb=metadata)
- metadata["USE"] = pkgsettings["PORTAGE_USE"]
myeb = cpv
- pkg = Package(type_name=pkg_type, root=root,
- cpv=cpv, metadata=metadata,
- built=built, installed=installed,
- onlydeps=onlydeps)
matched_packages.append(pkg)
if reinstall_for_flags:
self._reinstall_nodes[pkg] = \
from portage.locks import unlockfile
from portage.output import red
from portage.util import writemsg
-from portage import dep_expand
+from portage import auxdbkeys, dep_expand
from portage.versions import catpkgsplit, catsplit, pkgcmp
_category_re = re.compile(r'^\w[-.+\w]*$')
_pkg_dir_name_re = re.compile(r'^\w[-+\w]*$')
_categories = None
+ _known_keys = frozenset(x for x in auxdbkeys
+ if not x.startswith("UNUSED_0"))
def __init__(self):
pass
from itertools import izip
class bindbapi(fakedbapi):
+ _known_keys = frozenset(list(fakedbapi._known_keys) + \
+ ["CHOST", "repository", "USE"])
def __init__(self, mybintree=None, **kwargs):
fakedbapi.__init__(self, **kwargs)
self.bintree = mybintree
self.cpdict={}
# Selectively cache metadata in order to optimize dep matching.
self._aux_cache_keys = set(
- ["CHOST", "EAPI", "IUSE", "KEYWORDS",
- "LICENSE", "PROVIDE", "SLOT", "USE", "EPREFIX"])
+ ["CHOST", "DEPEND", "EAPI", "IUSE", "KEYWORDS",
+ "LICENSE", "PDEPEND", "PROVIDE",
+ "RDEPEND", "repository", "RESTRICT", "SLOT", "USE",
+ "EPREFIX"])
self._aux_cache = {}
def match(self, *pargs, **kwargs):
if self.bintree and not self.bintree.populated:
self.bintree.populate()
cache_me = False
- if not set(wants).difference(self._aux_cache_keys):
+ if not self._known_keys.intersection(
+ wants).difference(self._aux_cache_keys):
aux_cache = self._aux_cache.get(mycpv)
if aux_cache is not None:
- return [aux_cache[x] for x in wants]
+ return [aux_cache.get(x, "") for x in wants]
cache_me = True
mysplit = mycpv.split("/")
mylist = []
self._pkgindex_aux_keys = \
["CHOST", "DEPEND", "DESCRIPTION", "EAPI",
"IUSE", "KEYWORDS", "LICENSE", "PDEPEND",
- "PROVIDE", "RDEPEND", "SLOT", "USE", "EPREFIX"]
+ "PROVIDE", "RDEPEND", "repository", "SLOT", "USE",
+ "EPREFIX"]
self._pkgindex_aux_keys = list(self._pkgindex_aux_keys)
self._pkgindex_header_keys = set(["ACCEPT_KEYWORDS", "CBUILD",
"CHOST", "CONFIG_PROTECT", "CONFIG_PROTECT_MASK", "FEATURES",
else:
eapi = str(EAPI)
self._pkgindex_default_pkg_data = {
+ "DEPEND" : "",
"EAPI" : eapi,
"IUSE" : "",
+ "KEYWORDS": "",
"LICENSE" : "",
+ "PDEPEND" : "",
"PROVIDE" : "",
+ "RDEPEND" : "",
+ "RESTRICT": "",
"SLOT" : "0",
"USE" : ""
}
- self._pkgindex_inherited_keys = ["CHOST", "EPREFIX"]
+ self._pkgindex_inherited_keys = ["CHOST", "repository", "EPREFIX"]
+ self._pkgindex_default_header_data = {
+ "repository":""
+ }
def move_ent(self, mylist):
if not self.populated:
def _new_pkgindex(self):
return portage.getbinpkg.PackageIndex(
+ default_header_data=self._pkgindex_default_header_data,
default_pkg_data=self._pkgindex_default_pkg_data,
inherited_keys=self._pkgindex_inherited_keys)
del metadata["DESCRIPTION"]
use = metadata["USE"].split()
raw_use = use
- iuse = set(metadata["IUSE"].split())
+ iuse = set(f.lstrip("-+") for f in metadata["IUSE"].split())
use = [f for f in use if f in iuse]
use.sort()
metadata["USE"] = " ".join(use)
self.porttrees = [self.porttree_root] + \
[os.path.realpath(t) for t in self.mysettings["PORTDIR_OVERLAY"].split()]
self.treemap = {}
+ self._repository_map = {}
for path in self.porttrees:
repo_name_path = os.path.join(path, REPO_NAME_LOC)
try:
repo_name = open(repo_name_path, 'r').readline().strip()
self.treemap[repo_name] = path
+ self._repository_map[path] = repo_name
except (OSError,IOError):
# warn about missing repo_name at some other time, since we
# don't want to see a warning every time the portage module is
self.depcachedir, x, filtered_auxdbkeys, gid=portage_gid)
# Selectively cache metadata in order to optimize dep matching.
self._aux_cache_keys = set(
- ["EAPI", "IUSE", "KEYWORDS", "LICENSE", "PROVIDE", "SLOT"])
+ ["DEPEND", "EAPI", "IUSE", "KEYWORDS", "LICENSE",
+ "PDEPEND", "PROVIDE", "RDEPEND", "repository",
+ "RESTRICT", "SLOT"])
self._aux_cache = {}
self._broken_ebuilds = set()
cache_me = False
if not mytree:
cache_me = True
- if not mytree and not set(mylist).difference(self._aux_cache_keys):
+ if not mytree and not self._known_keys.intersection(
+ mylist).difference(self._aux_cache_keys):
aux_cache = self._aux_cache.get(mycpv)
if aux_cache is not None:
- return [aux_cache[x] for x in mylist]
+ return [aux_cache.get(x, "") for x in mylist]
cache_me = True
global auxdbkeys, auxdbkeylen
cat,pkg = mycpv.split("/", 1)
if not mydata.setdefault("EAPI", "0"):
mydata["EAPI"] = "0"
+ # do we have a origin repository name for the current package
+ mydata["repository"] = self._repository_map.get(
+ os.path.sep.join(myebuild.split(os.path.sep)[:-3]), "")
+
#finally, we look at our internal cache entry and return the requested data.
returnme = []
for x in mylist:
from portage.update import fixdbentries
from portage.util import apply_secpass_permissions, ConfigProtect, ensure_dirs, \
writemsg, writemsg_stdout, write_atomic, atomic_ofstream, writedict, \
- grabfile, grabdict, normalize_path, new_protect_filename
+ grabfile, grabdict, normalize_path, new_protect_filename, getlibpaths
from portage.versions import pkgsplit, catpkgsplit, catsplit, best, pkgcmp
from portage import listdir, dep_expand, flatten, key_expand, \
for lib in list(preserve_libs):
if not has_external_consumers(lib, old_contents, preserve_libs):
- preserve_libs.remove(lib)
+ preserve_libs.remove(lib)
+ for path in getlibpaths():
+ if os.path.exists(os.path.join(path, lib)):
+ preserve_libs.remove(lib)
# get the real paths for the libs
preserve_paths = [x for x in old_contents if os.path.basename(x) in preserve_libs]
# exploit listdir() file order so we process log entries in chronological order
mylogfiles.reverse()
logentries = {}
- for f in mylogfiles:
- msgfunction, msgtype = f.split(".")
+ for msgfunction in mylogfiles:
if msgfunction not in EBUILD_PHASES:
writemsg("!!! can't process invalid log file: %s\n" % f,
noiselevel=-1)
continue
if not msgfunction in logentries:
logentries[msgfunction] = []
- msgcontent = open(os.path.join(path, f), "r").readlines()
- logentries[msgfunction].append((msgtype, msgcontent))
+ lastmsgtype = None
+ msgcontent = []
+ for l in open(os.path.join(path, msgfunction), "r").readlines():
+ msgtype, msg = l.split(" ", 1)
+ if lastmsgtype is None:
+ lastmsgtype = msgtype
+ if msgtype == lastmsgtype:
+ msgcontent.append(msg)
+ else:
+ if msgcontent:
+ logentries[msgfunction].append((lastmsgtype, msgcontent))
+ msgcontent = [msg]
+ lastmsgtype = msgtype
+
# clean logfiles to avoid repetitions
for f in mylogfiles:
try:
class PackageIndex(object):
- def __init__(self, default_pkg_data=None, inherited_keys=None):
+ def __init__(self, default_header_data=None, default_pkg_data=None,
+ inherited_keys=None):
+ self._default_header_data = default_header_data
self._default_pkg_data = default_pkg_data
self._inherited_keys = inherited_keys
self.header = {}
+ if self._default_header_data:
+ self.header.update(self._default_header_data)
self.packages = []
self.modified = True
self.header["PACKAGES"] = str(len(self.packages))
keys = self.header.keys()
keys.sort()
- self._writepkgindex(pkgfile, [(k, self.header[k]) for k in keys])
+ self._writepkgindex(pkgfile, [(k, self.header[k]) \
+ for k in keys if self.header[k]])
for metadata in sorted(self.packages, _cmp_cpv):
metadata = metadata.copy()
cpv = metadata["CPV"]