aboutsummaryrefslogtreecommitdiffstats
path: root/build-aux/git-hooks/commit-msg-files.awk
diff options
context:
space:
mode:
authorVibhav Pant2023-06-06 19:30:27 +0530
committerVibhav Pant2023-06-06 19:30:27 +0530
commit49ffcbf86a32a8a217538d4df3736fe069ccf35d (patch)
treea5f16157cc20fb19a844473a6fbd2b434f4c8260 /build-aux/git-hooks/commit-msg-files.awk
parentaf569fa3d90a717983b743eb97adbf869c6d1736 (diff)
parent7ca1d782f5910d0c3978c6798a45c6854ec668c7 (diff)
downloademacs-49ffcbf86a32a8a217538d4df3736fe069ccf35d.tar.gz
emacs-49ffcbf86a32a8a217538d4df3736fe069ccf35d.zip
Merge branch 'master' into scratch/comp-static-data
Diffstat (limited to 'build-aux/git-hooks/commit-msg-files.awk')
-rw-r--r--build-aux/git-hooks/commit-msg-files.awk128
1 files changed, 128 insertions, 0 deletions
diff --git a/build-aux/git-hooks/commit-msg-files.awk b/build-aux/git-hooks/commit-msg-files.awk
new file mode 100644
index 00000000000..5c9b70a5de5
--- /dev/null
+++ b/build-aux/git-hooks/commit-msg-files.awk
@@ -0,0 +1,128 @@
1# Check the file list of GNU Emacs change log entries for each commit SHA.
2
3# Copyright 2023 Free Software Foundation, Inc.
4
5# This file is part of GNU Emacs.
6
7# GNU Emacs is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11
12# GNU Emacs is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16
17# You should have received a copy of the GNU General Public License
18# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20### Commentary:
21
22# This script accepts a list of (unabbreviated) Git commit SHAs, and
23# will then iterate over them to check that any files mentioned in the
24# commit message are actually present in the commit's diff. If not,
25# it will print out the incorrect file names and return 1.
26
27# You can also pass "-v reason=pre-push", which will add more-verbose
28# output, indicating the abbreviated commit SHA and first line of the
29# commit message for any improper commits.
30
31### Code:
32
33function get_commit_changes(commit_sha, changes, cmd, i, j, len, \
34 bits, filename) {
35 # Collect all the files touched in the specified commit.
36 cmd = ("git show --name-status --first-parent --format= " commit_sha)
37 while ((cmd | getline) > 0) {
38 for (i = 2; i <= NF; i++) {
39 len = split($i, bits, "/")
40 for (j = 1; j <= len; j++) {
41 if (j == 1)
42 filename = bits[j]
43 else
44 filename = filename "/" bits[j]
45 changes[filename] = 1
46 }
47 }
48 }
49 close(cmd)
50}
51
52function check_commit_msg_files(commit_sha, verbose, changes, good, \
53 cmd, msg, filenames_str, filenames, i) {
54 get_commit_changes(commit_sha, changes)
55 good = 1
56
57 cmd = ("git log -1 --format=%B " commit_sha)
58 while ((cmd | getline) > 0) {
59 if (verbose && ! msg)
60 msg = $0
61
62 # Find file entries in the commit message. We look at any line
63 # starting with "*" (possibly prefixed by "; ") followed by a ":",
64 # possibly on a different line. If we encounter a blank line
65 # without seeing a ":", then we don't treat that as a file entry.
66
67 # Accumulate the contents of a (possible) file entry.
68 if (/^[ \t]*$/)
69 filenames_str = ""
70 else if (/^(; )?\*[ \t]+[[:alnum:]]/)
71 filenames_str = $0
72 else if (filenames_str)
73 filenames_str = (filenames_str $0)
74
75 # We have a file entry; analyze it.
76 if (filenames_str && /:/) {
77 # Delete the leading "*" and any trailing information.
78 sub(/^(; )?\*[ \t]+/, "", filenames_str)
79 sub(/[ \t]*[[(<:].*$/, "", filenames_str)
80
81 # There might be multiple files listed in this entry, separated
82 # by spaces (and possibly a comma). Iterate over each of them.
83 split(filenames_str, filenames, ",[ \t]+")
84 for (i in filenames) {
85 # Remove trailing slashes from any directory entries.
86 sub(/\/$/, "", filenames[i])
87
88 if (length(filenames[i]) && ! (filenames[i] in changes)) {
89 if (good) {
90 # Print a header describing the error.
91 if (verbose)
92 printf("In commit %s \"%s\"...\n", substr(commit_sha, 1, 10), msg)
93 printf("Files listed in commit message, but not in diff:\n")
94 }
95 printf(" %s\n", filenames[i])
96 good = 0
97 }
98 }
99
100 filenames_str = ""
101 }
102 }
103 close(cmd)
104
105 return good
106}
107
108BEGIN {
109 if (reason == "pre-push")
110 verbose = 1
111}
112
113/^[a-z0-9]{40}$/ {
114 if (! check_commit_msg_files($0, verbose)) {
115 status = 1
116 }
117}
118
119END {
120 if (status != 0) {
121 if (reason == "pre-push")
122 error_msg = "Push aborted"
123 else
124 error_msg = "Bad commit message"
125 printf("%s; please see the file 'CONTRIBUTE'\n", error_msg)
126 }
127 exit status
128}