mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 07:17:17 +00:00
146 lines
5.8 KiB
Python
146 lines
5.8 KiB
Python
#
|
|
# Copyright (c) 2021-2022 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 typing import List, Optional, Tuple, Type
|
|
|
|
from ahriman.application.application import Application
|
|
from ahriman.application.handlers 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
|
|
|
|
|
|
class Patch(Handler):
|
|
"""
|
|
patch control handler
|
|
"""
|
|
|
|
@classmethod
|
|
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
|
report: bool, unsafe: bool) -> None:
|
|
"""
|
|
callback for command line
|
|
|
|
Args:
|
|
args(argparse.Namespace): command line args
|
|
architecture(str): repository architecture
|
|
configuration(Configuration): configuration instance
|
|
report(bool): force enable or disable reporting
|
|
unsafe(bool): if set no user check will be performed before path creation
|
|
"""
|
|
application = Application(architecture, configuration, report=report, unsafe=unsafe)
|
|
application.on_start()
|
|
|
|
if args.action == Action.Update and args.variable is not None:
|
|
patch = Patch.patch_create_from_function(args.variable, args.patch)
|
|
Patch.patch_set_create(application, args.package, patch)
|
|
elif args.action == Action.Update and args.variable is None:
|
|
package_base, patch = Patch.patch_create_from_diff(args.package, args.track)
|
|
Patch.patch_set_create(application, package_base, patch)
|
|
elif args.action == Action.List:
|
|
Patch.patch_set_list(application, args.package, args.variable, args.exit_code)
|
|
elif args.action == Action.Remove:
|
|
Patch.patch_set_remove(application, args.package, args.variable)
|
|
|
|
@staticmethod
|
|
def patch_create_from_diff(sources_dir: Path, 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
|
|
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)
|
|
patch = Sources.patch_create(sources_dir, *track)
|
|
return package.base, PkgbuildPatch(None, patch)
|
|
|
|
@staticmethod
|
|
def patch_create_from_function(variable: str, patch_path: Optional[Path]) -> PkgbuildPatch:
|
|
"""
|
|
create single-function patch set for the package base
|
|
|
|
Args:
|
|
variable(str): function or variable name inside PKGBUILD
|
|
patch_path(Path): 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:
|
|
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")
|
|
patch = patch.strip() # remove spaces around the patch
|
|
return PkgbuildPatch(variable, patch)
|
|
|
|
@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.database.patches_insert(package_base, patch)
|
|
|
|
@staticmethod
|
|
def patch_set_list(application: Application, package_base: Optional[str], variables: List[str],
|
|
exit_code: bool) -> None:
|
|
"""
|
|
list patches available for the package base
|
|
|
|
Args:
|
|
application(Application): application instance
|
|
package_base(Optional[str]): package base
|
|
variables(List[str]): extract patches only for specified PKGBUILD variables
|
|
exit_code(bool): exit with error on empty search result
|
|
"""
|
|
patches = application.database.patches_list(package_base, variables)
|
|
Patch.check_if_empty(exit_code, not patches)
|
|
|
|
for base, patch in patches.items():
|
|
PatchPrinter(base, patch).print(verbose=True, separator=" = ")
|
|
|
|
@staticmethod
|
|
def patch_set_remove(application: Application, package_base: str, variables: List[str]) -> None:
|
|
"""
|
|
remove patch set for the package base
|
|
|
|
Args:
|
|
application(Application): application instance
|
|
package_base(str): package base
|
|
variables(List[str]): remove patches only for specified PKGBUILD variables
|
|
"""
|
|
application.database.patches_remove(package_base, variables)
|