-
Notifications
You must be signed in to change notification settings - Fork 0
/
pre-push
executable file
·152 lines (138 loc) · 4.84 KB
/
pre-push
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
#!/usr/bin/env bash
#
# Usage: Copy this file to your repository's .git/hooks directory. Name the
# copy "pre-push" and set the executable bit.
#
# cp gerrit-pre-push /path/to/repo/.git/hooks/pre-push \
# && chmod +x /path/to/repo/.git/hooks/pre-push
#
# This hook checks for unwanted pushes to specific remotes by checking commit
# messages for bad patterns. If such a pattern is found, the push is aborted.
# This hook can also run additional checks when pushing to those remotes.
#
# # Selecting remotes #
#
# Run `git config jdkprepush.remotes "<remote_names>"`. Remote names should be
# a space-separated list. Additionally, the special name "GERRIT" can be used
# to check pushes to any remote when the remote ref starts with "refs/for/".
#
# If not specified in git config, the default value "GERRIT" is used. If
# specified but empty, this hook will not check any remotes.
#
# # Specifying patterns #
#
# Run `git config jdkprepush.patterns "<patterns>"`. Use a whitespace-separated
# list of regular expression patterns. If your patterns may include whitespace,
# you can use another separator character; in that case, also run
# `git config jdkprepush.separator '<char>'` to specify it.
#
# Patters are passed to git rev-list --grep. By default, patterns are case-
# insensitive.
#
# If not specified in git config, the default value "^(WIP|stash)" is used. If
# specified but empty, this hook will not look for any patterns.
#
# # Running additional checks #
#
# To run project-specific checks before pushing (e.g. a test suite), do either
# of the following:
#
# - Add a file named "pre-push-run-checks" in the .git/hooks directory. It will
# be executed if pushing to Gerrit, and its exit status will be used as the
# exit status for this hook.
#
# - Modify the block at the end of this file with your commands. (In that case,
# make sure this isn't a symlinked file.)
#
# Remaining comments are copied from .git/hooks/pre-push.sample.
#
# -----
# An example hook script to verify what is about to be pushed. Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed. If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
# <local ref> <local sha1> <remote ref> <remote sha1>
remote="$1"
url="$2"
z40=0000000000000000000000000000000000000000
# read git config for remotes
# -> not specified -> "GERRIT"
# -> empty -> skip hook
# read git config for patterns (pattern?)
# -> not specified -> "^(WIP|stash)"
# -> empty -> don't look for patterns (but still run checks)
# while read
# - pass deletes through
# - check if we're interested (if not, pass)
# - remote_ref in REMOTES, or GERRIT in REMOTES and remote_ref starts with refs/for/
# - mark run-checks
# - check patterns (unless patterns empty)
while read local_ref local_sha remote_ref remote_sha
do
# Handle delete
if [[ "$local_sha" = "$z40" ]]
then
echo "$local_ref, $remote_ref"
:
# Move along if we don't match refs/for/
elif [[ ! "$remote_ref" =~ ^refs/for/.+ ]]
then
echo "$local_ref, $remote_ref"
:
else
echo "$local_ref, $local_sha, $remote_ref, $remote_sha"
if [[ "$remote_sha" = "$z40" ]]
then
# New branch, examine all commits
branchname="${remote_ref#refs/for/}"
if [[ "$branchname" =~ % ]]
then
# Gerrit allows various push-options by appending them to the remote
# using "%<option>=<string>[,<option>=<string>...]". Strip this off.
# TODO: '%' is a valid character in branch names, so this could mangle
# the branch name. We should find a way to workaround that.
echo "NOTE: stripping Gerrit push-options beginning at '%'"
branchname=${branchname%%\%*}
fi
if git check-ref-format --allow-onelevel "$branchname"
then
range="${remote}/${branchname}..$local_sha"
fi
if [[ -z "$range" ]]
then
range="$local_sha"
fi
else
# Update to existing branch, examine new commits
range="$remote_sha..$local_sha"
fi
echo "Examining $range"
# Check for WIP/stash commit
commit=`git rev-list -n 1 -i --grep '^WIP' --grep '^stash' "$range"`
if [[ -n "$commit" ]]
then
echo >&2 "Found WIP/stash commit in $local_ref, not pushing ($commit)"
exit 1
fi
# In case you want to run any verifications
run_checks=true
fi
done
if [[ -n "$run_checks" ]]; then
hookfile="$(git rev-parse --git-dir)/hooks/gerrit-pre-push"
if [[ -e "$hookfile" ]]; then
[[ -x "$hookfile" ]] && "$hookfile"
exit $?
fi
fi
exit 0