From 5e7f722bd9ab953a4f14fa3401e50871e3d75cab Mon Sep 17 00:00:00 2001 From: lyuksovannyy Date: Sat, 19 Sep 2026 17:16:51 +0200 Subject: [PATCH] [nobump] Added plugin minor version auto-increment --- scripts/pre-commit | 135 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100755 scripts/pre-commit diff --git a/scripts/pre-commit b/scripts/pre-commit new file mode 100755 index 0000000..d22e087 --- /dev/null +++ b/scripts/pre-commit @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +import json +import re +import subprocess +import sys +from pathlib import Path + +REPO_ROOT = Path(subprocess.check_output(["git", "rev-parse", "--show-toplevel"], text=True).strip()) +PLUGIN_JSON_PATH = REPO_ROOT / "plugin.json" + +STOP_PATTERNS = [ + r"\[no[-_ ]?bump\]", + r"\[skip[-_ ]?bump\]", + r"\[no[-_ ]?version[-_ ]?bump\]", + r"\[skip[-_ ]?version\]", + r"\bno[-_ ]bump\b", + r"\bskip[-_ ]bump\b", + r"\bno[-_ ]version[-_ ]bump\b", +] + + +def increment_patch_version(version_str: str) -> str: + match = re.fullmatch(r"^(\d+)\.(\d+)\.(\d+)(.*)$", version_str.strip()) + if not match: + raise ValueError(f"Version '{version_str}' does not match x.y.z format") + major, minor, patch, suffix = match.groups() + new_patch = int(patch) + 1 + return f"{major}.{minor}.{new_patch}{suffix}" + + +def get_head_version() -> str | None: + res = subprocess.run( + ["git", "rev-parse", "--verify", "HEAD"], + cwd=REPO_ROOT, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + if res.returncode != 0: + return None + + show_res = subprocess.run( + ["git", "show", "HEAD:plugin.json"], + cwd=REPO_ROOT, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + text=True, + ) + if show_res.returncode != 0: + return None + + try: + head_data = json.loads(show_res.stdout) + return str(head_data.get("version")) if "version" in head_data else None + except json.JSONDecodeError: + return None + + +def should_skip_from_commit_msg() -> bool: + # 1. Check GIT_PARAMS / COMMIT_EDITMSG / MERGE_MSG + candidates = [ + REPO_ROOT / ".git" / "COMMIT_EDITMSG", + REPO_ROOT / ".git" / "MERGE_MSG", + ] + for p in candidates: + if p.exists(): + content = p.read_text(encoding="utf-8", errors="replace") + lines = [line for line in content.splitlines() if not line.strip().startswith("#")] + text = " ".join(lines) + for pattern in STOP_PATTERNS: + if re.search(pattern, text, re.IGNORECASE): + return True + + # 2. Check process command-line arguments (e.g. git commit -m "...") + try: + # On Linux, inspect parent process /proc cmdline + ppid = subprocess.check_output(["ps", "-o", "ppid=", "-p", str(Path("/proc/self").resolve().name)], text=True).strip() + cmdline_path = Path(f"/proc/{ppid}/cmdline") + if cmdline_path.exists(): + cmd_args = cmdline_path.read_bytes().decode("utf-8", errors="replace") + for pattern in STOP_PATTERNS: + if re.search(pattern, cmd_args, re.IGNORECASE): + return True + except Exception: + pass + + return False + + +def main() -> int: + # Don't auto-bump during merge/rebase in progress + if (REPO_ROOT / ".git" / "MERGE_HEAD").exists() or (REPO_ROOT / ".git" / "rebase-merge").exists(): + return 0 + + if should_skip_from_commit_msg(): + print("pre-commit: stop word detected in commit message, skipping version bump") + return 0 + + if not PLUGIN_JSON_PATH.exists(): + return 0 + + try: + data = json.loads(PLUGIN_JSON_PATH.read_text(encoding="utf-8")) + current_version = str(data.get("version", "")) + except Exception as e: + print(f"pre-commit: failed to parse {PLUGIN_JSON_PATH}: {e}", file=sys.stderr) + return 1 + + head_version = get_head_version() + + # Skip if version was manually changed (differs from HEAD) + if head_version is not None and current_version != head_version: + print( + f"pre-commit: version already modified ({head_version} -> {current_version}), skipping auto-increment" + ) + return 0 + + try: + new_version = increment_patch_version(current_version) + data["version"] = new_version + PLUGIN_JSON_PATH.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8") + except Exception as e: + print(f"pre-commit: failed to bump version in {PLUGIN_JSON_PATH}: {e}", file=sys.stderr) + return 1 + + res = subprocess.run(["git", "add", str(PLUGIN_JSON_PATH)], cwd=REPO_ROOT) + if res.returncode != 0: + print("pre-commit: failed to stage plugin.json", file=sys.stderr) + return res.returncode + + print(f"pre-commit: bumped version {current_version} -> {new_version}") + return 0 + + +if __name__ == "__main__": + sys.exit(main())