Skip to content

Commit 3e35af1

Browse files
committed
feat: git hook runner
1 parent e0d326b commit 3e35af1

File tree

4 files changed

+147
-45
lines changed

4 files changed

+147
-45
lines changed

.git-hooks/commit-msg

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,4 @@
11
#!/usr/bin/env sh
22

3-
# From Gerrit Code Review 3.1.3, with some modifications
4-
5-
if test "$#" != 1; then
6-
echo "$0 requires an argument."
7-
exit 1
8-
fi
9-
if test ! -f "$1"; then
10-
echo "file does not exist: $1"
11-
exit 1
12-
fi
13-
# Create a change id only if requested
14-
if test ! "true" = "$(git config --bool --get gerrit.createChangeId)"; then
15-
exit 0
16-
fi
17-
# $RANDOM will be undefined if not using bash, so don't use set -u
18-
random=$( (
19-
whoami
20-
hostname
21-
date
22-
cat "$1"
23-
) | git hash-object --stdin)
24-
dest="$1.tmp.${random}"
25-
trap 'rm -f "${dest}"' EXIT
26-
if ! git stripspace --strip-comments <"$1" >"${dest}"; then
27-
echo "cannot strip comments from $1"
28-
exit 1
29-
fi
30-
if test ! -s "${dest}"; then
31-
echo "file is empty: $1"
32-
exit 1
33-
fi
34-
# Avoid the --in-place option which only appeared in Git 2.8
35-
# Avoid the --if-exists option which only appeared in Git 2.15
36-
if ! git -c trailer.ifexists=doNothing interpret-trailers \
37-
--trailer "Change-Id: I${random}" <"$1" >"${dest}"; then
38-
echo "cannot insert change-id line in $1"
39-
exit 1
40-
fi
41-
if ! mv "${dest}" "$1"; then
42-
echo "cannot mv ${dest} to $1"
43-
exit 1
44-
fi
3+
script_dir="$(dirname "$0")"
4+
"${script_dir}/git-hook-runner.sh" "commit-msg" "$@"
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#!/bin/sh
2+
3+
# From Gerrit Code Review 3.13.0-rc3-374-g42b0eb075c
4+
#
5+
# Part of Gerrit Code Review (https://www.gerritcodereview.com/)
6+
#
7+
# Copyright (C) 2009 The Android Open Source Project
8+
#
9+
# Licensed under the Apache License, Version 2.0 (the "License");
10+
# you may not use this file except in compliance with the License.
11+
# You may obtain a copy of the License at
12+
#
13+
# http://www.apache.org/licenses/LICENSE-2.0
14+
#
15+
# Unless required by applicable law or agreed to in writing, software
16+
# distributed under the License is distributed on an "AS IS" BASIS,
17+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
# See the License for the specific language governing permissions and
19+
# limitations under the License.
20+
21+
set -u
22+
23+
# avoid [[ which is not POSIX sh.
24+
if test "$#" != 1 ; then
25+
echo "$0 requires an argument."
26+
exit 1
27+
fi
28+
29+
if test ! -f "$1" ; then
30+
echo "file does not exist: $1"
31+
exit 1
32+
fi
33+
34+
# Do not create a change id if requested
35+
case "$(git config --get gerrit.createChangeId)" in
36+
false)
37+
exit 0
38+
;;
39+
always)
40+
;;
41+
*)
42+
# Do not create a change id for squash/fixup commits.
43+
if head -n1 "$1" | LC_ALL=C grep -q '^[a-z][a-z]*! '; then
44+
exit 0
45+
fi
46+
;;
47+
esac
48+
49+
50+
if git rev-parse --verify HEAD >/dev/null 2>&1; then
51+
refhash="$(git rev-parse HEAD)"
52+
else
53+
refhash="$(git hash-object -t tree /dev/null)"
54+
fi
55+
56+
random=$({ git var GIT_COMMITTER_IDENT ; echo "$refhash" ; cat "$1"; } | git hash-object --stdin)
57+
dest="$1.tmp.${random}"
58+
59+
trap 'rm -f "$dest" "$dest-2"' EXIT
60+
61+
if ! sed -e '/>8/q' "$1" | git stripspace --strip-comments > "${dest}" ; then
62+
echo "cannot strip comments from $1"
63+
exit 1
64+
fi
65+
66+
if test ! -s "${dest}" ; then
67+
echo "file is empty: $1"
68+
exit 1
69+
fi
70+
71+
reviewurl="$(git config --get gerrit.reviewUrl)"
72+
if test -n "${reviewurl}" ; then
73+
token="Link"
74+
value="${reviewurl%/}/id/I$random"
75+
pattern=".*/id/I[0-9a-f]\{40\}"
76+
else
77+
token="Change-Id"
78+
value="I$random"
79+
pattern=".*"
80+
fi
81+
82+
if git interpret-trailers --no-divider --parse < "$1" | grep -q "^$token: $pattern$" ; then
83+
exit 0
84+
fi
85+
86+
# There must be a Signed-off-by trailer for the code below to work. Insert a
87+
# sentinel at the end to make sure there is one.
88+
# Avoid the --in-place option which only appeared in Git 2.8
89+
if ! git interpret-trailers \
90+
--no-divider \
91+
--trailer "Signed-off-by: SENTINEL" < "$1" > "$dest-2" ; then
92+
echo "cannot insert Signed-off-by sentinel line in $1"
93+
exit 1
94+
fi
95+
96+
# Make sure the trailer appears before any Signed-off-by trailers by inserting
97+
# it as if it was a Signed-off-by trailer and then use sed to remove the
98+
# Signed-off-by prefix and the Signed-off-by sentinel line.
99+
# Avoid the --in-place option which only appeared in Git 2.8
100+
# Avoid the --where option which only appeared in Git 2.15
101+
if ! git -c trailer.where=before interpret-trailers \
102+
--no-divider \
103+
--trailer "Signed-off-by: $token: $value" < "$dest-2" |
104+
sed -e "s/^Signed-off-by: \($token: \)/\1/" \
105+
-e "/^Signed-off-by: SENTINEL/d" > "$dest" ; then
106+
echo "cannot insert $token line in $1"
107+
exit 1
108+
fi
109+
110+
if ! mv "${dest}" "$1" ; then
111+
echo "cannot mv ${dest} to $1"
112+
exit 1
113+
fi

