diff --git a/src/ahriman/application/handlers/patch.py b/src/ahriman/application/handlers/patch.py index 124fa795..b2abb2f3 100644 --- a/src/ahriman/application/handlers/patch.py +++ b/src/ahriman/application/handlers/patch.py @@ -198,8 +198,7 @@ class Patch(Handler): else: patch = patch_path.read_text(encoding="utf8") # remove spaces around the patch and parse to correct type - parsed = PkgbuildPatch.parse(patch.strip()) - return PkgbuildPatch(variable, parsed) + return PkgbuildPatch.parse(variable, patch.strip()) @staticmethod def patch_set_create(application: Application, package_base: str, patch: PkgbuildPatch) -> None: diff --git a/src/ahriman/core/database/operations/patch_operations.py b/src/ahriman/core/database/operations/patch_operations.py index e657a346..61f479dc 100644 --- a/src/ahriman/core/database/operations/patch_operations.py +++ b/src/ahriman/core/database/operations/patch_operations.py @@ -83,7 +83,7 @@ class PatchOperations(Operations): """ def run(connection: Connection) -> list[tuple[str, PkgbuildPatch]]: return [ - (row["package_base"], PkgbuildPatch(row["variable"], row["patch"])) + (row["package_base"], PkgbuildPatch.parse(row["variable"], row["patch"])) for row in connection.execute( """select * from patches where :package_base is null or package_base = :package_base""", {"package_base": package_base}) diff --git a/src/ahriman/models/pkgbuild_patch.py b/src/ahriman/models/pkgbuild_patch.py index 69f93c8d..834d8610 100644 --- a/src/ahriman/models/pkgbuild_patch.py +++ b/src/ahriman/models/pkgbuild_patch.py @@ -17,6 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # +import json import shlex from dataclasses import dataclass, fields @@ -79,11 +80,11 @@ class PkgbuildPatch: variable(str): variable in bash form, i.e. KEY=VALUE Returns: - Self: package properties + Self: patch object """ key, *value_parts = variable.split("=", maxsplit=1) raw_value = next(iter(value_parts), "") # extract raw value - return cls(key, cls.parse(raw_value)) + return cls.parse(key, raw_value) @classmethod def from_json(cls, dump: dict[str, Any]) -> Self: @@ -100,21 +101,36 @@ class PkgbuildPatch: known_fields = [pair.name for pair in fields(cls)] return cls(**filter_json(dump, known_fields)) - @staticmethod - def parse(source: str) -> str | list[str]: + @classmethod + def parse(cls, key: str, source: str) -> Self: """ parse string value to the PKGBUILD patch value. This method simply takes string, tries to identify it as array - or just string and return the respective value. Functions should be processed correctly, however, not guaranteed + or just string and return the respective value. Functions are returned as is. Shell arrays and single values + are returned without quotes Args: - source(str): source string to parse + key(str): variable key + source(str): source value string to parse Returns: - str | list[str]: parsed value either string or list of strings + Self: parsed patch object """ - if source.startswith("(") and source.endswith(")"): - return shlex.split(source[1:-1]) # arrays for poor - return PkgbuildPatch.unquote(source) + def value() -> str | list[str]: + match source: + case function if key.endswith("()"): + # the key looks like a function, no further processing should be applied here + return function + case shell_array if shell_array.startswith("(") and shell_array.endswith(")"): + # the source value looks like shell array, remove brackets and parse with shlex + return shlex.split(shell_array[1:-1]) + case json_array if json_array.startswith("[") and json_array.endswith("]"): + # json (aka python) array, parse with json parser instead + parsed: list[str] = json.loads(json_array) + return parsed + case variable: + return cls.unquote(variable) + + return cls(key, value()) @staticmethod def unquote(source: str) -> str: