201 lines
5.7 KiB
Python
201 lines
5.7 KiB
Python
import re
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from tree_sitter import Node
|
|
|
|
from aides_spec.replacers.arch_replacer import ArchReplacer
|
|
from aides_spec.replacers.base import BaseReplacer
|
|
|
|
|
|
class StringValue(str):
|
|
def __init__(self, node: "Node"):
|
|
self.node = node
|
|
|
|
def get_text_value(self) -> str:
|
|
value = self.node.text.decode("utf-8")
|
|
return value[1:-1]
|
|
|
|
def get_quote(self) -> str:
|
|
value = self.node.text.decode("utf-8")
|
|
return value[0]
|
|
|
|
def __repr__(self):
|
|
return self.node.text.decode("utf-8")
|
|
|
|
def __str__(self):
|
|
return self.__repr__()
|
|
|
|
|
|
class Utils:
|
|
def parse_variable_assignment(node: "Node"):
|
|
var_node = node.child_by_field_name("name")
|
|
value_node = node.child_by_field_name("value")
|
|
|
|
if not (var_node and value_node):
|
|
return None
|
|
|
|
return (var_node, value_node)
|
|
|
|
def get_string_values_from_array(node: "Node"):
|
|
arr = []
|
|
for item in node.children:
|
|
if (
|
|
item.type == "string"
|
|
or item.type == "raw_string"
|
|
or item.type == "concatenation"
|
|
):
|
|
arr.append(StringValue(item))
|
|
|
|
return arr
|
|
|
|
|
|
CHECKSUMS_REPLACEMENTS = {
|
|
"b2sums": "blake2b-512",
|
|
"sha512sums": "sha512",
|
|
"sha384sums": "sha384",
|
|
"sha256sums": "sha256",
|
|
"sha224sums": "sha224",
|
|
"sha1sums": "sha1",
|
|
"md5sums": "md5",
|
|
}
|
|
|
|
SOURCE_PATTERN = r"^source(?:_(x86_64|i686|armv7h|aarch64))?$"
|
|
CHECKSUMS_PATTERN = (
|
|
r"^(b2sums|sha512sums|sha384sums|sha256sums|sha224sums|sha1sums|md5sums)"
|
|
r"(?:_(x86_64|i686|armv7h|aarch64))?$"
|
|
)
|
|
|
|
|
|
class SourcesReplacer(BaseReplacer):
|
|
def process(self):
|
|
root_node = self.tree.root_node
|
|
|
|
self.local_files = []
|
|
self.prepare_func_body = None
|
|
|
|
self.nodes_to_remove = []
|
|
|
|
sources = dict()
|
|
checksums = dict()
|
|
|
|
def execute(node: "Node"):
|
|
if node.type == "function_definition":
|
|
func_name = self._node_text(node.child_by_field_name("name"))
|
|
if func_name != "prepare":
|
|
return
|
|
self.prepare_func_body = node
|
|
return
|
|
|
|
if node.type == "variable_assignment":
|
|
var_node = node.child_by_field_name("name")
|
|
value_node = node.child_by_field_name("value")
|
|
if not (var_node and value_node):
|
|
return
|
|
|
|
var_name = self._node_text(var_node)
|
|
|
|
re_match = re.match(SOURCE_PATTERN, var_name)
|
|
if re_match:
|
|
self.nodes_to_remove.append(node)
|
|
|
|
arch = re_match.group(1)
|
|
sources[arch if arch else "-"] = (
|
|
Utils.get_string_values_from_array(value_node)
|
|
)
|
|
|
|
re_match = re.match(CHECKSUMS_PATTERN, var_name)
|
|
if re_match:
|
|
self.nodes_to_remove.append(node)
|
|
|
|
checksum = CHECKSUMS_REPLACEMENTS[re_match.group(1)]
|
|
arch = re_match.group(2)
|
|
|
|
checksums[arch if arch else "-"] = [
|
|
f"'{checksum}:{v.get_text_value()}'"
|
|
for v in Utils.get_string_values_from_array(value_node)
|
|
]
|
|
|
|
def traverse(node: "Node"):
|
|
execute(node)
|
|
for child in node.children:
|
|
traverse(child)
|
|
|
|
traverse(root_node)
|
|
|
|
content = ""
|
|
|
|
for node in self.nodes_to_remove:
|
|
self.replaces.append({"node": node, "content": ""})
|
|
|
|
for arch, files in sources.items():
|
|
source_files = []
|
|
checksums_str = []
|
|
|
|
for i, file in enumerate(files):
|
|
file_name = file.get_text_value()
|
|
if "://" in file_name:
|
|
source_files.append(file)
|
|
checksums_str.append(checksums[arch][i])
|
|
else:
|
|
self.local_files.append(file)
|
|
|
|
content += self.source_to_str(arch, source_files) + "\n"
|
|
content += self.checksums_to_str(arch, checksums_str) + "\n"
|
|
|
|
if len(self.local_files) > 0:
|
|
copy_commands = "\n ".join(
|
|
f'cp "${{scriptdir}}/{file.get_text_value()}" "${{srcdir}}"'
|
|
for file in self.local_files
|
|
)
|
|
|
|
prepare_func_content = f"""
|
|
{copy_commands}
|
|
"""
|
|
if self.prepare_func_body is not None:
|
|
text = self._node_text(self.prepare_func_body)
|
|
closing_brace_index = text.rfind("}")
|
|
text = (
|
|
text[:closing_brace_index]
|
|
+ prepare_func_content
|
|
+ text[closing_brace_index:]
|
|
)
|
|
self.replaces.append(
|
|
{
|
|
"node": self.prepare_func_body,
|
|
"content": text,
|
|
}
|
|
)
|
|
else:
|
|
text = self._node_text(root_node)
|
|
content += f"""
|
|
prepare() {{
|
|
{prepare_func_content}}}
|
|
"""
|
|
|
|
self.appends.append(
|
|
{
|
|
"node": root_node,
|
|
"content": content,
|
|
}
|
|
)
|
|
|
|
return self._apply_replacements()
|
|
|
|
def source_to_str(self, arch, files):
|
|
return f"""
|
|
{f"sources_{ArchReplacer.ARCH_MAPPING[arch]}" if arch != '-' else "sources"}=(
|
|
{'\n '.join([s.__str__() for s in files])}
|
|
)"""
|
|
|
|
def checksums_to_str(self, arch, files):
|
|
var_name = (
|
|
f"checksums_{ArchReplacer.ARCH_MAPPING[arch]}"
|
|
if arch != "-"
|
|
else "checksums"
|
|
)
|
|
|
|
return f"""
|
|
{var_name}=(
|
|
{'\n '.join([s.__str__() for s in files])}
|
|
)"""
|