-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathkw-commit-msg.py
More file actions
executable file
·153 lines (133 loc) · 4.95 KB
/
kw-commit-msg.py
File metadata and controls
executable file
·153 lines (133 loc) · 4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env python3
# ==========================================================================
#
# Copyright NumFOCUS
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0.txt
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# ==========================================================================
import os
import re
import subprocess
import sys
from pathlib import Path
DEFAULT_LINE_LENGTH: int = 78
def die(message, commit_msg_path):
print("commit-msg hook failure", file=sys.stderr)
print("-----------------------", file=sys.stderr)
print(message, file=sys.stderr)
print("-----------------------", file=sys.stderr)
print(
f"""
To continue editing, run the command
git commit -e -F "{commit_msg_path}"
(assuming your working directory is at the top).""",
file=sys.stderr,
)
sys.exit(1)
def get_max_length():
try:
result = subprocess.run(
["git", "config", "--get", "hooks.commit-msg.ITKCommitSubjectMaxLength"],
capture_output=True,
text=True,
check=True,
)
return int(result.stdout.strip())
except (subprocess.CalledProcessError, ValueError):
return DEFAULT_LINE_LENGTH
def main():
git_dir_path: Path = Path(os.environ.get("GIT_DIR", ".git")).resolve()
commit_msg_path: Path = git_dir_path / "COMMIT_MSG"
if len(sys.argv) < 2:
die(f"Usage: {sys.argv[0]} <git_commit_message_file>", commit_msg_path)
input_file: Path = Path(sys.argv[1])
if not input_file.exists():
die(
f"Missing input_file {sys.argv[1]} for {sys.argv[0]} processing",
commit_msg_path,
)
max_subjectline_length: int = get_max_length()
original_input_file_lines: list[str] = []
with open(input_file) as f_in:
original_input_file_lines = f_in.readlines()
input_file_lines: list[str] = []
for test_line in original_input_file_lines:
test_line = test_line.strip()
is_empty_line_before_subject: bool = (
len(input_file_lines) == 0 and len(test_line) == 0
)
if test_line.startswith("#") or is_empty_line_before_subject:
continue
input_file_lines.append(f"{test_line}\n")
with open(commit_msg_path, "w") as f_out:
f_out.writelines(input_file_lines)
subject_line: str = input_file_lines[0]
if len(subject_line) < 8:
die(
f"The first line must be at least 8 characters:\n--------\n{subject_line}\n--------",
commit_msg_path,
)
if (
len(subject_line) > max_subjectline_length
and not subject_line.startswith("Merge ")
and not subject_line.startswith("Revert ")
):
die(
f"The first line may be at most {max_subjectline_length} characters:\n"
+ "-" * max_subjectline_length
+ f"\n{subject_line}\n"
+ "-" * max_subjectline_length,
commit_msg_path,
)
if re.match(r"^[ \t]|[ \t]$", subject_line):
die(
f"The first line may not have leading or trailing space:\n[{subject_line}]",
commit_msg_path,
)
if not re.match(
r"^(Merge|Revert|BUG:|COMP:|DOC:|ENH:|PERF:|STYLE:|WIP:)\s", subject_line
):
die(
f"""Start ITK commit messages with a standard prefix (and a space):
BUG: - fix for runtime crash or incorrect result
COMP: - compiler error or warning fix
DOC: - documentation change
ENH: - new functionality
PERF: - performance improvement
STYLE: - no logic impact (indentation, comments)
WIP: - Work In Progress not ready for merge
To reference GitHub issue XXXX, add "Issue #XXXX" to the commit message.
If the issue addresses an open issue, add "Closes #XXXX" to the message.""",
commit_msg_path,
)
if re.match(r"^BUG: [0-9]+\.", subject_line):
die(
f'Do not put a "." after the bug number:\n\n {subject_line}',
commit_msg_path,
)
del subject_line
if len(input_file_lines) > 1:
second_line: str = input_file_lines[
1
].strip() # Remove whitespace at beginning and end
if len(second_line) == 0:
input_file_lines[1] = "\n" # Replace line with only newline
else:
die(
f'The second line of the commit message must be empty:\n"{second_line}" with length {len(second_line)}',
commit_msg_path,
)
del second_line
if __name__ == "__main__":
main()