aboutsummaryrefslogtreecommitdiff
path: root/patchtree/header.py
diff options
context:
space:
mode:
Diffstat (limited to 'patchtree/header.py')
-rw-r--r--patchtree/header.py89
1 files changed, 89 insertions, 0 deletions
diff --git a/patchtree/header.py b/patchtree/header.py
new file mode 100644
index 0000000..d797ff0
--- /dev/null
+++ b/patchtree/header.py
@@ -0,0 +1,89 @@
+from __future__ import annotations
+from typing import TYPE_CHECKING
+
+from importlib import metadata
+import shlex
+
+if TYPE_CHECKING:
+ from .context import Context
+ from .config import Config
+
+
+class Header:
+ """
+ Patch output header generator.
+
+ The header is formatted as
+
+ #. shebang
+ #. patchtree version info
+ #. extra version info (empty by default)
+ #. license (empty by default)
+ """
+
+ config: Config
+ context: Context
+
+ name = "patchtree"
+ """Program name shown in version info."""
+
+ license = None
+ """License text (optional)."""
+
+ def __init__(self, config: Config, context: Context):
+ self.config = config
+ self.context = context
+
+ def write(self) -> str:
+ return "".join(
+ (
+ self.write_shebang(),
+ self.write_version(),
+ self.write_version_extra(),
+ self.write_license(),
+ )
+ )
+
+ def write_shebang(self) -> str:
+ """
+ Write a shebang line to apply the output patch unless the ``--no-shebang`` option was passed.
+ """
+
+ if self.config.no_shebang:
+ return ""
+
+ # NOTE: the GIT_DIR environment variable is set in order to allow users to apply the
+ # .patch file to a target tree already tracked using git (which may be under a
+ # different directory relative to the repository root, causing the patch to be skipped
+ # silently). This effectively makes git-apply always behave as if it is outside a git
+ # tree, while still applying changes described using the extended git diff format.
+ cmd = ["/usr/bin/env", "-S", "GIT_DIR="]
+ cmd.append(shlex.join(self.context.get_apply_cmd()))
+ cmdline = " ".join(cmd)
+ return f"#!{cmdline}\n"
+
+ def write_version(self) -> str:
+ """
+ Write the patchtree name and version number.
+ """
+
+ version = metadata.version("patchtree")
+ return f"{self.name} output (version {version})\n"
+
+ def write_version_extra(self) -> str:
+ """
+ Write extra version information (empty).
+
+ This method is meant to be implemented by subclasses of Header defined in the :ref:`configuration file <ptconfig>`.
+ """
+
+ return ""
+
+ def write_license(self) -> str:
+ """
+ Write a license if it is defined.
+ """
+
+ if self.license is None:
+ return ""
+ return f"{self.license}\n"