Skip to content

Instantly share code, notes, and snippets.

@lmgarret
Last active July 6, 2021 07:33
Show Gist options
  • Save lmgarret/731dff72578c9b2804d130d6ec082906 to your computer and use it in GitHub Desktop.
Save lmgarret/731dff72578c9b2804d130d6ec082906 to your computer and use it in GitHub Desktop.
prepare-commit-msg
#!/usr/bin/env python3
"""
Git hook to automatically insert in a git commit message an issue number
(e.g. Jira ticket number) from the current branch name.
"""
import itertools
import logging
import re
import sys
from subprocess import check_output
from typing import ClassVar, List, Optional, Pattern
logger: logging.Logger = logging.getLogger(__name__)
class CommitMessage:
_regex: ClassVar[Pattern] = re.compile(
r"^(?P<leading_comments>(?:\s*#.*\n|\s*\n)*)(?P<title_prefix>\w+(?:\([^()\r\n]*\)|\()?!?):\s*(?P<title_subject>.*)?(?P<trailing_lines>(?:\n.*)*)$"
)
_file_path: str
leading_comments: str
title_prefix: str
title_subject: str
trailing_lines: str
def __init__(self, commit_file_path: str):
self._file_path = commit_msg_filepath
with open(commit_msg_filepath, "r") as f:
commit_msg: str = f.read()
if match := re.match(CommitMessage._regex, commit_msg):
self.leading_comments = match.groupdict().get("leading_comments", "")
self.title_prefix = match.groupdict().get("title_prefix", "")
self.title_subject = match.groupdict().get("title_subject", "")
self.trailing_lines = match.groupdict().get("trailing_lines", "")
else:
raise ValueError(f"Invalid commit message at {commit_file_path}")
def to_jira_commit(self, ticket_nb: str) -> str:
return f"{self.leading_comments}{self.title_prefix}: {ticket_nb} {self.title_subject}{self.trailing_lines}"
def update_file(self, ticket_nb: str):
with open(self._file_path, "w") as f:
f.seek(0, 0) # correctly positions issue_number when writing commit message
f.write(self.to_jira_commit(ticket_nb))
commit_msg_filepath = sys.argv[1]
commit_src = sys.argv[2]
if commit_src != "message":
logger.warning(
f'Unsupported commit source: "{commit_src}", failing silently without editing commit message.'
)
sys.exit(0) # not a big fan of this..
try:
branch = (
check_output(["git", "symbolic-ref", "--short", "HEAD"]).decode("utf-8").strip()
)
except:
logger.warning(
"Could not read branch name, failing silently without editing commit message."
)
sys.exit(0) # not a big fan of this..
else:
if branch_match := re.match(r"^(\w+)\/((?:\w+-|#)\d+)\/.*$", branch):
issue_number = branch_match.group(2)
commit_msg: CommitMessage = CommitMessage(commit_msg_filepath)
commit_msg.update_file(issue_number)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment