summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2009-03-23 21:16:27 +0000
committerZac Medico <zmedico@gentoo.org>2009-03-23 21:16:27 +0000
commitff7cdd18aa9fe95be848637366b4b7fcaf440f6f (patch)
treed9fc884e0b1e152cffb4c222ad22fb0025e8c9ce
parentWhen calling doebuild() to spawn the 'depend' phase, just call config.setcpv() (diff)
downloadportage-multirepo-ff7cdd18aa9fe95be848637366b4b7fcaf440f6f.tar.gz
portage-multirepo-ff7cdd18aa9fe95be848637366b4b7fcaf440f6f.tar.bz2
portage-multirepo-ff7cdd18aa9fe95be848637366b4b7fcaf440f6f.zip
Add support for FEATURES=parse-eapi-ebuild-head, which is similar to GLEP 55
except that the EAPI is parsed 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. svn path=/main/trunk/; revision=13173
-rw-r--r--man/make.conf.55
-rw-r--r--pym/_emerge/__init__.py14
-rw-r--r--pym/portage/__init__.py36
-rw-r--r--pym/portage/cache/util.py21
-rw-r--r--pym/portage/dbapi/porttree.py24
5 files changed, 87 insertions, 13 deletions
diff --git a/man/make.conf.5 b/man/make.conf.5
index 2f9c3650..268fd4c8 100644
--- a/man/make.conf.5
+++ b/man/make.conf.5
@@ -269,6 +269,11 @@ Fetch in the background while compiling. Run
`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.
diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py
index 17fec42d..76acb8a1 100644
--- a/pym/_emerge/__init__.py
+++ b/pym/_emerge/__init__.py
@@ -4,6 +4,7 @@
# $Id$
import array
+import codecs
from collections import deque
import fcntl
import formatter
@@ -3029,6 +3030,19 @@ class EbuildMetadataPhase(SubProcess):
settings = self.settings
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
diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py
index f56c6447..5c1cc173 100644
--- a/pym/portage/__init__.py
+++ b/pym/portage/__init__.py
@@ -1790,6 +1790,9 @@ class config(object):
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
self._init_dirs()
@@ -5024,6 +5027,30 @@ def eapi_is_supported(eapi):
return False
return eapi <= portage.const.EAPI
+# 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)
@@ -5096,6 +5123,15 @@ def doebuild_environment(myebuild, mydo, myroot, mysettings, debug, use_cache, m
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.
diff --git a/pym/portage/cache/util.py b/pym/portage/cache/util.py
index 9fcd4b49..0f2685c0 100644
--- a/pym/portage/cache/util.py
+++ b/pym/portage/cache/util.py
@@ -10,7 +10,8 @@ from portage.cache import cache_errors
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__)
@@ -39,6 +40,17 @@ def mirror_cache(valid_nodes_iterable, src_cache, trg_cache, eclass_cache=None,
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:
@@ -102,13 +114,10 @@ def mirror_cache(valid_nodes_iterable, src_cache, trg_cache, eclass_cache=None,
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)
diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py
index 07771523..4cbf7af3 100644
--- a/pym/portage/dbapi/porttree.py
+++ b/pym/portage/dbapi/porttree.py
@@ -25,7 +25,7 @@ from portage import eclass_cache, auxdbkeys, doebuild, flatten, \
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):
@@ -419,12 +419,22 @@ class portdbapi(dbapi):
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)