Merge branch 'nd/interpret-trailers-docfix'
[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         test_i18ngrep -F "$error" output.err &&
31         git for-each-ref $prefix >actual &&
32         test_cmp unchanged actual
33 }
34
35 Q="'"
36
37 # Test adding and deleting D/F-conflicting references in a single
38 # transaction.
39 df_test() {
40         prefix="$1"
41         pack=: symadd=false symdel=false add_del=false addref= delref=
42         shift
43         while test $# -gt 0
44         do
45                 case "$1" in
46                 --pack)
47                         pack="git pack-refs --all"
48                         shift
49                         ;;
50                 --sym-add)
51                         # Perform the add via a symbolic reference
52                         symadd=true
53                         shift
54                         ;;
55                 --sym-del)
56                         # Perform the del via a symbolic reference
57                         symdel=true
58                         shift
59                         ;;
60                 --del-add)
61                         # Delete first reference then add second
62                         add_del=false
63                         delref="$prefix/r/$2"
64                         addref="$prefix/r/$3"
65                         shift 3
66                         ;;
67                 --add-del)
68                         # Add first reference then delete second
69                         add_del=true
70                         addref="$prefix/r/$2"
71                         delref="$prefix/r/$3"
72                         shift 3
73                         ;;
74                 *)
75                         echo 1>&2 "Extra args to df_test: $*"
76                         return 1
77                         ;;
78                 esac
79         done
80         git update-ref "$delref" $C &&
81         if $symadd
82         then
83                 addname="$prefix/s/symadd" &&
84                 git symbolic-ref "$addname" "$addref"
85         else
86                 addname="$addref"
87         fi &&
88         if $symdel
89         then
90                 delname="$prefix/s/symdel" &&
91                 git symbolic-ref "$delname" "$delref"
92         else
93                 delname="$delref"
94         fi &&
95         cat >expected-err <<-EOF &&
96         fatal: cannot lock ref $Q$addname$Q: $Q$delref$Q exists; cannot create $Q$addref$Q
97         EOF
98         $pack &&
99         if $add_del
100         then
101                 printf "%s\n" "create $addname $D" "delete $delname"
102         else
103                 printf "%s\n" "delete $delname" "create $addname $D"
104         fi >commands &&
105         test_must_fail git update-ref --stdin <commands 2>output.err &&
106         test_i18ncmp expected-err output.err &&
107         printf "%s\n" "$C $delref" >expected-refs &&
108         git for-each-ref --format="%(objectname) %(refname)" $prefix/r >actual-refs &&
109         test_cmp expected-refs actual-refs
110 }
111
112 test_expect_success 'setup' '
113
114         git commit --allow-empty -m Initial &&
115         C=$(git rev-parse HEAD) &&
116         git commit --allow-empty -m Second &&
117         D=$(git rev-parse HEAD) &&
118         git commit --allow-empty -m Third &&
119         E=$(git rev-parse HEAD)
120 '
121
122 test_expect_success 'existing loose ref is a simple prefix of new' '
123
124         prefix=refs/1l &&
125         test_update_rejected "a c e" false "b c/x d" \
126                 "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q"
127
128 '
129
130 test_expect_success 'existing packed ref is a simple prefix of new' '
131
132         prefix=refs/1p &&
133         test_update_rejected "a c e" true "b c/x d" \
134                 "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q"
135
136 '
137
138 test_expect_success 'existing loose ref is a deeper prefix of new' '
139
140         prefix=refs/2l &&
141         test_update_rejected "a c e" false "b c/x/y d" \
142                 "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q"
143
144 '
145
146 test_expect_success 'existing packed ref is a deeper prefix of new' '
147
148         prefix=refs/2p &&
149         test_update_rejected "a c e" true "b c/x/y d" \
150                 "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q"
151
152 '
153
154 test_expect_success 'new ref is a simple prefix of existing loose' '
155
156         prefix=refs/3l &&
157         test_update_rejected "a c/x e" false "b c d" \
158                 "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q"
159
160 '
161
162 test_expect_success 'new ref is a simple prefix of existing packed' '
163
164         prefix=refs/3p &&
165         test_update_rejected "a c/x e" true "b c d" \
166                 "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q"
167
168 '
169
170 test_expect_success 'new ref is a deeper prefix of existing loose' '
171
172         prefix=refs/4l &&
173         test_update_rejected "a c/x/y e" false "b c d" \
174                 "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q"
175
176 '
177
178 test_expect_success 'new ref is a deeper prefix of existing packed' '
179
180         prefix=refs/4p &&
181         test_update_rejected "a c/x/y e" true "b c d" \
182                 "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q"
183
184 '
185
186 test_expect_success 'one new ref is a simple prefix of another' '
187
188         prefix=refs/5 &&
189         test_update_rejected "a e" false "b c c/x d" \
190                 "cannot process $Q$prefix/c$Q and $Q$prefix/c/x$Q at the same time"
191
192 '
193
194 test_expect_success 'empty directory should not fool rev-parse' '
195         prefix=refs/e-rev-parse &&
196         git update-ref $prefix/foo $C &&
197         git pack-refs --all &&
198         mkdir -p .git/$prefix/foo/bar/baz &&
199         echo "$C" >expected &&
200         git rev-parse $prefix/foo >actual &&
201         test_cmp expected actual
202 '
203
204 test_expect_success 'empty directory should not fool for-each-ref' '
205         prefix=refs/e-for-each-ref &&
206         git update-ref $prefix/foo $C &&
207         git for-each-ref $prefix >expected &&
208         git pack-refs --all &&
209         mkdir -p .git/$prefix/foo/bar/baz &&
210         git for-each-ref $prefix >actual &&
211         test_cmp expected actual
212 '
213
214 test_expect_success 'empty directory should not fool create' '
215         prefix=refs/e-create &&
216         mkdir -p .git/$prefix/foo/bar/baz &&
217         printf "create %s $C\n" $prefix/foo |
218         git update-ref --stdin
219 '
220
221 test_expect_success 'empty directory should not fool verify' '
222         prefix=refs/e-verify &&
223         git update-ref $prefix/foo $C &&
224         git pack-refs --all &&
225         mkdir -p .git/$prefix/foo/bar/baz &&
226         printf "verify %s $C\n" $prefix/foo |
227         git update-ref --stdin
228 '
229
230 test_expect_success 'empty directory should not fool 1-arg update' '
231         prefix=refs/e-update-1 &&
232         git update-ref $prefix/foo $C &&
233         git pack-refs --all &&
234         mkdir -p .git/$prefix/foo/bar/baz &&
235         printf "update %s $D\n" $prefix/foo |
236         git update-ref --stdin
237 '
238
239 test_expect_success 'empty directory should not fool 2-arg update' '
240         prefix=refs/e-update-2 &&
241         git update-ref $prefix/foo $C &&
242         git pack-refs --all &&
243         mkdir -p .git/$prefix/foo/bar/baz &&
244         printf "update %s $D $C\n" $prefix/foo |
245         git update-ref --stdin
246 '
247
248 test_expect_success 'empty directory should not fool 0-arg delete' '
249         prefix=refs/e-delete-0 &&
250         git update-ref $prefix/foo $C &&
251         git pack-refs --all &&
252         mkdir -p .git/$prefix/foo/bar/baz &&
253         printf "delete %s\n" $prefix/foo |
254         git update-ref --stdin
255 '
256
257 test_expect_success 'empty directory should not fool 1-arg delete' '
258         prefix=refs/e-delete-1 &&
259         git update-ref $prefix/foo $C &&
260         git pack-refs --all &&
261         mkdir -p .git/$prefix/foo/bar/baz &&
262         printf "delete %s $C\n" $prefix/foo |
263         git update-ref --stdin
264 '
265
266 test_expect_success 'D/F conflict prevents add long + delete short' '
267         df_test refs/df-al-ds --add-del foo/bar foo
268 '
269
270 test_expect_success 'D/F conflict prevents add short + delete long' '
271         df_test refs/df-as-dl --add-del foo foo/bar
272 '
273
274 test_expect_success 'D/F conflict prevents delete long + add short' '
275         df_test refs/df-dl-as --del-add foo/bar foo
276 '
277
278 test_expect_success 'D/F conflict prevents delete short + add long' '
279         df_test refs/df-ds-al --del-add foo foo/bar
280 '
281
282 test_expect_success 'D/F conflict prevents add long + delete short packed' '
283         df_test refs/df-al-dsp --pack --add-del foo/bar foo
284 '
285
286 test_expect_success 'D/F conflict prevents add short + delete long packed' '
287         df_test refs/df-as-dlp --pack --add-del foo foo/bar
288 '
289
290 test_expect_success 'D/F conflict prevents delete long packed + add short' '
291         df_test refs/df-dlp-as --pack --del-add foo/bar foo
292 '
293
294 test_expect_success 'D/F conflict prevents delete short packed + add long' '
295         df_test refs/df-dsp-al --pack --del-add foo foo/bar
296 '
297
298 # Try some combinations involving symbolic refs...
299
300 test_expect_success 'D/F conflict prevents indirect add long + delete short' '
301         df_test refs/df-ial-ds --sym-add --add-del foo/bar foo
302 '
303
304 test_expect_success 'D/F conflict prevents indirect add long + indirect delete short' '
305         df_test refs/df-ial-ids --sym-add --sym-del --add-del foo/bar foo
306 '
307
308 test_expect_success 'D/F conflict prevents indirect add short + indirect delete long' '
309         df_test refs/df-ias-idl --sym-add --sym-del --add-del foo foo/bar
310 '
311
312 test_expect_success 'D/F conflict prevents indirect delete long + indirect add short' '
313         df_test refs/df-idl-ias --sym-add --sym-del --del-add foo/bar foo
314 '
315
316 test_expect_success 'D/F conflict prevents indirect add long + delete short packed' '
317         df_test refs/df-ial-dsp --sym-add --pack --add-del foo/bar foo
318 '
319
320 test_expect_success 'D/F conflict prevents indirect add long + indirect delete short packed' '
321         df_test refs/df-ial-idsp --sym-add --sym-del --pack --add-del foo/bar foo
322 '
323
324 test_expect_success 'D/F conflict prevents add long + indirect delete short packed' '
325         df_test refs/df-al-idsp --sym-del --pack --add-del foo/bar foo
326 '
327
328 test_expect_success 'D/F conflict prevents indirect delete long packed + indirect add short' '
329         df_test refs/df-idlp-ias --sym-add --sym-del --pack --del-add foo/bar foo
330 '
331
332 # Test various errors when reading the old values of references...
333
334 test_expect_success 'missing old value blocks update' '
335         prefix=refs/missing-update &&
336         cat >expected <<-EOF &&
337         fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q
338         EOF
339         printf "%s\n" "update $prefix/foo $E $D" |
340         test_must_fail git update-ref --stdin 2>output.err &&
341         test_cmp expected output.err
342 '
343
344 test_expect_success 'incorrect old value blocks update' '
345         prefix=refs/incorrect-update &&
346         git update-ref $prefix/foo $C &&
347         cat >expected <<-EOF &&
348         fatal: cannot lock ref $Q$prefix/foo$Q: is at $C but expected $D
349         EOF
350         printf "%s\n" "update $prefix/foo $E $D" |
351         test_must_fail git update-ref --stdin 2>output.err &&
352         test_cmp expected output.err
353 '
354
355 test_expect_success 'existing old value blocks create' '
356         prefix=refs/existing-create &&
357         git update-ref $prefix/foo $C &&
358         cat >expected <<-EOF &&
359         fatal: cannot lock ref $Q$prefix/foo$Q: reference already exists
360         EOF
361         printf "%s\n" "create $prefix/foo $E" |
362         test_must_fail git update-ref --stdin 2>output.err &&
363         test_cmp expected output.err
364 '
365
366 test_expect_success 'incorrect old value blocks delete' '
367         prefix=refs/incorrect-delete &&
368         git update-ref $prefix/foo $C &&
369         cat >expected <<-EOF &&
370         fatal: cannot lock ref $Q$prefix/foo$Q: is at $C but expected $D
371         EOF
372         printf "%s\n" "delete $prefix/foo $D" |
373         test_must_fail git update-ref --stdin 2>output.err &&
374         test_cmp expected output.err
375 '
376
377 test_expect_success 'missing old value blocks indirect update' '
378         prefix=refs/missing-indirect-update &&
379         git symbolic-ref $prefix/symref $prefix/foo &&
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 $E $D" |
384         test_must_fail git update-ref --stdin 2>output.err &&
385         test_cmp expected output.err
386 '
387
388 test_expect_success 'incorrect old value blocks indirect update' '
389         prefix=refs/incorrect-indirect-update &&
390         git symbolic-ref $prefix/symref $prefix/foo &&
391         git update-ref $prefix/foo $C &&
392         cat >expected <<-EOF &&
393         fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D
394         EOF
395         printf "%s\n" "update $prefix/symref $E $D" |
396         test_must_fail git update-ref --stdin 2>output.err &&
397         test_cmp expected output.err
398 '
399
400 test_expect_success 'existing old value blocks indirect create' '
401         prefix=refs/existing-indirect-create &&
402         git symbolic-ref $prefix/symref $prefix/foo &&
403         git update-ref $prefix/foo $C &&
404         cat >expected <<-EOF &&
405         fatal: cannot lock ref $Q$prefix/symref$Q: reference already exists
406         EOF
407         printf "%s\n" "create $prefix/symref $E" |
408         test_must_fail git update-ref --stdin 2>output.err &&
409         test_cmp expected output.err
410 '
411
412 test_expect_success 'incorrect old value blocks indirect delete' '
413         prefix=refs/incorrect-indirect-delete &&
414         git symbolic-ref $prefix/symref $prefix/foo &&
415         git update-ref $prefix/foo $C &&
416         cat >expected <<-EOF &&
417         fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D
418         EOF
419         printf "%s\n" "delete $prefix/symref $D" |
420         test_must_fail git update-ref --stdin 2>output.err &&
421         test_cmp expected output.err
422 '
423
424 test_expect_success 'missing old value blocks indirect no-deref update' '
425         prefix=refs/missing-noderef-update &&
426         git symbolic-ref $prefix/symref $prefix/foo &&
427         cat >expected <<-EOF &&
428         fatal: cannot lock ref $Q$prefix/symref$Q: reference is missing but expected $D
429         EOF
430         printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
431         test_must_fail git update-ref --stdin 2>output.err &&
432         test_cmp expected output.err
433 '
434
435 test_expect_success 'incorrect old value blocks indirect no-deref update' '
436         prefix=refs/incorrect-noderef-update &&
437         git symbolic-ref $prefix/symref $prefix/foo &&
438         git update-ref $prefix/foo $C &&
439         cat >expected <<-EOF &&
440         fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D
441         EOF
442         printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
443         test_must_fail git update-ref --stdin 2>output.err &&
444         test_cmp expected output.err
445 '
446
447 test_expect_success 'existing old value blocks indirect no-deref create' '
448         prefix=refs/existing-noderef-create &&
449         git symbolic-ref $prefix/symref $prefix/foo &&
450         git update-ref $prefix/foo $C &&
451         cat >expected <<-EOF &&
452         fatal: cannot lock ref $Q$prefix/symref$Q: reference already exists
453         EOF
454         printf "%s\n" "option no-deref" "create $prefix/symref $E" |
455         test_must_fail git update-ref --stdin 2>output.err &&
456         test_cmp expected output.err
457 '
458
459 test_expect_success 'incorrect old value blocks indirect no-deref delete' '
460         prefix=refs/incorrect-noderef-delete &&
461         git symbolic-ref $prefix/symref $prefix/foo &&
462         git update-ref $prefix/foo $C &&
463         cat >expected <<-EOF &&
464         fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D
465         EOF
466         printf "%s\n" "option no-deref" "delete $prefix/symref $D" |
467         test_must_fail git update-ref --stdin 2>output.err &&
468         test_cmp expected output.err
469 '
470
471 test_expect_success 'non-empty directory blocks create' '
472         prefix=refs/ne-create &&
473         mkdir -p .git/$prefix/foo/bar &&
474         : >.git/$prefix/foo/bar/baz.lock &&
475         test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" &&
476         cat >expected <<-EOF &&
477         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
478         EOF
479         printf "%s\n" "update $prefix/foo $C" |
480         test_must_fail git update-ref --stdin 2>output.err &&
481         test_cmp expected output.err &&
482         cat >expected <<-EOF &&
483         fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q
484         EOF
485         printf "%s\n" "update $prefix/foo $D $C" |
486         test_must_fail git update-ref --stdin 2>output.err &&
487         test_cmp expected output.err
488 '
489
490 test_expect_success 'broken reference blocks create' '
491         prefix=refs/broken-create &&
492         mkdir -p .git/$prefix &&
493         echo "gobbledigook" >.git/$prefix/foo &&
494         test_when_finished "rm -f .git/$prefix/foo" &&
495         cat >expected <<-EOF &&
496         fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken
497         EOF
498         printf "%s\n" "update $prefix/foo $C" |
499         test_must_fail git update-ref --stdin 2>output.err &&
500         test_cmp expected output.err &&
501         cat >expected <<-EOF &&
502         fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken
503         EOF
504         printf "%s\n" "update $prefix/foo $D $C" |
505         test_must_fail git update-ref --stdin 2>output.err &&
506         test_cmp expected output.err
507 '
508
509 test_expect_success 'non-empty directory blocks indirect create' '
510         prefix=refs/ne-indirect-create &&
511         git symbolic-ref $prefix/symref $prefix/foo &&
512         mkdir -p .git/$prefix/foo/bar &&
513         : >.git/$prefix/foo/bar/baz.lock &&
514         test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" &&
515         cat >expected <<-EOF &&
516         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
517         EOF
518         printf "%s\n" "update $prefix/symref $C" |
519         test_must_fail git update-ref --stdin 2>output.err &&
520         test_cmp expected output.err &&
521         cat >expected <<-EOF &&
522         fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q
523         EOF
524         printf "%s\n" "update $prefix/symref $D $C" |
525         test_must_fail git update-ref --stdin 2>output.err &&
526         test_cmp expected output.err
527 '
528
529 test_expect_success 'broken reference blocks indirect create' '
530         prefix=refs/broken-indirect-create &&
531         git symbolic-ref $prefix/symref $prefix/foo &&
532         echo "gobbledigook" >.git/$prefix/foo &&
533         test_when_finished "rm -f .git/$prefix/foo" &&
534         cat >expected <<-EOF &&
535         fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken
536         EOF
537         printf "%s\n" "update $prefix/symref $C" |
538         test_must_fail git update-ref --stdin 2>output.err &&
539         test_cmp expected output.err &&
540         cat >expected <<-EOF &&
541         fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken
542         EOF
543         printf "%s\n" "update $prefix/symref $D $C" |
544         test_must_fail git update-ref --stdin 2>output.err &&
545         test_cmp expected output.err
546 '
547
548 test_expect_success 'no bogus intermediate values during delete' '
549         prefix=refs/slow-transaction &&
550         # Set up a reference with differing loose and packed versions:
551         git update-ref $prefix/foo $C &&
552         git pack-refs --all &&
553         git update-ref $prefix/foo $D &&
554         git for-each-ref $prefix >unchanged &&
555         # Now try to update the reference, but hold the `packed-refs` lock
556         # for a while to see what happens while the process is blocked:
557         : >.git/packed-refs.lock &&
558         test_when_finished "rm -f .git/packed-refs.lock" &&
559         {
560                 # Note: the following command is intentionally run in the
561                 # background. We increase the timeout so that `update-ref`
562                 # attempts to acquire the `packed-refs` lock for much longer
563                 # than it takes for us to do the check then delete it:
564                 git -c core.packedrefstimeout=30000 update-ref -d $prefix/foo &
565         } &&
566         pid2=$! &&
567         # Give update-ref plenty of time to get to the point where it tries
568         # to lock packed-refs:
569         sleep 1 &&
570         # Make sure that update-ref did not complete despite the lock:
571         kill -0 $pid2 &&
572         # Verify that the reference still has its old value:
573         sha1=$(git rev-parse --verify --quiet $prefix/foo || echo undefined) &&
574         case "$sha1" in
575         $D)
576                 # This is what we hope for; it means that nothing
577                 # user-visible has changed yet.
578                 : ;;
579         undefined)
580                 # This is not correct; it means the deletion has happened
581                 # already even though update-ref should not have been
582                 # able to acquire the lock yet.
583                 echo "$prefix/foo deleted prematurely" &&
584                 break
585                 ;;
586         $C)
587                 # This value should never be seen. Probably the loose
588                 # reference has been deleted but the packed reference
589                 # is still there:
590                 echo "$prefix/foo incorrectly observed to be C" &&
591                 break
592                 ;;
593         *)
594                 # WTF?
595                 echo "unexpected value observed for $prefix/foo: $sha1" &&
596                 break
597                 ;;
598         esac >out &&
599         rm -f .git/packed-refs.lock &&
600         wait $pid2 &&
601         test_must_be_empty out &&
602         test_must_fail git rev-parse --verify --quiet $prefix/foo
603 '
604
605 test_expect_success 'delete fails cleanly if packed-refs file is locked' '
606         prefix=refs/locked-packed-refs &&
607         # Set up a reference with differing loose and packed versions:
608         git update-ref $prefix/foo $C &&
609         git pack-refs --all &&
610         git update-ref $prefix/foo $D &&
611         git for-each-ref $prefix >unchanged &&
612         # Now try to delete it while the `packed-refs` lock is held:
613         : >.git/packed-refs.lock &&
614         test_when_finished "rm -f .git/packed-refs.lock" &&
615         test_must_fail git update-ref -d $prefix/foo >out 2>err &&
616         git for-each-ref $prefix >actual &&
617         test_i18ngrep "Unable to create $Q.*packed-refs.lock$Q: " err &&
618         test_cmp unchanged actual
619 '
620
621 test_expect_success 'delete fails cleanly if packed-refs.new write fails' '
622         # Setup and expectations are similar to the test above.
623         prefix=refs/failed-packed-refs &&
624         git update-ref $prefix/foo $C &&
625         git pack-refs --all &&
626         git update-ref $prefix/foo $D &&
627         git for-each-ref $prefix >unchanged &&
628         # This should not happen in practice, but it is an easy way to get a
629         # reliable error (we open with create_tempfile(), which uses O_EXCL).
630         : >.git/packed-refs.new &&
631         test_when_finished "rm -f .git/packed-refs.new" &&
632         test_must_fail git update-ref -d $prefix/foo &&
633         git for-each-ref $prefix >actual &&
634         test_cmp unchanged actual
635 '
636
637 test_done