euscan-ng/src/euscan/mangling.py

174 lines
4.9 KiB
Python
Raw Normal View History

# Copyright 2011 Corentin Chary <corentin.chary@gmail.com>
# Copyright 2020-2023 src_prepare group
# Distributed under the terms of the GNU General Public License v2
import re
import euscan.handlers
def apply_mangling_rule(mangle, string):
# convert regex from perl format to python format
# there are some regex in this format: s/pattern/replacement/
m = re.match(r"s/(.*[^\\])/(.*)/", mangle)
if not m:
# or in this format s|pattern|replacement|
m = re.match(r"s\|(.*[^\\])\|(.*)\|", mangle)
if not m: # Not a known regex format
return string
pattern, repl = m.groups()
repl = re.sub(r"\$(\d+)", r"\\\1", repl)
return re.sub(pattern, repl, string)
def apply_mangling_rules(kind, rules, string):
"""
Apply multiple mangling rules (both sed-like and handlers)
in order
"""
if kind not in rules:
return string
for rule in rules[kind]:
ret = None
# First try handlers rules
if rule == "gentoo" and kind == "versionmangle":
ret = gentoo_mangle_version(string)
elif kind == "downloadurlmangle":
ret = euscan.handlers.mangle_url(rule, string)
elif kind == "versionmangle":
ret = euscan.handlers.mangle_version(rule, string)
if ret is not None: # Use return value as new string if not None
string = ret
else: # Apply sed like rules
string = apply_mangling_rule(rule, string)
return string
def mangle_version(up_pv, options):
# Default rule is gentoo when empty
if "versionmangle" not in options or not options["versionmangle"]:
options["versionmangle"] = ["gentoo"]
return apply_mangling_rules("versionmangle", options, up_pv)
def mangle_url(url, options):
return apply_mangling_rules("downloadurlmangle", options, url)
# Stolen from g-pypi
def gentoo_mangle_version(up_pv):
"""Convert PV to MY_PV if needed
:param up_pv: Upstream package version
:type up_pv: string
:returns: pv
:rtype: string
Can't determine PV from upstream's version.
Do our best with some well-known versioning schemes:
* 1.0a1 (1.0_alpha1)
* 1.0-a1 (1.0_alpha1)
* 1.0b1 (1.0_beta1)
* 1.0-b1 (1.0_beta1)
* 1.0-r1234 (1.0_pre1234)
* 1.0dev-r1234 (1.0_pre1234)
* 1.0.dev-r1234 (1.0_pre1234)
* 1.0dev-20091118 (1.0_pre20091118)
Regex match.groups():
* pkgfoo-1.0.dev-r1234
* group 1 pv major (1.0)
* group 2 replace this with portage suffix (.dev-r)
* group 3 suffix version (1234)
The order of the regexes is significant. For instance if you have
.dev-r123, dev-r123 and -r123 you should order your regex's in
that order.
The chronological portage release versions are:
* _alpha
* _beta
* _pre
* _rc
* release
* _p
**Example:**
>>> gentoo_mangle_version('1.0b2')
'1.0_beta2'
.. note::
The number of regex's could have been reduced, but we use four
number of match.groups every time to simplify the code
"""
bad_suffixes = re.compile(r"((?:[._-]*)(?:dev|devel|final|stable|snapshot)$)", re.I)
revision_suffixes = re.compile(r"(.*?)([\._-]*(?:r|patch|p)[\._-]*)([0-9]*)$", re.I)
suf_matches = {
"_pre": [
r"(.*?)([\._-]*dev[\._-]*r?)([0-9]+)$",
r"(.*?)([\._-]*(?:pre|preview)[\._-]*)([0-9]*)$",
],
"_alpha": [
r"(.*?)([\._-]*(?:alpha|test)[\._-]*)([0-9]*)$",
r"(.*?)([\._-]*a[\._-]*)([0-9]*)$",
r"(.*[^a-z])(a)([0-9]*)$",
],
"_beta": [
r"(.*?)([\._-]*beta[\._-]*)([0-9]*)$",
r"(.*?)([\._-]*b)([0-9]*)$",
r"(.*[^a-z])(b)([0-9]*)$",
],
"_rc": [
r"(.*?)([\._-]*rc[\._-]*)([0-9]*)$",
r"(.*?)([\._-]*c[\._-]*)([0-9]*)$",
r"(.*[^a-z])(c[\._-]*)([0-9]+)$",
],
}
rs_match = None
pv = up_pv
additional_version = ""
rev_match = revision_suffixes.search(up_pv)
if rev_match:
pv = up_pv = rev_match.group(1)
# replace_me = rev_match.group(2)
rev = rev_match.group(3)
additional_version = "_p" + rev
2019-12-05 17:46:19 +01:00
for this_suf in list(suf_matches.keys()):
if rs_match:
break
for regex in suf_matches[this_suf]:
rsuffix_regex = re.compile(regex, re.I)
rs_match = rsuffix_regex.match(up_pv)
if rs_match:
portage_suffix = this_suf
break
if rs_match:
# e.g. 1.0.dev-r1234
major_ver = rs_match.group(1) # 1.0
# replace_me = rs_match.group(2) # .dev-r
rev = rs_match.group(3) # 1234
pv = major_ver + portage_suffix + rev
else:
# Single suffixes with no numeric component are simply removed.
match = bad_suffixes.search(up_pv)
if match:
suffix = match.groups()[0]
pv = up_pv[: -(len(suffix))]
pv = pv + additional_version
return pv