pmb/parse/_apkbuild: implement parsing for more variable styles (!1854)
Add a test for APKBUILD variable parsing as well
This commit is contained in:
parent
b0563c54d0
commit
2320e0100c
|
@ -16,58 +16,101 @@ GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with pmbootstrap. If not, see <http://www.gnu.org/licenses/>.
|
along with pmbootstrap. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
import os
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.parse.version
|
import pmb.parse.version
|
||||||
|
|
||||||
|
# sh variable name regex: https://stackoverflow.com/a/2821201/3527128
|
||||||
|
|
||||||
|
# ${foo}
|
||||||
|
revar = re.compile(r"\${([a-zA-Z_]+[a-zA-Z0-9_]*)}")
|
||||||
|
|
||||||
|
# $foo
|
||||||
|
revar2 = re.compile(r"\$([a-zA-Z_]+[a-zA-Z0-9_]*)")
|
||||||
|
|
||||||
|
# ${var/foo/bar}, ${var/foo/}, ${var/foo} -- replace foo with bar
|
||||||
|
revar3 = re.compile(r"\${([a-zA-Z_]+[a-zA-Z0-9_]*)/([^/]+)(?:/([^/]*?))?}")
|
||||||
|
|
||||||
|
# ${foo#bar} -- cut off bar from foo from start of string
|
||||||
|
revar4 = re.compile(r"\${([a-zA-Z_]+[a-zA-Z0-9_]*)#(.*)}")
|
||||||
|
|
||||||
|
|
||||||
|
def replace_variable(apkbuild, value: str) -> str:
|
||||||
|
# ${foo}
|
||||||
|
for match in revar.finditer(value):
|
||||||
|
try:
|
||||||
|
logging.verbose("{}: replace '{}' with '{}'".format(
|
||||||
|
apkbuild["pkgname"], match.group(0),
|
||||||
|
apkbuild[match.group(1)]))
|
||||||
|
value = value.replace(match.group(0), apkbuild[match.group(1)], 1)
|
||||||
|
except KeyError:
|
||||||
|
logging.debug("{}: key '{}' for replacing '{}' not found, ignoring"
|
||||||
|
"".format(apkbuild["pkgname"], match.group(1),
|
||||||
|
match.group(0)))
|
||||||
|
|
||||||
|
# $foo
|
||||||
|
for match in revar2.finditer(value):
|
||||||
|
try:
|
||||||
|
newvalue = apkbuild[match.group(1)]
|
||||||
|
if type(newvalue) is list:
|
||||||
|
newvalue = " ".join(newvalue)
|
||||||
|
logging.verbose("{}: replace '{}' with '{}'".format(
|
||||||
|
apkbuild["pkgname"], match.group(0),
|
||||||
|
newvalue))
|
||||||
|
value = value.replace(match.group(0), newvalue, 1)
|
||||||
|
except KeyError:
|
||||||
|
logging.debug("{}: key '{}' for replacing '{}' not found, ignoring"
|
||||||
|
"".format(apkbuild["pkgname"], match.group(1),
|
||||||
|
match.group(0)))
|
||||||
|
|
||||||
|
# ${var/foo/bar}, ${var/foo/}, ${var/foo}
|
||||||
|
for match in revar3.finditer(value):
|
||||||
|
newvalue = apkbuild[match.group(1)]
|
||||||
|
search = match.group(2)
|
||||||
|
replacement = match.group(3)
|
||||||
|
if replacement is None: # arg 3 is optional
|
||||||
|
replacement = ""
|
||||||
|
newvalue = newvalue.replace(search, replacement, 1)
|
||||||
|
logging.verbose("{}: replace '{}' with '{}'".format(
|
||||||
|
apkbuild["pkgname"], match.group(0), newvalue))
|
||||||
|
value = value.replace(match.group(0), newvalue, 1)
|
||||||
|
|
||||||
|
# ${foo#bar}
|
||||||
|
rematch4 = revar4.finditer(value)
|
||||||
|
for match in rematch4:
|
||||||
|
newvalue = apkbuild[match.group(1)]
|
||||||
|
substr = match.group(2)
|
||||||
|
if newvalue.startswith(substr):
|
||||||
|
newvalue = newvalue.replace(substr, "", 1)
|
||||||
|
logging.verbose("{}: replace '{}' with '{}'".format(
|
||||||
|
apkbuild["pkgname"], match.group(0), newvalue))
|
||||||
|
value = value.replace(match.group(0), newvalue, 1)
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
def replace_variables(apkbuild):
|
def replace_variables(apkbuild):
|
||||||
"""
|
"""
|
||||||
Replace a hardcoded list of variables inside the APKBUILD.
|
Replace a hardcoded list of variables inside the APKBUILD.
|
||||||
"""
|
"""
|
||||||
ret = apkbuild
|
ret = apkbuild
|
||||||
# _flavor: ${_device} (lineageos kernel packages)
|
|
||||||
ret["_flavor"] = ret["_flavor"].replace("${_device}",
|
|
||||||
ret["_device"])
|
|
||||||
|
|
||||||
# pkgname: $_flavor
|
# Iterate through all apkbuild attributes which get parsed
|
||||||
ret["pkgname"] = ret["pkgname"].replace("${_flavor}", ret["_flavor"])
|
for key in pmb.config.apkbuild_attributes:
|
||||||
|
if type(ret[key]) is list:
|
||||||
# subpackages, *depends*: $pkgname
|
replaced = []
|
||||||
for key in ["subpackages", "depends", "makedepends", "makedepends_host",
|
for value in ret[key]:
|
||||||
"makedepends_build"]:
|
replaced_value = replace_variable(ret, value).split()
|
||||||
replaced = []
|
replaced.extend(replaced_value)
|
||||||
for subpackage in ret[key]:
|
ret[key] = replaced
|
||||||
replaced.append(subpackage.replace("$pkgname", ret["pkgname"]))
|
elif type(ret[key]) is str:
|
||||||
ret[key] = replaced
|
ret[key] = replace_variable(ret, ret[key])
|
||||||
|
|
||||||
# makedepends: $makedepends_host, $makedepends_build, $_llvmver
|
|
||||||
replaced = []
|
|
||||||
for makedepend in ret["makedepends"]:
|
|
||||||
if makedepend.startswith("$"):
|
|
||||||
key = makedepend[1:]
|
|
||||||
if key in ret:
|
|
||||||
replaced += ret[key]
|
|
||||||
else:
|
|
||||||
raise RuntimeError("Could not resolve variable " +
|
|
||||||
makedepend + " in APKBUILD of " +
|
|
||||||
apkbuild["pkgname"])
|
|
||||||
else:
|
else:
|
||||||
# replace in the middle of the string
|
raise RuntimeError("Value type " + type(ret[key]) + " not handled.")
|
||||||
for var in ["_llvmver"]:
|
|
||||||
makedepend = makedepend.replace("$" + var, ret[var])
|
|
||||||
replaced += [makedepend]
|
|
||||||
|
|
||||||
# Python: ${pkgname#py-}
|
|
||||||
if ret["pkgname"].startswith("py-"):
|
|
||||||
replacement = ret["pkgname"][3:]
|
|
||||||
for var in ["depends", "makedepends", "subpackages"]:
|
|
||||||
for i in range(len(ret[var])):
|
|
||||||
ret[var][i] = ret[var][i].replace(
|
|
||||||
"${pkgname#py-}", replacement)
|
|
||||||
|
|
||||||
ret["makedepends"] = replaced
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -123,3 +123,10 @@ def test_parse_attributes():
|
||||||
with pytest.raises(RuntimeError) as e:
|
with pytest.raises(RuntimeError) as e:
|
||||||
func("depends", 'depends="')
|
func("depends", 'depends="')
|
||||||
assert str(e.value).startswith("Can't find closing")
|
assert str(e.value).startswith("Can't find closing")
|
||||||
|
|
||||||
|
|
||||||
|
def test_variable_replacements(args):
|
||||||
|
path = pmb_src + "/test/testdata/apkbuild/APKBUILD.variable-replacements"
|
||||||
|
apkbuild = pmb.parse.apkbuild(args, path, check_pkgname=False)
|
||||||
|
assert apkbuild["url"] == "replacements variable string-replacements"
|
||||||
|
assert apkbuild["subpackages"] == ["replacements", "test"]
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
pkgname="variable-replacements"
|
||||||
|
pkgver="1.0.0"
|
||||||
|
pkgrel=0
|
||||||
|
arch="armhf"
|
||||||
|
pkgdesc="variable-replacements test"
|
||||||
|
url="${pkgname/variable-} ${pkgname/-replacements/} ${pkgname/variable/string}"
|
||||||
|
subpackages="${pkgdesc#variable-}"
|
Loading…
Reference in New Issue