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