t4129: don't fail if setgid is set in the test directory
[git] / t / t7503-pre-commit-and-pre-merge-commit-hooks.sh
1 #!/bin/sh
2
3 test_description='pre-commit and pre-merge-commit hooks'
4
5 . ./test-lib.sh
6
7 HOOKDIR="$(git rev-parse --git-dir)/hooks"
8 PRECOMMIT="$HOOKDIR/pre-commit"
9 PREMERGE="$HOOKDIR/pre-merge-commit"
10
11 # Prepare sample scripts that write their $0 to actual_hooks
12 test_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
38 test_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
50 test_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
62 test_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
70 test_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
79 test_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
87 test_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
96 test_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
106 test_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
116 test_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
134 test_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
143 test_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
153 test_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
163 test_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
172 test_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
182 test_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
192 test_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
201 test_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
210 test_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
220 test_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
230 test_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
244 test_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
259 test_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
281 test_done