2 # pylint: disable-msg=C0103,E0611,W0511
8 Functions for extracting useful info from a pkg URI
9 such as PN, PV, MY_P, SRC_URI
11 * Examples of what it can detect/convert:
12 (See test_enamer.py for full capabilities)
14 http://www.foo.com/pkgfoo-1.0.tbz2
17 Ebuild name: pkgfoo-1.0.ebuild
18 SRC_URI="http://www.foo.com/${P}.tbz2"
20 http://www.foo.com/PkgFoo-1.0.tbz2
23 Ebuild name: pkgfoo-1.0.ebuild
25 SRC_URI="http://www.foo.com/${MY_P}.tbz2"
27 http://www.foo.com/pkgfoo_1.0.tbz2
30 Ebuild name: pkgfoo-1.0.ebuild
32 SRC_URI="http://www.foo.com/${MY_P}.tbz2"
34 http://www.foo.com/PKGFOO_1.0.tbz2
37 Ebuild name: pkgfoo-1.0.ebuild
39 SRC_URI="http://www.foo.com/${MY_P}.tbz2"
41 http://www.foo.com/pkg-foo-1.0_beta1.tbz2
44 Ebuild name: pkg-foo-1.0_beta1.ebuild
45 SRC_URI="http://www.foo.com/${P}.tbz2"
52 from portage import pkgsplit
56 from portage import dep as portage_dep
59 from portage import portage_dep
63 from portage import exception as portage_exception
66 from portage import portage_exception
68 __docformat__ = 'restructuredtext'
71 def get_filename(uri):
73 Return file name minus extension from src_uri
74 e.g. http://somesite.com/foobar-1.0.tar.gz will yield foobar-1.0
76 @param uri: URI to package with no variables substitution
82 path = urlparse.urlparse(uri)[2]
83 path = path.split('/')
84 return strip_ext(path[len(path)-1])
87 """Strip possible extensions from filename."""
88 valid_extensions = [".zip", ".tgz", ".tar.gz", ".tar.bz2", ".tbz2"]
89 for ext in valid_extensions:
90 if fname.endswith(ext):
91 fname = fname.replace(ext, "")
95 def is_valid_uri(uri):
97 Check if URI's addressing scheme is valid
99 @param uri: URI to pacakge with no variable substitution
102 @returns: True or False
104 if uri.startswith("http:") or uri.startswith("ftp:") or \
105 uri.startswith("mirror:") or uri.startswith("svn:"):
110 def parse_sourceforge_uri(uri):
112 Change URI to mirror://sourceforge format
113 Also determines a homepage string which can be used if the metadata
114 doesn't have Home_page
116 @param uri: URI to pacakge with no variable substitution
119 @returns: tuple (uri string, homepage string)
121 uri_out = homepage = ""
122 tst_uri = urlparse.urlparse(uri)
126 if upath.startswith("/sourceforge"):
128 if ("sourceforge" in host) or (host.endswith("sf.net")):
129 uri_out = 'mirror://sourceforge%s' % upath
130 homepage = "http://sourceforge.net/projects/%s/" % \
132 return uri_out, homepage
134 def is_good_filename(uri):
135 """If filename is sane enough to deduce PN & PV, return pkgsplit results"""
136 if is_valid_uri(uri):
137 psplit = split_p(uri)
138 if psplit and psplit[0].islower():
142 """Try to split a URI into PN, PV"""
143 p = get_filename(uri)
146 def get_components(uri):
147 """Split uri into pn and pv and new uri"""
148 p = get_filename(uri)
149 psplit = split_p(uri)
150 uri_out = uri.replace(p, "${P}")
151 pn = psplit[0].lower()
153 return uri_out, pn, pv
156 """Return MY_P and new uri with MY_P in it"""
157 my_p = get_filename(uri)
158 uri_out = uri.replace(my_p, "${MY_P}")
161 def guess_components(my_p):
162 """Try to break up raw MY_P into PN and PV"""
165 # Ok, we just have one automagical test here.
166 # We should look at versionator.eclass for inspiration
167 # and then come up with several functions.
168 my_p = my_p.replace("_", "-")
170 psplit = pkgsplit(my_p)
172 pn = psplit[0].lower()
177 def bad_pv(up_pn, up_pv, pn="", pv="", my_pn="", my_pv=""):
179 Can't determine PV from upstream's version.
180 Do our best with some well-known versioning schemes:
186 1.0-r1234 (1.0_pre1234)
187 1.0dev-r1234 (1.0_pre1234)
188 1.0.dev-r1234 (1.0_pre1234)
192 group 1 pv major (1.0)
193 group 2 entire suffix (.dev-r1234)
194 group 3 replace this with portage suffix (.dev-r)
195 group 4 suffix version (1234)
197 The order of the regex's is significant. For instance if you have
198 .dev-r123, dev-r123 and -r123 you should order your regex's in
201 The number of regex's could have been reduced, but we use four
202 number of match.groups every time to simplify the code
204 The _pre suffix is most-likely incorrect. There is no 'dev'
205 prefix used by portage, the 'earliest' there is is '_alpha'.
206 The chronological portage release versions are:
216 '_pre': ['(.*)((\.dev-r)([0-9]+))$',
217 '(.*)((dev-r)([0-9]+))$',
218 '(.*)((-r)([0-9]+))$'],
219 '_alpha': ['(.*)((-a)([0-9]+))$', '(.*)((a)([0-9]+))$'],
220 '_beta': ['(.*)((-b)([0-9]+))$', '(.*)((b)([0-9]+))$'],
221 '_rc': ['(.*)((\.rc)([0-9]+))$', '(.*)((-rc)([0-9]+))$',
222 '(.*)((rc)([0-9]+))$', '(.*)((-c)([0-9]+))$',
223 '(.*)((\.c)([0-9]+))$', '(.*)((c)([0-9]+))$'],
225 sufs = suf_matches.keys()
227 for this_suf in sufs:
230 for regex in suf_matches[this_suf]:
231 rsuffix_regex = re.compile(regex)
232 rs_match = rsuffix_regex.match(up_pv)
234 portage_suffix = this_suf
238 major_ver = rs_match.group(1) # 1.0
239 #whole_suffix = rs_match.group(2) #.dev-r1234
240 replace_me = rs_match.group(3) #.dev-r
241 rev = rs_match.group(4) #1234
242 if not up_pn.islower():
245 pv = major_ver + portage_suffix + rev
247 my_p = "${MY_PN}-${MY_PV}"
249 my_p = "${PN}-${MY_PV}"
250 my_pv = "${PV/%s/%s}" % (portage_suffix, replace_me)
252 #Single suffixes with no numeric component are simply removed.
254 bad_suffixes = [".dev", "-dev", "dev", ".final", "-final", "final"]
255 for suffix in bad_suffixes:
256 if up_pv.endswith(suffix):
257 my_pv = "${PV}%s" % suffix
258 my_p = "${PN}-${MY_PV}"
260 pv = up_pv[:-(len(suffix))]
266 return pn, pv, my_p, my_pn, my_pv
268 def sanitize_uri(uri):
270 Return URI without any un-needed extension.
271 e.g. http://downloads.sourceforge.net/pythonreports/PythonReports-0.3.1.tar.gz?modtime=1182702645&big_mirror=0
272 would have everything after '?' stripped
274 @param uri: URI to pacakge with no variable substitution
283 def get_vars(uri, up_pn, up_pv, pn="", pv="", my_pn="", my_pv=""):
285 Determine P* and MY_* variables
287 Don't modify this to accept new URI schemes without writing new
288 test_enamer unit tests
290 This function makes me weep and gives me nightmares.
294 uri = sanitize_uri(uri)
295 sf_uri, _sf_homepage = parse_sourceforge_uri(uri)
298 #XXX _sf_homepage can be used if package metadata doesn't have one
301 #Make sure we have a valid PV
303 #Test for PV with -r1234 suffix
304 #Portage uses -r suffixes for it's own ebuild revisions so
305 #we have to convert it to _pre or _alpha etc.
307 tail = up_pv.split("-")[-1:][0][0]
308 #we have a version with a -r[nnn] suffix
310 pn, pv, my_p, my_pn, my_pv = \
311 bad_pv(up_pn, up_pv, pn, pv, my_pn, my_pv)
315 if not portage_dep.isvalidatom("=dev-python/%s-%s" % (up_pn, up_pv)):
316 pn, pv, my_p, my_pn, my_pv = \
317 bad_pv(up_pn, up_pv, pn, pv, my_pn, my_pv)
319 #No PN or PV given on command-line, try upstream's name/version
320 if not pn and not pv:
321 #Try to determine pn and pv from uri
324 # pylint: disable-msg=W0612
325 # unused variable 'rev'
326 # The 'rev' is never used because these are
327 # new ebuilds being created.
332 #Try upstream's version if it could't be determined from uri or cli option
339 #up_pn is lower but uri has upper-case
346 pn = pn.replace('.', '-')
347 my_p = "${MY_PN}-${PV}"
349 p = "%s-%s" % (pn, pv)
351 #Check if we need to use MY_P based on src's uri
353 src_uri, my_p_raw = get_myp(uri)
355 src_uri, my_p, my_p_raw = get_src_uri(uri)
357 #Make sure we have a valid P
358 if not portage_dep.isvalidatom("=dev-python/%s-%s" % (pn, pv)):
359 if not portage_dep.isjustname("dev-python/%s-%s" % (pn, pv)):
360 raise portage_exception.InvalidPackageName(pn)
362 raise portage_exception.InvalidVersionString(pv)
365 my_pn = "-".join(my_p.split("-")[:-1])
366 if (my_pn == pn) or (my_pn == "${PN}"):
370 if my_p == "%s-%s" % (my_pn, "${PV}"):
371 my_p = "${MY_PN}-${PV}"
372 elif my_p == "%s-%s" % (my_pn, my_pv):
373 my_p = "${MY_PN}-${MY_PV}"
374 elif my_p == "%s-%s" % ("${PN}", my_pv):
375 my_p = "${PN}-${MY_PV}"
377 my_p = my_p.replace(pn, "${PN}")
378 my_p = my_p.replace(pv, "${PV}")
386 'my_p_raw': my_p_raw,
390 def get_src_uri(uri):
393 if is_good_filename(uri):
394 src_uri, pn, pv = get_components(uri)
396 src_uri, my_p = get_myp(uri)
397 pn, pv = guess_components(my_p)
400 my_p = my_p.replace(pn, "${PN}")
401 my_p = my_p.replace(pv, "${PV}")
403 return src_uri, my_p, my_p_raw