1#!/bin/sh
2
3test_description='pre-commit and pre-merge-commit hooks'
4
5. ./test-lib.sh
6
7HOOKDIR="$(git rev-parse --git-dir)/hooks"
8PRECOMMIT="$HOOKDIR/pre-commit"
9PREMERGE="$HOOKDIR/pre-merge-commit"
10
11# Prepare sample scripts that write their $0 to actual_hooks
12test_expect_success 'sample script setup' '
13 mkdir -p "$HOOKDIR" &&
14 write_script "$HOOKDIR/success.sample" <<-\EOF &&
15 echo $0 >>actual_hooks
16 exit 0
17 EOF
18 write_script "$HOOKDIR/fail.sample" <<-\EOF &&
19 echo $0 >>actual_hooks
20 exit 1
21 EOF
22 write_script "$HOOKDIR/non-exec.sample" <<-\EOF &&
23 echo $0 >>actual_hooks
24 exit 1
25 EOF
26 chmod -x "$HOOKDIR/non-exec.sample" &&
27 write_script "$HOOKDIR/require-prefix.sample" <<-\EOF &&
28 echo $0 >>actual_hooks
29 test $GIT_PREFIX = "success/"
30 EOF
31 write_script "$HOOKDIR/check-author.sample" <<-\EOF
32 echo $0 >>actual_hooks
33 test "$GIT_AUTHOR_NAME" = "New Author" &&
34 test "$GIT_AUTHOR_EMAIL" = "newauthor@example.com"
35 EOF
36'
37
38test_expect_success 'root commit' '
39 echo "root" >file &&
40 git add file &&
41 git commit -m "zeroth" &&
42 git checkout -b side &&
43 echo "foo" >foo &&
44 git add foo &&
45 git commit -m "make it non-ff" &&
46 git branch side-orig side &&
47 git checkout master
48'
49
50test_expect_success 'setup conflicting branches' '
51 test_when_finished "git checkout master" &&
52 git checkout -b conflicting-a master &&
53 echo a >conflicting &&
54 git add conflicting &&
55 git commit -m conflicting-a &&
56 git checkout -b conflicting-b master &&
57 echo b >conflicting &&
58 git add conflicting &&
59 git commit -m conflicting-b
60'
61
62test_expect_success 'with no hook' '
63 test_when_finished "rm -f actual_hooks" &&
64 echo "foo" >file &&
65 git add file &&
66 git commit -m "first" &&
67 test_path_is_missing actual_hooks
68'
69
70test_expect_success 'with no hook (merge)' '
71 test_when_finished "rm -f actual_hooks" &&
72 git branch -f side side-orig &&
73 git checkout side &&
74 git merge -m "merge master" master &&
75 git checkout master &&
76 test_path_is_missing actual_hooks
77'
78
79test_expect_success '--no-verify with no hook' '
80 test_when_finished "rm -f actual_hooks" &&
81 echo "bar" >file &&
82 git add file &&
83 git commit --no-verify -m "bar" &&
84 test_path_is_missing actual_hooks
85'
86
87test_expect_success '--no-verify with no hook (merge)' '
88 test_when_finished "rm -f actual_hooks" &&
89 git branch -f side side-orig &&
90 git checkout side &&
91 git merge --no-verify -m "merge master" master &&
92 git checkout master &&
93 test_path_is_missing actual_hooks
94'
95
96test_expect_success 'with succeeding hook' '
97 test_when_finished "rm -f \"$PRECOMMIT\" expected_hooks actual_hooks" &&
98 cp "$HOOKDIR/success.sample" "$PRECOMMIT" &&
99 echo "$PRECOMMIT" >expected_hooks &&
100 echo "more" >>file &&
101 git add file &&
102 git commit -m "more" &&
103 test_cmp expected_hooks actual_hooks
104'
105
106test_expect_success 'with succeeding hook (merge)' '
107 test_when_finished "rm -f \"$PREMERGE\" expected_hooks actual_hooks" &&
108 cp "$HOOKDIR/success.sample" "$PREMERGE" &&
109 echo "$PREMERGE" >expected_hooks &&
110 git checkout side &&
111 git merge -m "merge master" master &&
112 git checkout master &&
113 test_cmp expected_hooks actual_hooks
114'
115
116test_expect_success 'automatic merge fails; both hooks are available' '
117 test_when_finished "rm -f \"$PREMERGE\" \"$PRECOMMIT\"" &&
118 test_when_finished "rm -f expected_hooks actual_hooks" &&
119 test_when_finished "git checkout master" &&
120 cp "$HOOKDIR/success.sample" "$PREMERGE" &&
121 cp "$HOOKDIR/success.sample" "$PRECOMMIT" &&
122
123 git checkout conflicting-a &&
124 test_must_fail git merge -m "merge conflicting-b" conflicting-b &&
125 test_path_is_missing actual_hooks &&
126
127 echo "$PRECOMMIT" >expected_hooks &&
128 echo a+b >conflicting &&
129 git add conflicting &&
130 git commit -m "resolve conflict" &&
131 test_cmp expected_hooks actual_hooks
132'
133
134test_expect_success '--no-verify with succeeding hook' '
135 test_when_finished "rm -f \"$PRECOMMIT\" actual_hooks" &&
136 cp "$HOOKDIR/success.sample" "$PRECOMMIT" &&
137 echo "even more" >>file &&
138 git add file &&
139 git commit --no-verify -m "even more" &&
140 test_path_is_missing actual_hooks
141'
142
143test_expect_success '--no-verify with succeeding hook (merge)' '
144 test_when_finished "rm -f \"$PREMERGE\" actual_hooks" &&
145 cp "$HOOKDIR/success.sample" "$PREMERGE" &&
146 git branch -f side side-orig &&
147 git checkout side &&
148 git merge --no-verify -m "merge master" master &&
149 git checkout master &&
150 test_path_is_missing actual_hooks
151'
152
153test_expect_success 'with failing hook' '
154 test_when_finished "rm -f \"$PRECOMMIT\" expected_hooks actual_hooks" &&
155 cp "$HOOKDIR/fail.sample" "$PRECOMMIT" &&
156 echo "$PRECOMMIT" >expected_hooks &&
157 echo "another" >>file &&
158 git add file &&
159 test_must_fail git commit -m "another" &&
160 test_cmp expected_hooks actual_hooks
161'
162
163test_expect_success '--no-verify with failing hook' '
164 test_when_finished "rm -f \"$PRECOMMIT\" actual_hooks" &&
165 cp "$HOOKDIR/fail.sample" "$PRECOMMIT" &&
166 echo "stuff" >>file &&
167 git add file &&
168 git commit --no-verify -m "stuff" &&
169 test_path_is_missing actual_hooks
170'
171
172test_expect_success 'with failing hook (merge)' '
173 test_when_finished "rm -f \"$PREMERGE\" expected_hooks actual_hooks" &&
174 cp "$HOOKDIR/fail.sample" "$PREMERGE" &&
175 echo "$PREMERGE" >expected_hooks &&
176 git checkout side &&
177 test_must_fail git merge -m "merge master" master &&
178 git checkout master &&
179 test_cmp expected_hooks actual_hooks
180'
181
182test_expect_success '--no-verify with failing hook (merge)' '
183 test_when_finished "rm -f \"$PREMERGE\" actual_hooks" &&
184 cp "$HOOKDIR/fail.sample" "$PREMERGE" &&
185 git branch -f side side-orig &&
186 git checkout side &&
187 git merge --no-verify -m "merge master" master &&
188 git checkout master &&
189 test_path_is_missing actual_hooks
190'
191
192test_expect_success POSIXPERM 'with non-executable hook' '
193 test_when_finished "rm -f \"$PRECOMMIT\" actual_hooks" &&
194 cp "$HOOKDIR/non-exec.sample" "$PRECOMMIT" &&
195 echo "content" >>file &&
196 git add file &&
197 git commit -m "content" &&
198 test_path_is_missing actual_hooks
199'
200
201test_expect_success POSIXPERM '--no-verify with non-executable hook' '
202 test_when_finished "rm -f \"$PRECOMMIT\" actual_hooks" &&
203 cp "$HOOKDIR/non-exec.sample" "$PRECOMMIT" &&
204 echo "more content" >>file &&
205 git add file &&
206 git commit --no-verify -m "more content" &&
207 test_path_is_missing actual_hooks
208'
209
210test_expect_success POSIXPERM 'with non-executable hook (merge)' '
211 test_when_finished "rm -f \"$PREMERGE\" actual_hooks" &&
212 cp "$HOOKDIR/non-exec.sample" "$PREMERGE" &&
213 git branch -f side side-orig &&
214 git checkout side &&
215 git merge -m "merge master" master &&
216 git checkout master &&
217 test_path_is_missing actual_hooks
218'
219
220test_expect_success POSIXPERM '--no-verify with non-executable hook (merge)' '
221 test_when_finished "rm -f \"$PREMERGE\" actual_hooks" &&
222 cp "$HOOKDIR/non-exec.sample" "$PREMERGE" &&
223 git branch -f side side-orig &&
224 git checkout side &&
225 git merge --no-verify -m "merge master" master &&
226 git checkout master &&
227 test_path_is_missing actual_hooks
228'
229
230test_expect_success 'with hook requiring GIT_PREFIX' '
231 test_when_finished "rm -rf \"$PRECOMMIT\" expected_hooks actual_hooks success" &&
232 cp "$HOOKDIR/require-prefix.sample" "$PRECOMMIT" &&
233 echo "$PRECOMMIT" >expected_hooks &&
234 echo "more content" >>file &&
235 git add file &&
236 mkdir success &&
237 (
238 cd success &&
239 git commit -m "hook requires GIT_PREFIX = success/"
240 ) &&
241 test_cmp expected_hooks actual_hooks
242'
243
244test_expect_success 'with failing hook requiring GIT_PREFIX' '
245 test_when_finished "rm -rf \"$PRECOMMIT\" expected_hooks actual_hooks fail" &&
246 cp "$HOOKDIR/require-prefix.sample" "$PRECOMMIT" &&
247 echo "$PRECOMMIT" >expected_hooks &&
248 echo "more content" >>file &&
249 git add file &&
250 mkdir fail &&
251 (
252 cd fail &&
253 test_must_fail git commit -m "hook must fail"
254 ) &&
255 git checkout -- file &&
256 test_cmp expected_hooks actual_hooks
257'
258
259test_expect_success 'check the author in hook' '
260 test_when_finished "rm -f \"$PRECOMMIT\" expected_hooks actual_hooks" &&
261 cp "$HOOKDIR/check-author.sample" "$PRECOMMIT" &&
262 cat >expected_hooks <<-EOF &&
263 $PRECOMMIT
264 $PRECOMMIT
265 $PRECOMMIT
266 EOF
267 test_must_fail git commit --allow-empty -m "by a.u.thor" &&
268 (
269 GIT_AUTHOR_NAME="New Author" &&
270 GIT_AUTHOR_EMAIL="newauthor@example.com" &&
271 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL &&
272 git commit --allow-empty -m "by new.author via env" &&
273 git show -s
274 ) &&
275 git commit --author="New Author <newauthor@example.com>" \
276 --allow-empty -m "by new.author via command line" &&
277 git show -s &&
278 test_cmp expected_hooks actual_hooks
279'
280
281test_done