tmpsettings.backup_changes("EBUILD_SKIP_MANIFEST")
portage._doebuild_manifest_exempt_depend += 1
-build_dir_phases = set(["setup", "unpack", "configure", "compile",
- "test", "install", "package", "rpm"])
+build_dir_phases = set(["setup", "unpack", "prepare", "configure", "compile",
+ "test", "install", "package", "rpm", "merge", "qmerge"])
+
+# If the current metadata is invalid then force the ebuild to be
+# sourced again even if $T/environment already exists.
+ebuild_changed = False
+if build_dir_phases.intersection(pargs):
+ metadata, st, emtime = \
+ portage.portdb._pull_valid_cache(cpv, ebuild, ebuild_portdir)
+ if metadata is None:
+ ebuild_changed = True
def stale_env_warning():
if "clean" not in pargs and \
"noauto" not in tmpsettings.features and \
- tmpsettings.get("PORTAGE_QUIET") != "1" and \
build_dir_phases.intersection(pargs):
portage.doebuild_environment(ebuild, "setup", portage.root,
tmpsettings, debug, 1, portage.portdb)
for x in msg:
portage.writemsg(">>> %s\n" % x)
+ if ebuild_changed:
+ open(os.path.join(tmpsettings['PORTAGE_BUILDDIR'],
+ '.ebuild_changed'), 'w')
+
from portage.exception import PermissionDenied, \
PortagePackageException, UnsupportedAPIException
checked_for_stale_env = False
fi
if [ "${newstuff}" == "yes" ]; then
# We don't necessarily have privileges to do a full dyn_clean here.
- rm -rf "${PORTAGE_BUILDDIR}"/{.unpacked,.compiled,.tested,.packaged,build-info}
+ rm -rf "${PORTAGE_BUILDDIR}"/{.unpacked,.prepared,.configured,.compiled,.tested,.installed,.packaged,build-info}
rm -rf "${WORKDIR}"
if [ -d "${T}" ] && \
! hasq keeptemp $FEATURES && ! hasq keepwork $FEATURES ; then
fi
if [[ $EMERGE_FROM = binary ]] || ! hasq keepwork $FEATURES; then
- rm -f "$PORTAGE_BUILDDIR"/.{exit_status,logid,unpacked,prepared} \
+ rm -f "$PORTAGE_BUILDDIR"/.{ebuild_changed,exit_status,logid,unpacked,prepared} \
"$PORTAGE_BUILDDIR"/.{configured,compiled,tested,packaged}
rm -rf "${PORTAGE_BUILDDIR}/build-info"
unset PORTAGE_SANDBOX_ON
fi
-if ! hasq "$EBUILD_PHASE" clean cleanrm && \
- (
- hasq ${EBUILD_PHASE} depend || \
- [ ! -f "${T}"/environment ] || \
- hasq noauto ${FEATURES}
- ) ; then
+if ! hasq "$EBUILD_PHASE" clean cleanrm ; then
+if [[ $EBUILD_PHASE = depend || ! -f $T/environment || \
+ -f $PORTAGE_BUILDDIR/.ebuild_changed ]] || \
+ hasq noauto $FEATURES ; then
+
# The bashrcs get an opportunity here to set aliases that will be expanded
# during sourcing of ebuilds and eclasses.
source_all_bashrcs
if [ "${EBUILD_PHASE}" != "depend" ] ; then
RESTRICT=${PORTAGE_RESTRICT}
+ [[ -e $PORTAGE_BUILDDIR/.ebuild_changed ]] && \
+ rm "$PORTAGE_BUILDDIR/.ebuild_changed"
fi
# This next line is not the same as export RDEPEND=${RDEPEND:-${DEPEND}}
# This needs to be exported since prepstrip is a separate shell script.
[[ -n $QA_PRESTRIPPED ]] && export QA_PRESTRIPPED
fi
+fi
# Set default EAPI if necessary, so that most
# code can simply assume that it's defined.
`tail \-f /var/log/emerge\-fetch.log` in a
terminal to view parallel-fetch progress.
.TP
+.B parse\-eapi\-ebuild\-head
+Parse \fBEAPI\fR from the head of the ebuild (first 30 lines). This feature
+is only intended for experimental purposes and should not be enabled under
+normal circumstances.
+.TP
.B preserve\-libs
Preserve libraries when the sonames change during upgrade or downgrade.
Libraries are preserved only if consumers of those libraries are detected.
# $Id$
import array
+import codecs
from collections import deque
import fcntl
import formatter
if metadata is None:
mreasons = ["corruption"]
else:
- pkg = Package(type_name=pkg_type, root_config=root_config,
- cpv=cpv, built=built, installed=installed, metadata=metadata)
- mreasons = get_masking_status(pkg, pkgsettings, root_config)
+ eapi = metadata['EAPI']
+ if eapi[:1] == '-':
+ eapi = eapi[1:]
+ if not portage.eapi_is_supported(eapi):
+ mreasons = ['EAPI %s' % eapi]
+ else:
+ pkg = Package(type_name=pkg_type, root_config=root_config,
+ cpv=cpv, built=built, installed=installed, metadata=metadata)
+ mreasons = get_masking_status(pkg, pkgsettings, root_config)
return metadata, mreasons
def show_masked_packages(masked_packages):
def _start(self):
settings = self.settings
- settings.reset()
+ settings.setcpv(self.cpv)
ebuild_path = self.ebuild_path
+
+ if 'parse-eapi-ebuild-head' in settings.features:
+ eapi = portage._parse_eapi_ebuild_head(codecs.open(ebuild_path,
+ mode='r', encoding='utf_8', errors='replace'))
+ if not portage.eapi_is_supported(eapi):
+ self.metadata_callback(self.cpv, self.ebuild_path,
+ self.repo_path, {'EAPI' : eapi}, self.ebuild_mtime)
+ self.returncode = os.EX_OK
+ self.wait()
+ return
+
+ settings.configdict['pkg']['EAPI'] = eapi
+
debug = settings.get("PORTAGE_DEBUG") == "1"
master_fd = None
slave_fd = None
self.pusemask_list = []
rawpusemask = [grabdict_package(os.path.join(x, "package.use.mask"),
recursive=1) for x in self.profiles]
- for i in xrange(len(self.profiles)):
+ for pusemaskdict in rawpusemask:
cpdict = {}
- for k, v in rawpusemask[i].iteritems():
+ for k, v in pusemaskdict.iteritems():
cpdict.setdefault(dep_getkey(k), {})[k] = v
self.pusemask_list.append(cpdict)
del rawpusemask
self.pkgprofileuse = []
rawprofileuse = [grabdict_package(os.path.join(x, "package.use"),
juststrings=True, recursive=1) for x in self.profiles]
- for i in xrange(len(self.profiles)):
+ for rawpusedict in rawprofileuse:
cpdict = {}
- for k, v in rawprofileuse[i].iteritems():
+ for k, v in rawpusedict.iteritems():
cpdict.setdefault(dep_getkey(k), {})[k] = v
self.pkgprofileuse.append(cpdict)
del rawprofileuse
rawpuseforce = [grabdict_package(
os.path.join(x, "package.use.force"), recursive=1) \
for x in self.profiles]
- for i in xrange(len(self.profiles)):
+ for rawpusefdict in rawpuseforce:
cpdict = {}
- for k, v in rawpuseforce[i].iteritems():
+ for k, v in rawpusefdict.iteritems():
cpdict.setdefault(dep_getkey(k), {})[k] = v
self.puseforce_list.append(cpdict)
del rawpuseforce
self["FEATURES"] = " ".join(sorted(self.features))
self.backup_changes("FEATURES")
+ global _validate_cache_for_unsupported_eapis
+ if 'parse-eapi-ebuild-head' in self.features:
+ _validate_cache_for_unsupported_eapis = False
# inject EPREFIX as it's in no single config file (I hope),
# but needs to be available using portageq
if pkginternaluse != self.configdict["pkginternal"].get("USE", ""):
self.configdict["pkginternal"]["USE"] = pkginternaluse
has_changed = True
+
defaults = []
pos = 0
- for i in xrange(len(self.profiles)):
- cpdict = self.pkgprofileuse[i].get(cp, None)
+ for i, pkgprofileuse_dict in enumerate(self.pkgprofileuse):
+ cpdict = pkgprofileuse_dict.get(cp)
if cpdict:
keys = cpdict.keys()
while keys:
cp = dep_getkey(pkg)
usemask = []
pos = 0
- for i in xrange(len(self.profiles)):
- cpdict = self.pusemask_list[i].get(cp, None)
+ for i, pusemask_dict in enumerate(self.pusemask_list):
+ cpdict = pusemask_dict.get(cp)
if cpdict:
keys = cpdict.keys()
while keys:
cp = dep_getkey(pkg)
useforce = []
pos = 0
- for i in xrange(len(self.profiles)):
- cpdict = self.puseforce_list[i].get(cp, None)
+ for i, puseforce_dict in enumerate(self.puseforce_list):
+ cpdict = puseforce_dict.get(cp)
if cpdict:
keys = cpdict.keys()
while keys:
pkg = "%s:%s" % (cpv, metadata["SLOT"])
keywords = [[x for x in metadata["KEYWORDS"].split() if x != "-*"]]
pos = len(keywords)
- for i in xrange(len(self.profiles)):
- cpdict = self._pkeywords_list[i].get(cp, None)
+ for pkeywords_dict in self._pkeywords_list:
+ cpdict = pkeywords_dict.get(cp)
if cpdict:
keys = list(cpdict)
while keys:
return True
+# Generally, it's best not to assume that cache entries for unsupported EAPIs
+# can be validated. However, the current package manager specification does not
+# guarantee that that the EAPI can be parsed without sourcing the ebuild, so
+# it's too costly to discard existing cache entries for unsupported EAPIs.
+# Therefore, by default, assume that cache entries for unsupported EAPIs can be
+# validated. If FEATURES=parse-eapi-* is enabled, this assumption is discarded
+# since the EAPI can be determined without the incurring the cost of sourcing
+# the ebuild.
+_validate_cache_for_unsupported_eapis = True
+
+_parse_eapi_ebuild_head_re = re.compile(r'^EAPI=[\'"]?([^\'"]*)')
+_parse_eapi_ebuild_head_max_lines = 30
+
+def _parse_eapi_ebuild_head(f):
+ count = 0
+ for line in f:
+ m = _parse_eapi_ebuild_head_re.match(line)
+ if m is not None:
+ return m.group(1).strip()
+ count += 1
+ if count >= _parse_eapi_ebuild_head_max_lines:
+ break
+ return '0'
+
def doebuild_environment(myebuild, mydo, myroot, mysettings, debug, use_cache, mydbapi):
ebuild_path = os.path.abspath(myebuild)
tmpdir = mysettings["PORTAGE_TMPDIR"]
if mycpv != mysettings.mycpv:
- # Reload env.d variables and reset any previous settings.
- mysettings.reload()
- mysettings.reset()
if mydo == 'depend':
# Don't pass in mydbapi here since the resulting aux_get
# call would lead to infinite 'depend' phase recursion.
mysettings.setcpv(mycpv)
else:
+ # Reload env.d variables and reset any previous settings.
+ mysettings.reload()
+ mysettings.reset()
mysettings.setcpv(mycpv, mydb=mydbapi)
# config.reset() might have reverted a change made by the caller,
if portage.util.noiselimit < 0:
mysettings["PORTAGE_QUIET"] = "1"
+ if mydo == 'depend' and \
+ 'EAPI' not in mysettings.configdict['pkg'] and \
+ 'parse-eapi-ebuild-head' in mysettings.features:
+ eapi = _parse_eapi_ebuild_head(codecs.open(ebuild_path,
+ mode='r', encoding='utf_8', errors='replace'))
+ if not eapi_is_supported(eapi):
+ raise portage.exception.UnsupportedAPIException(mycpv, eapi)
+ mysettings.configdict['pkg']['EAPI'] = eapi
+
if mydo != "depend":
# Metadata vars such as EAPI and RESTRICT are
# set by the above config.setcpv() call.
for example.
@type fd_pipes: Dictionary
@param returnpid: Return a list of process IDs for a successful spawn, or
- in integer value if spawn is unsuccessful. NOTE: This requires the
+ an integer value if spawn is unsuccessful. NOTE: This requires the
caller clean up all returned PIDs.
@type returnpid: Boolean
@rtype: Boolean
d[k] = result[0][column_index]
# As a temporary workaround for bug #263081, convert unicode strings
- # to raw byte strings. This helps to potential unicode errors that can
+ # to raw byte strings. This avoids potential unicode errors that can
# be triggered elsewhere when attempting to join unicode strings with
# raw byte strings. TODO: Convert all string handling code to use
# unicode strings instead of raw byte strings (required for py3k
def mirror_cache(valid_nodes_iterable, src_cache, trg_cache, eclass_cache=None, verbose_instance=None):
- from portage import eapi_is_supported
+ from portage import eapi_is_supported, \
+ _validate_cache_for_unsupported_eapis
if not src_cache.complete_eclass_entries and not eclass_cache:
raise Exception("eclass_cache required for cache's of class %s!" % src_cache.__class__)
noise.exception(x, ce)
del ce
continue
+
+ eapi = entry.get('EAPI')
+ if not eapi:
+ eapi = '0'
+ eapi = eapi.lstrip('-')
+ eapi_supported = eapi_is_supported(eapi)
+ if not eapi_supported:
+ if not _validate_cache_for_unsupported_eapis:
+ noise.misc(x, "unable to validate cache for EAPI='%s'" % eapi)
+ continue
+
write_it = True
trg = None
try:
continue
entry["_eclasses_"] = eclasses
- eapi = entry.get("EAPI")
- if not eapi:
- eapi = "0"
- if not eapi_is_supported(eapi):
+ if not eapi_supported:
for k in set(entry).difference(("_mtime_", "_eclasses_")):
entry[k] = ""
- entry["EAPI"] = "-" + eapi.lstrip("-")
+ entry["EAPI"] = "-" + eapi
# by this time, if it reaches here, the eclass has been validated, and the entry has
# been updated/translated (if needs be, for metadata/cache mainly)
listdir, dep_expand, eapi_is_supported, key_expand, dep_check, \
_eapi_is_deprecated
-import os, stat
+import codecs, os, stat
from itertools import izip
def _src_uri_validate(cpv, eapi, src_uri):
writemsg("doregen: %s %s\n" % (doregen, mycpv), 2)
writemsg("Generating cache entry(0) for: "+str(myebuild)+"\n", 1)
- self.doebuild_settings.reset()
+ self.doebuild_settings.setcpv(mycpv)
mydata = {}
- myret = doebuild(myebuild, "depend",
- self.doebuild_settings["ROOT"], self.doebuild_settings,
- dbkey=mydata, tree="porttree", mydbapi=self)
- if myret != os.EX_OK:
- self._broken_ebuilds.add(myebuild)
- raise KeyError(mycpv)
+ eapi = None
+
+ if 'parse-eapi-ebuild-head' in self.doebuild_settings.features:
+ eapi = portage._parse_eapi_ebuild_head(codecs.open(myebuild,
+ mode='r', encoding='utf_8', errors='replace'))
+ self.doebuild_settings.configdict['pkg']['EAPI'] = eapi
+
+ if eapi is not None and not portage.eapi_is_supported(eapi):
+ mydata['EAPI'] = eapi
+ else:
+ myret = doebuild(myebuild, "depend",
+ self.doebuild_settings["ROOT"], self.doebuild_settings,
+ dbkey=mydata, tree="porttree", mydbapi=self)
+ if myret != os.EX_OK:
+ self._broken_ebuilds.add(myebuild)
+ raise KeyError(mycpv)
self._metadata_callback(
mycpv, myebuild, mylocation, mydata, emtime)