mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:27:44 +00:00
Meta: Use Python to parse a port's package.sh
in lint-ports
This reduced the runtime of `lint-ports` from 72s down to 0.5s on my computer (a reduction of ~99.2%)! While it may not be as accurate as running `package.sh showproperty` it makes using `precommit` while editing ports much nicer!
This commit is contained in:
parent
cba46a2d64
commit
bc75fa878e
1 changed files with 70 additions and 12 deletions
|
@ -87,24 +87,82 @@ def read_port_dirs():
|
|||
PORT_PROPERTIES = ('port', 'version', 'files', 'auth_type')
|
||||
|
||||
|
||||
def resolve_script_values(value: str, props: dict) -> str:
|
||||
"""Resolve all ${...} values in a string.
|
||||
|
||||
Args:
|
||||
value (str): string to resolve
|
||||
props (dict): dict of properties to resolve from
|
||||
|
||||
Returns:
|
||||
str: resolved string
|
||||
"""
|
||||
for match in re.finditer(r'\$\{([^}]+)\}', value):
|
||||
key = match.group(1)
|
||||
if key in props:
|
||||
value = value.replace(match.group(0), props[key])
|
||||
return value
|
||||
|
||||
|
||||
def get_script_props(dir: str, script_name: str, props: dict, depth: int = 0, max_depth: int = 10) -> dict:
|
||||
"""Parse a script file and return a dict of properties.
|
||||
|
||||
Args:
|
||||
dir (str): root directory of script
|
||||
script_name (str): name of script to parse
|
||||
props (dict): dict of properties to resolve from
|
||||
depth (int): current depth of recursion
|
||||
max_depth (int): maximum depth of recursion
|
||||
|
||||
Returns:
|
||||
dict: dict of properties
|
||||
"""
|
||||
if depth > max_depth:
|
||||
print(f"Maximum recursion depth exceeded while parsing {dir}/{script_name}")
|
||||
return props
|
||||
|
||||
buffer: str = ""
|
||||
for line in open(f"{dir}/{script_name}", 'r'):
|
||||
# Ignore comments (search in reverse to ignore # in strings)
|
||||
if line.rfind("#") > min(line.rfind('"'), line.rfind("'"), 0):
|
||||
line = line[0:line.rfind("#")]
|
||||
|
||||
line = line.rstrip()
|
||||
buffer += line
|
||||
|
||||
if "=" in buffer:
|
||||
[key, value] = buffer.split("=", 1)
|
||||
|
||||
if (key.startswith(" ") or key.isspace()):
|
||||
buffer = ""
|
||||
continue
|
||||
|
||||
if (value.startswith(('"', "'"))):
|
||||
if (value.endswith(value[0])):
|
||||
value = value[1:-1]
|
||||
else:
|
||||
buffer += "\n"
|
||||
continue
|
||||
|
||||
props[key] = resolve_script_values(value, props)
|
||||
buffer = ""
|
||||
elif buffer.startswith('source'):
|
||||
resolved_path = resolve_script_values(buffer, props).split(' ', 1)[1]
|
||||
props = get_script_props(dir, resolved_path, props, depth + 1, max_depth)
|
||||
buffer = ""
|
||||
else:
|
||||
buffer = ""
|
||||
return props
|
||||
|
||||
|
||||
def get_port_properties(port):
|
||||
"""Retrieves common port properties from its package.sh file.
|
||||
|
||||
Returns:
|
||||
dict: keys are values from PORT_PROPERTIES, values are from the package.sh file
|
||||
"""
|
||||
|
||||
package_sh_command = f"./package.sh showproperty {' '.join(PORT_PROPERTIES)}"
|
||||
res = subprocess.run(f"cd {port}; exec {package_sh_command}", shell=True, capture_output=True)
|
||||
if res.returncode == 0:
|
||||
results = res.stdout.decode('utf-8').split('\n\n')
|
||||
props = {prop: results[i].strip() for i, prop in enumerate(PORT_PROPERTIES)}
|
||||
else:
|
||||
print((
|
||||
f'Executing "{package_sh_command}" script for port {port} failed with '
|
||||
f'exit code {res.returncode}, output from stderr:\n{res.stderr.decode("utf-8").strip()}'
|
||||
))
|
||||
props = {x: '' for x in PORT_PROPERTIES}
|
||||
props = get_script_props(port, 'package.sh', {})
|
||||
props = {prop: props[prop] if prop in props else '' for prop in PORT_PROPERTIES}
|
||||
return props
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue