aboutsummaryrefslogtreecommitdiffstats
path: root/build-aux
diff options
context:
space:
mode:
authorPo Lu2023-04-22 09:21:25 +0800
committerPo Lu2023-04-22 09:21:25 +0800
commit74fd40c030bace1e84a65be30f50a2d7e0f29596 (patch)
tree19ebeb75776d29b91856e5e4dc779b33db929c85 /build-aux
parented2f8c660bf501726e687552b56911283d637271 (diff)
parent4f3dae2b0d5fc43e5e2effa6d36544b6de2a43d8 (diff)
downloademacs-74fd40c030bace1e84a65be30f50a2d7e0f29596.tar.gz
emacs-74fd40c030bace1e84a65be30f50a2d7e0f29596.zip
Merge remote-tracking branch 'origin/master' into feature/android
Diffstat (limited to 'build-aux')
-rw-r--r--build-aux/git-hooks/commit-msg-files.awk113
-rwxr-xr-xbuild-aux/git-hooks/post-commit45
-rwxr-xr-xbuild-aux/git-hooks/pre-push83
3 files changed, 241 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..3856e474d3e
--- /dev/null
+++ b/build-aux/git-hooks/commit-msg-files.awk
@@ -0,0 +1,113 @@
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 log -1 --name-status --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 lines that reference files. We look at any line starting
63 # with "*" (possibly prefixed by "; ") where the file part starts
64 # with an alphanumeric character. The file part ends if we
65 # encounter any of the following characters: [ ( < { :
66 if (/^(; )?\*[ \t]+[[:alnum:]]/ && match($0, /[[:alnum:]][^[(<{:]*/)) {
67 # There might be multiple files listed on this line, separated
68 # by spaces (and possibly a comma). Iterate over each of them.
69 split(substr($0, RSTART, RLENGTH), filenames, ",?([[:blank:]]+|$)")
70
71 for (i in filenames) {
72 # Remove trailing slashes from any directory entries.
73 sub(/\/$/, "", filenames[i])
74
75 if (length(filenames[i]) && ! (filenames[i] in changes)) {
76 if (good) {
77 # Print a header describing the error.
78 if (verbose)
79 printf("In commit %s \"%s\"...\n", substr(commit_sha, 1, 10), msg)
80 printf("Files listed in commit message, but not in diff:\n")
81 }
82 printf(" %s\n", filenames[i])
83 good = 0
84 }
85 }
86 }
87 }
88 close(cmd)
89
90 return good
91}
92
93BEGIN {
94 if (reason == "pre-push")
95 verbose = 1
96}
97
98/^[a-z0-9]{40}$/ {
99 if (! check_commit_msg_files($0, verbose)) {
100 status = 1
101 }
102}
103
104END {
105 if (status != 0) {
106 if (reason == "pre-push")
107 error_msg = "Push aborted"
108 else
109 error_msg = "Bad commit message"
110 printf("%s; please see the file 'CONTRIBUTE'\n", error_msg)
111 }
112 exit status
113}
diff --git a/build-aux/git-hooks/post-commit b/build-aux/git-hooks/post-commit
new file mode 100755
index 00000000000..68d9995d915
--- /dev/null
+++ b/build-aux/git-hooks/post-commit
@@ -0,0 +1,45 @@
1#!/bin/sh
2# Check the file list of GNU Emacs change log entries after committing.
3
4# Copyright 2023 Free Software Foundation, Inc.
5
6# This file is part of GNU Emacs.
7
8# GNU Emacs is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12
13# GNU Emacs is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17
18# You should have received a copy of the GNU General Public License
19# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
20
21### Commentary:
22
23# This hook runs after a commit is finalized and checks that the files
24# mentioned in the commit message match the diff. We perform this in
25# the post-commit phase so that we can be sure we properly detect all
26# the files in the diff (this is difficult during the commit-msg hook,
27# since there's no cross-platform way to detect when a commit is being
28# amended).
29
30# However, since this is a post-commit hook, it's too late to error
31# out and abort the commit: it's already done! As a result, this hook
32# is purely advisory, and instead we error out when trying to push
33# (see "pre-push" in this directory).
34
35### Code:
36
37# Prefer gawk if available, as it handles NUL bytes properly.
38if type gawk >/dev/null 2>&1; then
39 awk="gawk"
40else
41 awk="awk"
42fi
43
44git rev-parse HEAD | $awk -v reason=post-commit \
45 -f .git/hooks/commit-msg-files.awk
diff --git a/build-aux/git-hooks/pre-push b/build-aux/git-hooks/pre-push
new file mode 100755
index 00000000000..adcf27d4a5d
--- /dev/null
+++ b/build-aux/git-hooks/pre-push
@@ -0,0 +1,83 @@
1#!/bin/sh
2# Check the file list of GNU Emacs change log entries before pushing.
3
4# Copyright 2023 Free Software Foundation, Inc.
5
6# This file is part of GNU Emacs.
7
8# GNU Emacs is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12
13# GNU Emacs is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17
18# You should have received a copy of the GNU General Public License
19# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
20
21### Commentary:
22
23# This hook runs before pushing a series of commits and checks that
24# the files mentioned in each commit message match the diffs. This
25# helps ensure that the resulting change logs are correct, which
26# should prevent errors when generating etc/AUTHORS.
27
28# These checks also happen in the "post-commit" hook (which see), but
29# that hook can't abort a commit; it just advises the committer to fix
30# the commit so that this hook runs without errors.
31
32### Code:
33
34# Prefer gawk if available, as it handles NUL bytes properly.
35if type gawk >/dev/null 2>&1; then
36 awk="gawk"
37else
38 awk="awk"
39fi
40
41# Standard input receives lines of the form:
42# <local ref> SP <local name> SP <remote ref> SP <remote name> LF
43$awk -v origin_name="$1" '
44 # If the local SHA is all zeroes, ignore it.
45 $2 ~ /^0{40}$/ {
46 next
47 }
48
49 $2 ~ /^[a-z0-9]{40}$/ {
50 newref = $2
51 # If the remote SHA is all zeroes, this is a new object to be
52 # pushed (likely a branch). Go backwards until we find a SHA on
53 # an origin branch.
54 if ($4 ~ /^0{40}$/) {
55 back = 0
56 cmd = ("git branch -r -l '\''" origin_name "/*'\'' --contains " \
57 newref "~" back)
58 while ((cmd | getline) == 0) {
59
60 # Only look back at most 1000 commits, just in case...
61 if (back++ > 1000)
62 break;
63 }
64 close(cmd)
65
66 cmd = ("git rev-parse " newref "~" back)
67 cmd | getline oldref
68 if (!(oldref ~ /^[a-z0-9]{40}$/)) {
69 # The SHA is misformatted! Skip this line.
70 next
71 }
72 close(cmd)
73 } else if ($4 ~ /^[a-z0-9]{40}$/) {
74 oldref = $4
75 } else {
76 # The SHA is misformatted! Skip this line.
77 next
78 }
79
80 # Print every SHA after oldref, up to (and including) newref.
81 system("git rev-list --reverse " oldref ".." newref)
82 }
83' | $awk -v reason=pre-push -f .git/hooks/commit-msg-files.awk