mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 15:27:17 +00:00
158 lines
6.3 KiB
Python
158 lines
6.3 KiB
Python
#
|
|
# Copyright (c) 2021-2024 ahriman team.
|
|
#
|
|
# This file is part of ahriman
|
|
# (see https://github.com/arcan1s/ahriman).
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
import argparse
|
|
import sys
|
|
|
|
from pathlib import Path
|
|
|
|
from ahriman.application.application import Application
|
|
from ahriman.application.handlers.handler import Handler
|
|
from ahriman.core.build_tools.sources import Sources
|
|
from ahriman.core.configuration import Configuration
|
|
from ahriman.core.formatters import PatchPrinter
|
|
from ahriman.models.action import Action
|
|
from ahriman.models.package import Package
|
|
from ahriman.models.pkgbuild_patch import PkgbuildPatch
|
|
from ahriman.models.repository_id import RepositoryId
|
|
|
|
|
|
class Patch(Handler):
|
|
"""
|
|
patch control handler
|
|
"""
|
|
|
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
|
|
|
@classmethod
|
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
|
report: bool) -> None:
|
|
"""
|
|
callback for command line
|
|
|
|
Args:
|
|
args(argparse.Namespace): command line args
|
|
repository_id(RepositoryId): repository unique identifier
|
|
configuration(Configuration): configuration instance
|
|
report(bool): force enable or disable reporting
|
|
"""
|
|
application = Application(repository_id, configuration, report=report)
|
|
application.on_start()
|
|
|
|
match args.action:
|
|
case Action.Update if args.variable is not None:
|
|
patch = Patch.patch_create_from_function(args.variable, args.patch)
|
|
Patch.patch_set_create(application, args.package, patch)
|
|
case Action.Update:
|
|
package_base, patch = Patch.patch_create_from_diff(args.package, repository_id.architecture, args.track)
|
|
Patch.patch_set_create(application, package_base, patch)
|
|
case Action.List:
|
|
Patch.patch_set_list(application, args.package, args.variable, args.exit_code)
|
|
case Action.Remove:
|
|
Patch.patch_set_remove(application, args.package, args.variable)
|
|
|
|
@staticmethod
|
|
def patch_create_from_diff(sources_dir: Path, architecture: str, track: list[str]) -> tuple[str, PkgbuildPatch]:
|
|
"""
|
|
create PKGBUILD plain diff patches from sources directory
|
|
|
|
Args:
|
|
sources_dir(Path): path to directory with the package sources
|
|
architecture(str): repository architecture
|
|
track(list[str]): track files which match the glob before creating the patch
|
|
|
|
Returns:
|
|
tuple[str, PkgbuildPatch]: package base and created PKGBUILD patch based on the diff from master HEAD
|
|
to current files
|
|
"""
|
|
package = Package.from_build(sources_dir, architecture, None)
|
|
patch = Sources.patch_create(sources_dir, *track)
|
|
return package.base, PkgbuildPatch(None, patch)
|
|
|
|
@staticmethod
|
|
def patch_create_from_function(variable: str, patch_path: Path | None) -> PkgbuildPatch:
|
|
"""
|
|
create single-function patch set for the package base
|
|
|
|
Args:
|
|
variable(str): function or variable name inside PKGBUILD
|
|
patch_path(Path | None): optional path to patch content. If not set, it will be read from stdin
|
|
|
|
Returns:
|
|
PkgbuildPatch: created patch for the PKGBUILD function
|
|
"""
|
|
if patch_path is None:
|
|
# pylint: disable=bad-builtin
|
|
print("Post new function or variable value below. Press Ctrl-D to finish:", file=sys.stderr)
|
|
patch = "".join(list(sys.stdin))
|
|
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)
|
|
|
|
@staticmethod
|
|
def patch_set_create(application: Application, package_base: str, patch: PkgbuildPatch) -> None:
|
|
"""
|
|
create patch set for the package base
|
|
|
|
Args:
|
|
application(Application): application instance
|
|
package_base(str): package base
|
|
patch(PkgbuildPatch): patch descriptor
|
|
"""
|
|
application.reporter.package_patches_update(package_base, patch)
|
|
|
|
@staticmethod
|
|
def patch_set_list(application: Application, package_base: str, variables: list[str] | None,
|
|
exit_code: bool) -> None:
|
|
"""
|
|
list patches available for the package base
|
|
|
|
Args:
|
|
application(Application): application instance
|
|
package_base(str): package base
|
|
variables(list[str] | None): extract patches only for specified PKGBUILD variables
|
|
exit_code(bool): exit with error on empty search result
|
|
"""
|
|
patches = [
|
|
patch
|
|
for patch in application.reporter.package_patches_get(package_base, None)
|
|
if variables is None or patch.key in variables
|
|
]
|
|
Patch.check_status(exit_code, bool(patches))
|
|
|
|
PatchPrinter(package_base, patches)(verbose=True, separator=" = ")
|
|
|
|
@staticmethod
|
|
def patch_set_remove(application: Application, package_base: str, variables: list[str] | None) -> None:
|
|
"""
|
|
remove patch set for the package base
|
|
|
|
Args:
|
|
application(Application): application instance
|
|
package_base(str): package base
|
|
variables(list[str] | None): remove patches only for specified PKGBUILD variables
|
|
"""
|
|
if variables is not None:
|
|
for variable in variables: # iterate over single variable
|
|
application.reporter.package_patches_remove(package_base, variable)
|
|
else:
|
|
application.reporter.package_patches_remove(package_base, None) # just pass as is
|