summaryrefslogtreecommitdiffstats
path: root/pym/portage/dbapi
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2008-09-20 08:02:45 +0000
committerZac Medico <zmedico@gentoo.org>2008-09-20 08:02:45 +0000
commiteabfcf5e872971848ec00d877d9afc78455e0efe (patch)
tree31177f8456238da4db28c6507d81011ceb28dba1 /pym/portage/dbapi
parent0df2d2b63bdbf81a3519acc84999bc62a0a9549b (diff)
downloadportage-eabfcf5e872971848ec00d877d9afc78455e0efe.tar.gz
portage-eabfcf5e872971848ec00d877d9afc78455e0efe.tar.bz2
portage-eabfcf5e872971848ec00d877d9afc78455e0efe.zip
Implement SRC_URI arrows for EAPI 2. The portdbapi.getfetchlist() method
is now deprecated and there is a new getFetchMap() method that returns a dict which maps each file name to a set of alternative URIs. The portage.fetch() function uses introspection to detect when such a dict is passed in and handles it appropriately, while maintaining backward compatibility if a list of uris is passed in. svn path=/main/trunk/; revision=11522
Diffstat (limited to 'pym/portage/dbapi')
-rw-r--r--pym/portage/dbapi/porttree.py161
1 files changed, 134 insertions, 27 deletions
diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py
index a1165907c..feade6fc8 100644
--- a/pym/portage/dbapi/porttree.py
+++ b/pym/portage/dbapi/porttree.py
@@ -25,6 +25,52 @@ from portage import eclass_cache, auxdbkeys, doebuild, flatten, \
import os, stat
from itertools import izip
+def _src_uri_validate(cpv, eapi, src_uri):
+ """
+ Take a SRC_URI structure as returned by paren_reduce or use_reduce
+ and validate it. Raises InvalidDependString if a problem is detected,
+ such as missing operand for a -> operator.
+ """
+ uri = None
+ operator = None
+ for x in src_uri:
+ if isinstance(x, list):
+ if operator is not None:
+ raise portage.exception.InvalidDependString(
+ ("getFetchMap(): '%s' SRC_URI arrow missing " + \
+ "right operand") % (cpv,))
+ uri = None
+ _src_uri_validate(cpv, eapi, x)
+ continue
+ if x[:-1] == "?":
+ if operator is not None:
+ raise portage.exception.InvalidDependString(
+ ("getFetchMap(): '%s' SRC_URI arrow missing " + \
+ "right operand") % (cpv,))
+ uri = None
+ continue
+ if uri is None:
+ if x == "->":
+ raise portage.exception.InvalidDependString(
+ ("getFetchMap(): '%s' SRC_URI arrow missing " + \
+ "left operand") % (cpv,))
+ uri = x
+ continue
+ if x == "->":
+ if eapi in ("0", "1"):
+ raise portage.exception.InvalidDependString(
+ ("getFetchMap(): '%s' SRC_URI arrows are not " + \
+ "supported with EAPI='%s'") % (cpv, eapi))
+ operator = x
+ continue
+ uri = None
+ operator = None
+
+ if operator is not None:
+ raise portage.exception.InvalidDependString(
+ "getFetchMap(): '%s' SRC_URI arrow missing right operand" % \
+ (cpv,))
+
class portdbapi(dbapi):
"""this tree will scan a portage directory located at root (passed to init)"""
portdbapi_instances = []
@@ -450,9 +496,24 @@ class portdbapi(dbapi):
return returnme
- def getfetchlist(self, mypkg, useflags=None, mysettings=None, all=0, mytree=None):
- if mysettings is None:
- mysettings = self.doebuild_settings
+ def getFetchMap(self, mypkg, useflags=None, mytree=None):
+ """
+ Get the SRC_URI metadata as a dict which maps each file name to a
+ set of alternative URIs.
+
+ @param mypkg: cpv for an ebuild
+ @type mypkg: String
+ @param useflags: a collection of enabled USE flags, for evaluation of
+ conditionals
+ @type useflags: set, or None to enable all conditionals
+ @param mytree: The canonical path of the tree in which the ebuild
+ is located, or None for automatic lookup
+ @type mypkg: String
+ @returns: A dict which maps each file name to a set of alternative
+ URIs.
+ @rtype: dict
+ """
+
try:
eapi, myuris = self.aux_get(mypkg,
["EAPI", "SRC_URI"], mytree=mytree)
@@ -460,33 +521,80 @@ class portdbapi(dbapi):
# Convert this to an InvalidDependString exception since callers
# already handle it.
raise portage.exception.InvalidDependString(
- "getfetchlist(): aux_get() error reading "+mypkg+"; aborting.")
+ "getFetchMap(): aux_get() error reading "+mypkg+"; aborting.")
if not eapi_is_supported(eapi):
# Convert this to an InvalidDependString exception
# since callers already handle it.
raise portage.exception.InvalidDependString(
- "getfetchlist(): '%s' has unsupported EAPI: '%s'" % \
+ "getFetchMap(): '%s' has unsupported EAPI: '%s'" % \
(mypkg, eapi.lstrip("-")))
- if not all and useflags is None:
+ myuris = paren_reduce(myuris)
+ _src_uri_validate(mypkg, eapi, myuris)
+ myuris = use_reduce(myuris, uselist=useflags,
+ matchall=(useflags is None))
+ myuris = flatten(myuris)
+
+ uri_map = {}
+
+ uri = None
+ operator = None
+ myuris.reverse()
+ while myuris:
+ token = myuris.pop()
+ if uri is None:
+ uri = token
+ if myuris:
+ continue
+ if token == "->":
+ if eapi in ("0", "1"):
+ raise portage.exception.InvalidDependString(
+ ("getFetchMap(): '%s' SRC_URI arrows are not " + \
+ "supported with EAPI='%s'") % (mypkg, eapi))
+
+ operator = token
+ continue
+ if operator is None:
+ distfile = os.path.basename(uri)
+ if not distfile:
+ raise portage.exception.InvalidDependString(
+ ("getFetchMap(): '%s' SRC_URI has no file " + \
+ "name: '%s'") % (mypkg, uri))
+ else:
+ distfile = token
+ if "/" in distfile:
+ raise portage.exception.InvalidDependString(
+ ("getFetchMap(): '%s' SRC_URI '/' character in " + \
+ "file name: '%s'") % (mypkg, distfile))
+ uri_set = uri_map.get(distfile)
+ if uri_set is None:
+ uri_set = set()
+ uri_map[distfile] = uri_set
+ uri_set.add(uri)
+ uri = None
+ operator = None
+
+ return uri_map
+
+ def getfetchlist(self, mypkg, useflags=None, mysettings=None,
+ all=0, mytree=None):
+
+ writemsg("!!! pordbapi.getfetchlist() is deprecated, " + \
+ "use getFetchMap() instead.\n", noiselevel=-1)
+
+ if all:
+ useflags = None
+ elif useflags is None:
+ if mysettings is None:
+ mysettings = self.doebuild_settings
mysettings.setcpv(mypkg, mydb=self)
useflags = mysettings["PORTAGE_USE"].split()
-
- myurilist = paren_reduce(myuris)
- myurilist = use_reduce(myurilist, uselist=useflags, matchall=all)
- newuris = flatten(myurilist)
-
- myfiles = []
- for x in newuris:
- mya = os.path.basename(x)
- if not mya:
- raise portage.exception.InvalidDependString(
- "getfetchlist(): '%s' SRC_URI has no file name: '%s'" % \
- (mypkg, x))
- if not mya in myfiles:
- myfiles.append(mya)
- return [newuris, myfiles]
+ uri_map = self.getFetchMap(mypkg, useflags=useflags, mytree=mytree)
+ uris = set()
+ for uri_set in uri_map.itervalues():
+ uris.update(uri_set)
+ return [list(uris), uri_map.keys()]
def getfetchsizes(self, mypkg, useflags=None, debug=0):
# returns a filename:size dictionnary of remaining downloads
@@ -499,10 +607,7 @@ class portdbapi(dbapi):
print "[empty/missing/bad digest]: "+mypkg
return None
filesdict={}
- if useflags is None:
- myuris, myfiles = self.getfetchlist(mypkg,all=1)
- else:
- myuris, myfiles = self.getfetchlist(mypkg,useflags=useflags)
+ myfiles = self.getFetchMap(mypkg, useflags=useflags)
#XXX: maybe this should be improved: take partial downloads
# into account? check checksums?
for myfile in myfiles:
@@ -530,10 +635,12 @@ class portdbapi(dbapi):
return filesdict
def fetch_check(self, mypkg, useflags=None, mysettings=None, all=False):
- if not useflags:
+ if all:
+ useflags = None
+ elif useflags is None:
if mysettings:
useflags = mysettings["USE"].split()
- myuri, myfiles = self.getfetchlist(mypkg, useflags=useflags, mysettings=mysettings, all=all)
+ myfiles = self.getFetchMap(mypkg, useflags=useflags)
myebuild = self.findname(mypkg)
pkgdir = os.path.dirname(myebuild)
mf = Manifest(pkgdir, self.mysettings["DISTDIR"])