Merge branch 'ma/leakplugs'
[git] / t / t1404-update-ref-errors.sh
1 #!/bin/sh
2
3 test_description='Test git update-ref error handling'
4 . ./test-lib.sh
5
6 # Create some references, perhaps run pack-refs --all, then try to
7 # create some more references. Ensure that the second creation fails
8 # with the correct error message.
9 # Usage: test_update_rejected <before> <pack> <create> <error>
10 #   <before> is a ws-separated list of refs to create before the test
11 #   <pack> (true or false) tells whether to pack the refs before the test
12 #   <create> is a list of variables to attempt creating
13 #   <error> is a string to look for in the stderr of update-ref.
14 # All references are created in the namespace specified by the current
15 # value of $prefix.
16 test_update_rejected () {
17         before="$1" &&
18         pack="$2" &&
19         create="$3" &&
20         error="$4" &&
21         printf "create $prefix/%s $C\n" $before |
22         git update-ref --stdin &&
23         git for-each-ref $prefix >unchanged &&
24         if $pack
25         then
26                 git pack-refs --all
27         fi &&
28         printf "create $prefix/%s $C\n" $create >input &&
29         test_must_fail git update-ref --stdin <input 2>output.err &&
30         grep -F "$error" output.err &&
31         git for-each-ref $prefix >actual &&
32         test_cmp unchanged actual
33 }
34
35 Q="'"
36
37 test_expect_success 'setup' '
38
39         git commit --allow-empty -m Initial &&
40         C=$(git rev-parse HEAD) &&
41         git commit --allow-empty -m Second &&
42         D=$(git rev-parse HEAD) &&
43         git commit --allow-empty -m Third &&
44         E=$(git rev-parse HEAD)
45 '
46
47 test_expect_success 'existing loose ref is a simple prefix of new' '
48
49         prefix=refs/1l &&
50         test_update_rejected "a c e" false "b c/x d" \
51                 "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q"
52
53 '
54
55 test_expect_success 'existing packed ref is a simple prefix of new' '
56
57         prefix=refs/1p &&
58         test_update_rejected "a c e" true "b c/x d" \
59                 "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q"
60
61 '
62
63 test_expect_success 'existing loose ref is a deeper prefix of new' '
64
65         prefix=refs/2l &&
66         test_update_rejected "a c e" false "b c/x/y d" \
67                 "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q"
68
69 '
70
71 test_expect_success 'existing packed ref is a deeper prefix of new' '
72
73         prefix=refs/2p &&
74         test_update_rejected "a c e" true "b c/x/y d" \
75                 "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q"
76
77 '
78
79 test_expect_success 'new ref is a simple prefix of existing loose' '
80
81         prefix=refs/3l &&
82         test_update_rejected "a c/x e" false "b c d" \
83                 "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q"
84
85 '
86
87 test_expect_success 'new ref is a simple prefix of existing packed' '
88
89         prefix=refs/3p &&
90         test_update_rejected "a c/x e" true "b c d" \
91                 "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q"
92
93 '
94
95 test_expect_success 'new ref is a deeper prefix of existing loose' '
96
97         prefix=refs/4l &&
98         test_update_rejected "a c/x/y e" false "b c d" \
99                 "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q"
100
101 '
102
103 test_expect_success 'new ref is a deeper prefix of existing packed' '
104
105         prefix=refs/4p &&
106         test_update_rejected "a c/x/y e" true "b c d" \
107                 "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q"
108
109 '
110
111 test_expect_success 'one new ref is a simple prefix of another' '
112
113         prefix=refs/5 &&
114         test_update_rejected "a e" false "b c c/x d" \
115                 "cannot process $Q$prefix/c$Q and $Q$prefix/c/x$Q at the same time"
116
117 '
118
119 test_expect_success 'empty directory should not fool rev-parse' '
120         prefix=refs/e-rev-parse &&
121         git update-ref $prefix/foo $C &&
122         git pack-refs --all &&
123         mkdir -p .git/$prefix/foo/bar/baz &&
124         echo "$C" >expected &&
125         git rev-parse $prefix/foo >actual &&
126         test_cmp expected actual
127 '
128
129 test_expect_success 'empty directory should not fool for-each-ref' '
130         prefix=refs/e-for-each-ref &&
131         git update-ref $prefix/foo $C &&
132         git for-each-ref $prefix >expected &&
133         git pack-refs --all &&
134         mkdir -p .git/$prefix/foo/bar/baz &&
135         git for-each-ref $prefix >actual &&
136         test_cmp expected actual
137 '
138
139 test_expect_success 'empty directory should not fool create' '
140         prefix=refs/e-create &&
141         mkdir -p .git/$prefix/foo/bar/baz &&
142         printf "create %s $C\n" $prefix/foo |
143         git update-ref --stdin
144 '
145
146 test_expect_success 'empty directory should not fool verify' '
147         prefix=refs/e-verify &&
148         git update-ref $prefix/foo $C &&
149         git pack-refs --all &&
150         mkdir -p .git/$prefix/foo/bar/baz &&
151         printf "verify %s $C\n" $prefix/foo |
152         git update-ref --stdin
153 '
154
155 test_expect_success 'empty directory should not fool 1-arg update' '
156         prefix=refs/e-update-1 &&
157         git update-ref $prefix/foo $C &&
158         git pack-refs --all &&
159         mkdir -p .git/$prefix/foo/bar/baz &&
160         printf "update %s $D\n" $prefix/foo |
161         git update-ref --stdin
162 '
163
164 test_expect_success 'empty directory should not fool 2-arg update' '
165         prefix=refs/e-update-2 &&
166         git update-ref $prefix/foo $C &&
167         git pack-refs --all &&
168         mkdir -p .git/$prefix/foo/bar/baz &&
169         printf "update %s $D $C\n" $prefix/foo |
170         git update-ref --stdin
171 '
172
173 test_expect_success 'empty directory should not fool 0-arg delete' '
174         prefix=refs/e-delete-0 &&
175         git update-ref $prefix/foo $C &&
176         git pack-refs --all &&
177         mkdir -p .git/$prefix/foo/bar/baz &&
178         printf "delete %s\n" $prefix/foo |
179         git update-ref --stdin
180 '
181
182 test_expect_success 'empty directory should not fool 1-arg delete' '
183         prefix=refs/e-delete-1 &&
184         git update-ref $prefix/foo $C &&
185         git pack-refs --all &&
186         mkdir -p .git/$prefix/foo/bar/baz &&
187         printf "delete %s $C\n" $prefix/foo |
188         git update-ref --stdin
189 '
190
191 # Test various errors when reading the old values of references...
192
193 test_expect_success 'missing old value blocks update' '
194         prefix=refs/missing-update &&
195         cat >expected <<-EOF &&
196         fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q
197         EOF
198         printf "%s\n" "update $prefix/foo $E $D" |
199         test_must_fail git update-ref --stdin 2>output.err &&
200         test_cmp expected output.err
201 '
202
203 test_expect_success 'incorrect old value blocks update' '
204         prefix=refs/incorrect-update &&
205         git update-ref $prefix/foo $C &&
206         cat >expected <<-EOF &&
207         fatal: cannot lock ref $Q$prefix/foo$Q: is at $C but expected $D
208         EOF
209         printf "%s\n" "update $prefix/foo $E $D" |
210         test_must_fail git update-ref --stdin 2>output.err &&
211         test_cmp expected output.err
212 '
213
214 test_expect_success 'existing old value blocks create' '
215         prefix=refs/existing-create &&
216         git update-ref $prefix/foo $C &&
217         cat >expected <<-EOF &&
218         fatal: cannot lock ref $Q$prefix/foo$Q: reference already exists
219         EOF
220         printf "%s\n" "create $prefix/foo $E" |
221         test_must_fail git update-ref --stdin 2>output.err &&
222         test_cmp expected output.err
223 '
224
225 test_expect_success 'incorrect old value blocks delete' '
226         prefix=refs/incorrect-delete &&
227         git update-ref $prefix/foo $C &&
228         cat >expected <<-EOF &&
229         fatal: cannot lock ref $Q$prefix/foo$Q: is at $C but expected $D
230         EOF
231         printf "%s\n" "delete $prefix/foo $D" |
232         test_must_fail git update-ref --stdin 2>output.err &&
233         test_cmp expected output.err
234 '
235
236 test_expect_success 'missing old value blocks indirect update' '
237         prefix=refs/missing-indirect-update &&
238         git symbolic-ref $prefix/symref $prefix/foo &&
239         cat >expected <<-EOF &&
240         fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q
241         EOF
242         printf "%s\n" "update $prefix/symref $E $D" |
243         test_must_fail git update-ref --stdin 2>output.err &&
244         test_cmp expected output.err
245 '
246
247 test_expect_success 'incorrect old value blocks indirect update' '
248         prefix=refs/incorrect-indirect-update &&
249         git symbolic-ref $prefix/symref $prefix/foo &&
250         git update-ref $prefix/foo $C &&
251         cat >expected <<-EOF &&
252         fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D
253         EOF
254         printf "%s\n" "update $prefix/symref $E $D" |
255         test_must_fail git update-ref --stdin 2>output.err &&
256         test_cmp expected output.err
257 '
258
259 test_expect_success 'existing old value blocks indirect create' '
260         prefix=refs/existing-indirect-create &&
261         git symbolic-ref $prefix/symref $prefix/foo &&
262         git update-ref $prefix/foo $C &&
263         cat >expected <<-EOF &&
264         fatal: cannot lock ref $Q$prefix/symref$Q: reference already exists
265         EOF
266         printf "%s\n" "create $prefix/symref $E" |
267         test_must_fail git update-ref --stdin 2>output.err &&
268         test_cmp expected output.err
269 '
270
271 test_expect_success 'incorrect old value blocks indirect delete' '
272         prefix=refs/incorrect-indirect-delete &&
273         git symbolic-ref $prefix/symref $prefix/foo &&
274         git update-ref $prefix/foo $C &&
275         cat >expected <<-EOF &&
276         fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D
277         EOF
278         printf "%s\n" "delete $prefix/symref $D" |
279         test_must_fail git update-ref --stdin 2>output.err &&
280         test_cmp expected output.err
281 '
282
283 test_expect_success 'missing old value blocks indirect no-deref update' '
284         prefix=refs/missing-noderef-update &&
285         git symbolic-ref $prefix/symref $prefix/foo &&
286         cat >expected <<-EOF &&
287         fatal: cannot lock ref $Q$prefix/symref$Q: reference is missing but expected $D
288         EOF
289         printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
290         test_must_fail git update-ref --stdin 2>output.err &&
291         test_cmp expected output.err
292 '
293
294 test_expect_success 'incorrect old value blocks indirect no-deref update' '
295         prefix=refs/incorrect-noderef-update &&
296         git symbolic-ref $prefix/symref $prefix/foo &&
297         git update-ref $prefix/foo $C &&
298         cat >expected <<-EOF &&
299         fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D
300         EOF
301         printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
302         test_must_fail git update-ref --stdin 2>output.err &&
303         test_cmp expected output.err
304 '
305
306 test_expect_success 'existing old value blocks indirect no-deref create' '
307         prefix=refs/existing-noderef-create &&
308         git symbolic-ref $prefix/symref $prefix/foo &&
309         git update-ref $prefix/foo $C &&
310         cat >expected <<-EOF &&
311         fatal: cannot lock ref $Q$prefix/symref$Q: reference already exists
312         EOF
313         printf "%s\n" "option no-deref" "create $prefix/symref $E" |
314         test_must_fail git update-ref --stdin 2>output.err &&
315         test_cmp expected output.err
316 '
317
318 test_expect_success 'incorrect old value blocks indirect no-deref delete' '
319         prefix=refs/incorrect-noderef-delete &&
320         git symbolic-ref $prefix/symref $prefix/foo &&
321         git update-ref $prefix/foo $C &&
322         cat >expected <<-EOF &&
323         fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D
324         EOF
325         printf "%s\n" "option no-deref" "delete $prefix/symref $D" |
326         test_must_fail git update-ref --stdin 2>output.err &&
327         test_cmp expected output.err
328 '
329
330 test_expect_success 'non-empty directory blocks create' '
331         prefix=refs/ne-create &&
332         mkdir -p .git/$prefix/foo/bar &&
333         : >.git/$prefix/foo/bar/baz.lock &&
334         test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" &&
335         cat >expected <<-EOF &&
336         fatal: cannot lock ref $Q$prefix/foo$Q: there is a non-empty directory $Q.git/$prefix/foo$Q blocking reference $Q$prefix/foo$Q
337         EOF
338         printf "%s\n" "update $prefix/foo $C" |
339         test_must_fail git update-ref --stdin 2>output.err &&
340         test_cmp expected output.err &&
341         cat >expected <<-EOF &&
342         fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q
343         EOF
344         printf "%s\n" "update $prefix/foo $D $C" |
345         test_must_fail git update-ref --stdin 2>output.err &&
346         test_cmp expected output.err
347 '
348
349 test_expect_success 'broken reference blocks create' '
350         prefix=refs/broken-create &&
351         mkdir -p .git/$prefix &&
352         echo "gobbledigook" >.git/$prefix/foo &&
353         test_when_finished "rm -f .git/$prefix/foo" &&
354         cat >expected <<-EOF &&
355         fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken
356         EOF
357         printf "%s\n" "update $prefix/foo $C" |
358         test_must_fail git update-ref --stdin 2>output.err &&
359         test_cmp expected output.err &&
360         cat >expected <<-EOF &&
361         fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken
362         EOF
363         printf "%s\n" "update $prefix/foo $D $C" |
364         test_must_fail git update-ref --stdin 2>output.err &&
365         test_cmp expected output.err
366 '
367
368 test_expect_success 'non-empty directory blocks indirect create' '
369         prefix=refs/ne-indirect-create &&
370         git symbolic-ref $prefix/symref $prefix/foo &&
371         mkdir -p .git/$prefix/foo/bar &&
372         : >.git/$prefix/foo/bar/baz.lock &&
373         test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" &&
374         cat >expected <<-EOF &&
375         fatal: cannot lock ref $Q$prefix/symref$Q: there is a non-empty directory $Q.git/$prefix/foo$Q blocking reference $Q$prefix/foo$Q
376         EOF
377         printf "%s\n" "update $prefix/symref $C" |
378         test_must_fail git update-ref --stdin 2>output.err &&
379         test_cmp expected output.err &&
380         cat >expected <<-EOF &&
381         fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q
382         EOF
383         printf "%s\n" "update $prefix/symref $D $C" |
384         test_must_fail git update-ref --stdin 2>output.err &&
385         test_cmp expected output.err
386 '
387
388 test_expect_success 'broken reference blocks indirect create' '
389         prefix=refs/broken-indirect-create &&
390         git symbolic-ref $prefix/symref $prefix/foo &&
391         echo "gobbledigook" >.git/$prefix/foo &&
392         test_when_finished "rm -f .git/$prefix/foo" &&
393         cat >expected <<-EOF &&
394         fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken
395         EOF
396         printf "%s\n" "update $prefix/symref $C" |
397         test_must_fail git update-ref --stdin 2>output.err &&
398         test_cmp expected output.err &&
399         cat >expected <<-EOF &&
400         fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken
401         EOF
402         printf "%s\n" "update $prefix/symref $D $C" |
403         test_must_fail git update-ref --stdin 2>output.err &&
404         test_cmp expected output.err
405 '
406
407 test_expect_success 'no bogus intermediate values during delete' '
408         prefix=refs/slow-transaction &&
409         # Set up a reference with differing loose and packed versions:
410         git update-ref $prefix/foo $C &&
411         git pack-refs --all &&
412         git update-ref $prefix/foo $D &&
413         git for-each-ref $prefix >unchanged &&
414         # Now try to update the reference, but hold the `packed-refs` lock
415         # for a while to see what happens while the process is blocked:
416         : >.git/packed-refs.lock &&
417         test_when_finished "rm -f .git/packed-refs.lock" &&
418         {
419                 # Note: the following command is intentionally run in the
420                 # background. We increase the timeout so that `update-ref`
421                 # attempts to acquire the `packed-refs` lock for longer than
422                 # it takes for us to do the check then delete it:
423                 git -c core.packedrefstimeout=3000 update-ref -d $prefix/foo &
424         } &&
425         pid2=$! &&
426         # Give update-ref plenty of time to get to the point where it tries
427         # to lock packed-refs:
428         sleep 1 &&
429         # Make sure that update-ref did not complete despite the lock:
430         kill -0 $pid2 &&
431         # Verify that the reference still has its old value:
432         sha1=$(git rev-parse --verify --quiet $prefix/foo || echo undefined) &&
433         case "$sha1" in
434         $D)
435                 # This is what we hope for; it means that nothing
436                 # user-visible has changed yet.
437                 : ;;
438         undefined)
439                 # This is not correct; it means the deletion has happened
440                 # already even though update-ref should not have been
441                 # able to acquire the lock yet.
442                 echo "$prefix/foo deleted prematurely" &&
443                 break
444                 ;;
445         $C)
446                 # This value should never be seen. Probably the loose
447                 # reference has been deleted but the packed reference
448                 # is still there:
449                 echo "$prefix/foo incorrectly observed to be C" &&
450                 break
451                 ;;
452         *)
453                 # WTF?
454                 echo "unexpected value observed for $prefix/foo: $sha1" &&
455                 break
456                 ;;
457         esac >out &&
458         rm -f .git/packed-refs.lock &&
459         wait $pid2 &&
460         test_must_be_empty out &&
461         test_must_fail git rev-parse --verify --quiet $prefix/foo
462 '
463
464 test_expect_success 'delete fails cleanly if packed-refs file is locked' '
465         prefix=refs/locked-packed-refs &&
466         # Set up a reference with differing loose and packed versions:
467         git update-ref $prefix/foo $C &&
468         git pack-refs --all &&
469         git update-ref $prefix/foo $D &&
470         git for-each-ref $prefix >unchanged &&
471         # Now try to delete it while the `packed-refs` lock is held:
472         : >.git/packed-refs.lock &&
473         test_when_finished "rm -f .git/packed-refs.lock" &&
474         test_must_fail git update-ref -d $prefix/foo >out 2>err &&
475         git for-each-ref $prefix >actual &&
476         test_i18ngrep "Unable to create $Q.*packed-refs.lock$Q: File exists" err &&
477         test_cmp unchanged actual
478 '
479
480 test_done