.git-hooks/git-hook-runner.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/sh
2+
3+
hook_type="$1"
4+
shift
5+
6+
script_dir="$(dirname "$0")"
7+
hooks_d_dir="${script_dir}/${hook_type}.d"
8+
9+
if [ -d "$hooks_d_dir" ]; then
10+
for hook_script in "$hooks_d_dir"/*; do
11+
if [ -f "$hook_script" ] && [ -x "$hook_script" ]; then
12+
"$hook_script" "$@"
13+
exit_code=$?
14+
if [ $exit_code -ne 0 ]; then
15+
exit $exit_code
16+
fi
17+
fi
18+
done
19+
fi

README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,19 @@ shell they are applicable to. All the customizations are in the
5858

5959
### Git hooks
6060

61-
The dotfiles include the following Git hooks:
61+
The dotfiles include a the following Git hooks. For each Git hook type,
62+
`.git-hooks/git-hook-runner.sh` will run the hooks listed in the
63+
`.git-hooks/<Git hook name>.d` directory in alphabetic order.
6264

63-
- `commit-msg` that adds a `Change-Id` to the commit message, if necessary.
64-
Useful when working with Gerrit.
65+
- `commit-msg` hooks:
66+
67+
- `100-gerrit-commit-msg`: adds a `Change-Id` trailer to the commit message.
68+
Useful when working with Gerrit. This hook is disabled by default. Enable it
69+
by running:
70+
71+
```sh
72+
git config core.hooksPath .git/hooks
73+
```
6574

6675
## Thanks
6776

@@ -72,3 +81,4 @@ I used these dotfiles as inspiration and guidance:
7281
- [Mathias Bynens](https://github.com/mathiasbynens/dotfiles)
7382
- [Nicolas Gallagher](https://github.com/necolas/dotfiles)
7483
- [Peter Ward](https://blog.flowblok.id.au/2013-02/shell-startup-scripts.html)
84+
- [rmandvikar](https://github.com/rmandvikar/dotfiles)

0 commit comments

Comments
 (0)