diff options
| author | Loek Le Blansch <loek@pipeframe.xyz> | 2025-10-26 16:31:48 +0100 |
|---|---|---|
| committer | Loek Le Blansch <loek@pipeframe.xyz> | 2025-10-26 16:31:48 +0100 |
| commit | e78e1def6ff9255f9ab7f5e7875a18e99b1ab1fc (patch) | |
| tree | 8980ac88441c0db31b3e437dde28ccf1480e1ce6 | |
| parent | 0b7a11d7c9ad9288fcef9a0b26e81f129cc902d2 (diff) | |
add --shebang option
| -rw-r--r-- | patchtree/cli.py | 13 | ||||
| -rw-r--r-- | patchtree/config.py | 20 | ||||
| -rw-r--r-- | patchtree/context.py | 27 |
3 files changed, 50 insertions, 10 deletions
diff --git a/patchtree/cli.py b/patchtree/cli.py index 2535256..8e923dd 100644 --- a/patchtree/cli.py +++ b/patchtree/cli.py @@ -39,6 +39,12 @@ def parse_arguments(config: Config) -> Context: help="lines of context in output diff", type=int, ) + parser.add_argument( + "-s", + "--shebang", + help="output shebang in resulting patch", + action="store_true", + ) parser.add_argument("target", help="target directory or archive") parser.add_argument("patch", help="patch input glob(s)", nargs="+") @@ -47,8 +53,11 @@ def parse_arguments(config: Config) -> Context: if options.context is not None: config.diff_context = options.context + if options.shebang: + config.output_shebang = True + try: - return config.context(options) + return config.context(config, options) except Exception as e: parser.error(str(e)) @@ -70,7 +79,7 @@ def main(): print("no files to patch!", file=stderr) return 0 - config.header(context) + config.header(config, context) for file in files: patch = config.patch(config, file) diff --git a/patchtree/config.py b/patchtree/config.py index 743307b..196ecb1 100644 --- a/patchtree/config.py +++ b/patchtree/config.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from dataclasses import dataclass, field from argparse import ArgumentParser from importlib import metadata @@ -21,17 +23,32 @@ DEFAULT_DIFFS: dict[str, type[Diff]] = { class Header: + config: Config context: Context + name = "patchtree" license = None - def __init__(self, context: Context): + def __init__(self, config: Config, context: Context): + self.config = config self.context = context + self.write_shebang() self.write_version() self.write_version_extra() self.write_license() + def write_shebang(self): + if not self.config.output_shebang: + return + cmd = [ + "/usr/bin/env", + "-S", + *self.context.get_apply_cmd(), + ] + cmdline = " ".join(cmd) + self.context.output.write(f"#!{cmdline}\n") + def write_version(self): version = metadata.version("patchtree") self.context.output.write(f"{self.name} output (version {version})\n") @@ -59,6 +76,7 @@ class Config: ) header: type[Header] = Header diff_context: int = 3 + output_shebang: bool = False def __post_init__(self): self.processors = {**DEFAULT_PROCESSORS, **self.processors} diff --git a/patchtree/context.py b/patchtree/context.py index 554d09e..0ff769a 100644 --- a/patchtree/context.py +++ b/patchtree/context.py @@ -1,5 +1,7 @@ +from __future__ import annotations +from typing import TYPE_CHECKING, IO, cast + from argparse import Namespace -from typing import IO, cast from pathlib import Path from zipfile import ZipInfo, is_zipfile from tempfile import TemporaryFile @@ -9,6 +11,9 @@ from subprocess import run from zipfile import ZipFile from stat import S_IFDIR, S_IFREG +if TYPE_CHECKING: + from .config import Config + ZIP_CREATE_SYSTEM_UNX = 3 @@ -107,10 +112,14 @@ class ZipFS(FS): class Context: fs: FS output: IO + + config: Config options: Namespace - def __init__(self, options: Namespace): + def __init__(self, config: Config, options: Namespace): + self.config = config self.options = options + self.fs = self.get_fs() self.output = self.get_output() @@ -166,16 +175,20 @@ class Context: return stdout - def apply(self, reverse: bool) -> None: - location = cast(DiskFS, self.fs).path - cache = location.joinpath(".patchtree.diff") - + def get_apply_cmd(self) -> list[str]: cmd = [ "git", "apply", - "--unidiff-zero", "--allow-empty", ] + if self.config.diff_context == 0: + cmd.append("--unidiff-zero") + return cmd + + def apply(self, reverse: bool) -> None: + location = cast(DiskFS, self.fs).path + cache = location.joinpath(".patchtree.diff") + cmd = self.get_apply_cmd() if reverse: if not cache.exists(): |