Skip to content

Commit b8c336f

Browse files
committed
Make git hooks more robust
Fixes #202
1 parent 1e97ee5 commit b8c336f

File tree

4 files changed

+174
-101
lines changed

4 files changed

+174
-101
lines changed

developer-scripts/git-hooks/commit-msg

Lines changed: 52 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,52 @@
11
#!/bin/bash
22
#
3-
# An example hook script to check the commit log message.
3+
# A hook script to check the commit log message.
44
# Called by "git commit" with one argument, the name of the file
55
# that has the commit message. The hook should exit with non-zero
66
# status after issuing an appropriate message if it wants to stop the
77
# commit. The hook is allowed to edit the commit message file.
88
#
9-
# To enable this hook, rename this file to "commit-msg".
9+
# This hook is inteded to be used by OpenCoarrays developers to ensure
10+
# that they conform to project standards.
1011

11-
# Uncomment the below to add a Signed-off-by line to the message.
12-
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
13-
# hook is more suited to it.
14-
#
15-
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
16-
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
12+
13+
14+
set -o errexit
15+
set -o pipefail
16+
set -o nounset
17+
set -o errtrace
18+
19+
__file=commit-msg
20+
21+
err_report() {
22+
error_code=$?
23+
echo 2>&1 "Error in $__file in function $1 on line $2"
24+
exit $error_code
25+
}
26+
27+
trap 'err_report "${FUNCNAME:-.}" $LINENO' ERR
1728

