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)
147 def get_components(uri):
148 """Split uri into pn and pv and new uri"""
149 p = get_filename(uri)
150 psplit = split_p(uri)
151 uri_out = uri.replace(p, "${P}")
152 pn = psplit[0].lower()
154 return uri_out, pn, pv
157 """Return MY_P and new uri with MY_P in it"""
158 my_p = get_filename(uri)
159 uri_out = uri.replace(my_p, "${MY_P}")
162 def guess_components(my_p):
163 """Try to break up raw MY_P into PN and PV"""
166 # Ok, we just have one automagical test here.
167 # We should look at versionator.eclass for inspiration
168 # and then come up with several functions.
169 my_p = my_p.replace("_", "-")
171 psplit = pkgsplit(my_p)
173 pn = psplit[0].lower()
178 def bad_pv(up_pn, up_pv, pn="", pv="", my_pn="", my_pv=""):
180 Can't determine PV from upstream's version.
181 Do our best with some well-known versioning schemes:
187 1.0-r1234 (1.0_pre1234)
188 1.0dev-r1234 (1.0_pre1234)
189 1.0.dev-r1234 (1.0_pre1234)
193 group 1 pv major (1.0)
194 group 2 entire suffix (.dev-r1234)
195 group 3 replace this with portage suffix (.dev-r)
196 group 4 suffix version (1234)
198 The order of the regex's is significant. For instance if you have
199 .dev-r123, dev-r123 and -r123 you should order your regex's in
202 The number of regex's could have been reduced, but we use four
203 number of match.groups every time to simplify the code
205 The _pre suffix is most-likely incorrect. There is no 'dev'
206 prefix used by portage, the 'earliest' there is is '_alpha'.
207 The chronological portage release versions are:
217 '_pre': ['(.*)((\.dev-r)([0-9]+))$',
218 '(.*)((dev-r)([0-9]+))$',
219 '(.*)((-r)([0-9]+))$'],
220 '_alpha': ['(.*)((-a)([0-9]+))$', '(.*)((a)([0-9]+))$'],
221 '_beta': ['(.*)((-b)([0-9]+))$', '(.*)((b)([0-9]+))$'],
222 '_rc': ['(.*)((\.rc)([0-9]+))$', '(.*)((-rc)([0-9]+))$',
223 '(.*)((rc)([0-9]+))$', '(.*)((-c)([0-9]+))$',
224 '(.*)((\.c)([0-9]+))$', '(.*)((c)([0-9]+))$'],
226 sufs = suf_matches.keys()
228 for this_suf in sufs:
231 for regex in suf_matches[this_suf]:
232 rsuffix_regex = re.compile(regex)
233 rs_match = rsuffix_regex.match(up_pv)
235 portage_suffix = this_suf
239 major_ver = rs_match.group(1) # 1.0
240 #whole_suffix = rs_match.group(2) #.dev-r1234
241 replace_me = rs_match.group(3) #.dev-r
242 rev = rs_match.group(4) #1234
243 if not up_pn.islower():
246 pv = major_ver + portage_suffix + rev
248 my_p = "${MY_PN}-${MY_PV}"
250 my_p = "${PN}-${MY_PV}"
251 my_pv = "${PV/%s/%s}" % (portage_suffix, replace_me)
253 #Single suffixes with no numeric component are simply removed.
255 bad_suffixes = [".dev", "-dev", "dev", ".final", "-final", "final"]
256 for suffix in bad_suffixes:
257 if up_pv.endswith(suffix):
258 my_pv = "${PV}%s" % suffix
259 my_p = "${PN}-${MY_PV}"
261 pv = up_pv[:-(len(suffix))]
267 return pn, pv, my_p, my_pn, my_pv
269 def sanitize_uri(uri):
271 Return URI without any un-needed extension.
272 e.g. http://downloads.sourceforge.net/pythonreports/PythonReports-0.3.1.tar.gz?modtime=1182702645&big_mirror=0
273 would have everything after '?' stripped
275 @param uri: URI to pacakge with no variable substitution
284 def get_vars(uri, up_pn, up_pv, pn="", pv="", my_pn="", my_pv="", my_p=""):
286 Determine P* and MY_* variables
288 Don't modify this to accept new URI schemes without writing new
289 test_enamer unit tests
291 This function makes me weep and gives me nightmares.
295 uri = sanitize_uri(uri)
296 sf_uri, _sf_homepage = parse_sourceforge_uri(uri)
299 #XXX _sf_homepage can be used if package metadata doesn't have one
302 #Make sure we have a valid PV
304 #Test for PV with -r1234 suffix
305 #Portage uses -r suffixes for it's own ebuild revisions so
306 #we have to convert it to _pre or _alpha etc.
308 tail = up_pv.split("-")[-1:][0][0]
309 #we have a version with a -r[nnn] suffix
311 pn, pv, my_p, my_pn, my_pv = \
312 bad_pv(up_pn, up_pv, pn, pv, my_pn, my_pv)
316 if not portage_dep.isvalidatom("=dev-python/%s-%s" % (up_pn, up_pv)):
317 pn, pv, my_p, my_pn, my_pv = \
318 bad_pv(up_pn, up_pv, pn, pv, my_pn, my_pv)
320 #No PN or PV given on command-line, try upstream's name/version
321 if not pn and not pv:
322 #Try to determine pn and pv from uri
325 # pylint: disable-msg=W0612
326 # unused variable 'rev'
327 # The 'rev' is never used because these are
328 # new ebuilds being created.
333 #Try upstream's version if it could't be determined from uri or cli option
340 #up_pn is lower but uri has upper-case
344 p = "%s-%s" % (pn, pv)
347 #Make sure we have a valid P
348 if not portage_dep.isvalidatom("=dev-python/%s-%s" % (pn, pv)):
349 if not portage_dep.isjustname("dev-python/%s-%s" % (pn, pv)):
350 raise portage_exception.InvalidPackageName(pn)
352 raise portage_exception.InvalidVersionString(pv)
355 my_pn = "-".join(my_p.split("-")[:-1])
356 if (my_pn == pn) or (my_pn == "${PN}"):
360 if my_p == "%s-%s" % (my_pn, "${PV}"):
361 my_p = "${MY_PN}-${PV}"
362 elif my_p == "%s-%s" % (my_pn, my_pv):
363 my_p = "${MY_PN}-${MY_PV}"
364 elif my_p == "%s-%s" % ("${PN}", my_pv):
365 my_p = "${PN}-${MY_PV}"
367 my_p = my_p.replace(pn, "${PN}")
368 my_p = my_p.replace(pv, "${PV}")
370 if my_pn and not my_p:
372 my_p = '%s-%s' % (my_pn, my_pv)
374 my_p = '%s-%s' % (my_pn, '${PV}')
377 #Check if we need to use MY_P based on src's uri
379 src_uri, my_p_raw = get_myp(uri)
381 src_uri, my_p, my_p_raw = get_src_uri(uri)
389 'my_p_raw': my_p_raw,
393 def get_src_uri(uri):
396 if is_good_filename(uri):
397 src_uri, pn, pv = get_components(uri)
399 src_uri, my_p = get_myp(uri)
400 pn, pv = guess_components(my_p)
403 my_p = my_p.replace(pn, "${PN}")
404 my_p = my_p.replace(pv, "${PV}")
406 return src_uri, my_p, my_p_raw