1829
# error message function for writing good commit messages
30+
# shellcheck disable=SC2006,SC2035
1931
error_message () {
20-
cat <<\EOF >&2
32+
cat <<-EOF
2133
Error: bad commit message format. A copy of your commit message is in:
22-
`.git/COMMIT_EDITMSG`. Please fix it or write a new one according to the
34+
'.git/COMMIT_EDITMSG'. Please fix it or write a new one according to the
2335
guidlines below.
2436
2537
The first line of a commit message should start with a capitalized imperative
2638
verb used in a phrase to summarize the change. This first line must be less
2739
than 50 characters, followed by an additional blank line. Further detials are
2840
added after these first two lines, and may be up to 72 characters in length.
2941
30-
This is so that `--oneline` formatted `git log`s will contain human readable,
42+
This is so that '--oneline' formatted 'git log's will contain human readable,
3143
meaningful information, and the summaries on Github.com will also contain
3244
this concise summary. The 72 line limit is to ensure propper formatting on
3345
all terminals.
3446
3547
Here is an example of a good commit message:
3648
37-
```
49+
"""
3850
Redirect user to the requested page after login
3951
4052
https://github.com/sourceryinstitute/opencoarrays/Issues/29
@@ -46,11 +58,11 @@ being redirected to the login form.
4658
* Store requested path in a session variable
4759
* Redirect to the stored location after successfully logging in the user
4860
* Fixes #1
49-
```
61+
"""
5062
5163
As opposed to doing something bad like this:
5264
53-
`git commit -m "Fix login bug"`
65+
'git commit -m "Fix login bug"'
5466
5567
For more information on writting good commit messages,
5668
and keeping a clean history, please see:
@@ -65,50 +77,41 @@ EOF
6577

6678
}
6779

68-
let status=0
69-
70-
# This example catches duplicate Signed-off-by lines.
71-
72-
test "" = "$(grep '^Signed-off-by: ' "$1" |
73-
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
74-
echo >&2 "Duplicate Signed-off-by lines."
75-
let status=1
76-
}
80+
status=0
7781

7882
# Check that the first line of the commit starts with a
7983
# capitalized letter.
80-
if ! (head -n 1 $1 | grep '^[A-Z]' &>/dev/null ); then
84+
if ! (head -n 1 "$1" | grep '^[A-Z]' &>/dev/null ); then
8185
echo >&2 "First word of commit message must be a capitalized imperative verb."
8286
echo ""
83-
let status=1
87+
status=1
8488
fi
8589

8690
# Check each line for propper length
8791
ln=0
88-
cat $1 | \
89-
while read line; do
90-
let ln+=1
91-
nchars=$(wc -c <<<$line)
92-
if [[ "$ln" -eq "1" ]]; then
93-
if [[ "$nchars" -gt "51" ]]; then
94-
echo >&2 "First line of commit message too long ($nchars > 50 chars)"
95-
echo ""
96-
let status=1
97-
fi
98-
elif [[ "$ln" -eq "2" ]]; then
99-
if [[ "$nchars" -gt "1" ]] && ! grep '^#' <<<"$line" >/dev/null; then
100-
echo >&2 "Second line of commit message not blank"
101-
echo ""
102-
let status=1
103-
fi
104-
else
105-
if [[ "$nchars" -gt "72" ]]; then
106-
echo >&2 "Line $ln of commit message too long ($nchars > 72 chars)"
107-
echo ""
108-
let status=1
109-
fi
110-
fi
111-
done
92+
while read -r line; do
93+
ln+=1
94+
nchars=$(wc -c <<<"$line")
95+
if [[ "$ln" -eq "1" ]]; then
96+
if [[ "$nchars" -gt "51" ]]; then
97+
echo >&2 "First line of commit message too long ($nchars > 50 chars)"
98+
echo ""
99+
status=1
100+
fi
101+
elif [[ "$ln" -eq "2" ]]; then
102+
if [[ "$nchars" -gt "1" ]] && ! grep '^#' <<<"$line" >/dev/null; then
103+
echo >&2 "Second line of commit message not blank"
104+
echo ""
105+
status=1
106+
fi
107+
else
108+
if [[ "$nchars" -gt "72" ]]; then
109+
echo >&2 "Line $ln of commit message too long ($nchars > 72 chars)"
110+
echo ""
111+
status=1
112+
fi
113+
fi
114+
done < "$1"
112115

113116
if [[ $status = 0 ]]; then
114117
exit 0
Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,109 @@
11
#!/bin/bash
22
#
3-
# An example hook script to verify what is about to be committed.
3+
# Git pre-commit hook script to verify what is about to be committed.
44
# Called by "git commit" with no arguments. The hook should
55
# exit with non-zero status after issuing an appropriate message if
66
# it wants to stop the commit.
77
#
8-
# To enable this hook, rename this file to "pre-commit".
8+
# Checks performed by this script include:
9+
#
10+
# 1. Verifying that all text-based files end in a single new line character (appropriate for the given OS)
11+
# 2. No spurious, extra blank lines are at the end of a file textfile
12+
# 3. No files with non-ascii names are added to the git repo unless explicitly enabled in the git-config
13+
# 4. All files being committed conform to the git-config whitespace policy
14+
15+
set -o errexit
16+
set -o pipefail
17+
set -o nounset
18+
set -o errtrace
19+
20+
__file=pre-commit
21+
22+
err_report() {
23+
error_code=$?
24+
echo 2>&1 "Error in $__file in function $1 on line $2"
25+
exit $error_code
26+
}
27+
28+
trap 'err_report "${FUNCNAME:-.}" $LINENO' ERR
929

1030
function ends_with_newline() {
11-
test ! -s "$1" || test $(tail -r -c1 "$1" | xxd -ps) = "0a"
31+
[[ ! -s "$1" ]] || [[ "$(tail -c1 "$1" | xxd -ps)" = "0a" ]]
1232
}
1333

1434
function ends_with_single_new_line () {
15-
tail -2 "$1" | ( read x && read y && ! grep '^[[:blank:]]\+$' <<<$x >/dev/null)
35+
ends_with_newline "$1" && tail -1 "$1" | grep '[^[:blank:]]' >/dev/null 2>&1
1636
}
1737

18-
if git rev-parse --verify HEAD >/dev/null 2>&1
19-
then
20-
against=HEAD
38+
if git rev-parse --verify HEAD >/dev/null 2>&1 ; then
39+
against=HEAD
2140
else
22-
# Initial commit: diff against an empty tree object
23-
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
41+
# Initial commit: diff against an empty tree object
42+
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
2443
fi
2544

2645
# if we are in the middle of merging skip hooks
27-
MERGING=$(git rev-parse MERGE_HEAD 2>&1)
28-
if [[ $? == 0 ]]; then
46+
if git rev-parse MERGE_HEAD >/dev/null 2>&1 ; then
2947
exit 0
3048
fi
3149

32-
# if we are in the middle of merging skip hooks
33-
PICKING=$(git rev-parse CHERRY_PICK_HEAD 2>&1)
34-
if [[ $? == 0 ]]; then
50+
if git rev-parse CHERRY_PICK_HEAD >/dev/null 2>&1 ; then
3551
exit 0
3652
fi
3753

3854
# If you want to allow non-ASCII filenames set this variable to true.
39-
allownonascii=$(git config --bool hooks.allownonascii)
55+
allownonascii=$(git config --bool hooks.allownonascii || true)
4056

4157
# Redirect output to stderr.
4258
exec 1>&2
4359

44-
let status=0
60+
status=0
4561
# Cross platform projects tend to avoid non-ASCII filenames; prevent
4662
# them from being added to the repository. We exploit the fact that the
4763
# printable range starts at the space character and ends with tilde.
4864
if [ "$allownonascii" != "true" ] &&
49-
# Note that the use of brackets around a tr range is ok here, (it's
50-
# even required, for portability to Solaris 10's /usr/bin/tr), since
51-
# the square bracket bytes happen to fall in the designated range.
52-
test $(git diff --cached --name-only --diff-filter=A -z $against |
53-
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
65+
# Note that the use of brackets around a tr range is ok here, (it's
66+
# even required, for portability to Solaris 10's /usr/bin/tr), since
67+
# the square bracket bytes happen to fall in the designated range.
68+
(( "$(git diff --cached --name-only --diff-filter=A -z $against |
69+
LC_ALL=C tr -d '[ -~]\0' | wc -c)" != 0 ))
5470
then
55-
cat &>2 <<\EOF
56-
Error: Attempt to add a non-ASCII file name.
57-
58-
This can cause problems if you want to work with people on other platforms.
59-
60-
To be portable it is advisable to rename the file.
61-
62-
If you know what you are doing you can disable this check using:
63-
64-
git config hooks.allownonascii true
71+
cat <<-EOF
72+
Error: Attempt to add a non-ASCII file name.
73+
This can cause problems if you want to work with people on other platforms.
74+
To be portable it is advisable to rename the file.
75+
If you know what you are doing you can disable this check using:
76+
git config hooks.allownonascii true
6577
EOF
66-
let status=1
78+
status=1
6779
fi
6880

6981
# If there is a file that does not end with a newline, print its name and fail.
7082
for f in $(git diff-index --name-status --cached $against | grep -v ^D | cut -c3-); do
71-
if [[ "$f" =~ ([.](h|m|c|rb|sh|py|txt|md|f90|F90|cmake|x64|csh)|makefile|Makefile)$ ]] ||
83+
if [[ "$f" =~ ([.](h|m|c|rb|sh|py|txt|md|f90|F90|cmake|x64|csh|txt)|makefile|Makefile)$ ]] ||
7284
head -n 1 | grep '^#!/'; then
7385
if ! ends_with_newline "$f"; then
74-
echo &>2 "No newline at end of file: $f"
86+
echo "No newline at end of file: $f"
87+
echo ""
88+
status=1
89+
fi
90+
if ! ends_with_single_new_line "$f"; then
91+
echo "multiple blank lines at end of file: $f"
7592
echo ""
76-
let status=1
93+
status=1
7794
fi
7895
fi
7996
done
8097

8198
# If there are whitespace errors, print the offending file names and fail.
82-
git diff-index --check --cached $against -- || (let status=1 echo 'white space violations found')
99+
if ! git diff-index --check --cached $against -- ; then
100+
status=1
101+
echo "white space violations found"
102+
fi
103+
83104

84105
if [[ $status = 0 ]]; then
85-
exit 0
106+
exit 0
86107
fi
87108

88109
exit 1

developer-scripts/git-hooks/pre-push

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,48 @@
1616
#
1717
# <local ref> <local sha1> <remote ref> <remote sha1>
1818
#
19-
# This sample shows how to prevent push of commits where the log message starts
19+
# This script prevents the push of commits where the log message starts
2020
# with "WIP" (work in progress).
2121

22-
remote="$1"
23-
url="$2"
22+
# This script is distributed with OpenCoarrays and inteded to be used by
23+
# OpenCoarrays developers and contributors to ensure project coding standards
24+
# are adhered to.
25+
26+
# shellcheck disable=SC2034
27+
28+
set -o errexit
29+
set -o pipefail
30+
set -o nounset
31+
set -o errtrace
32+
33+
__file=pre-push
34+
35+
err_report() {
36+
error_code=$?
37+
echo 2>&1 "Error in $__file in function $1 on line $2"
38+
exit $error_code
39+
}
40+
41+
trap 'err_report "${FUNCNAME:-.}" $LINENO' ERR
42+
43+
err_report() {
44+
error_code=$?
45+
error "Error in $__file in function $1 on line $2"
46+
exit $error_code
47+
}
48+
49+
trap 'err_report "${FUNCNAME:-.}" $LINENO' ERR
50+
51+
52+
{
53+
remote="$1"
54+
url="$2"
55+
}
2456

2557
z40=0000000000000000000000000000000000000000
2658

27-
while read local_ref local_sha remote_ref remote_sha
59+
# shellcheck disable=SC2034
60+
while read -r local_ref local_sha remote_ref remote_sha
2861
do
2962
if [ "$local_sha" = $z40 ]
3063
then
@@ -41,7 +74,7 @@ do
4174
fi
4275

4376
# Check for WIP commit
44-
commit=`git rev-list -n 1 --grep '^WIP' "$range"`
77+
commit=$(git rev-list -n 1 --grep '^WIP' "$range" || true)
4578
if [ -n "$commit" ]
4679
then
4780
echo >&2 "Found WIP commit in $local_ref, not pushing"

0 commit comments

Comments
 (0)