]>
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 | ||
35 | Q="'" | |
36 | ||
2e9de01a MH |
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 && | |
661558f0 | 106 | test_i18ncmp expected-err output.err && |
2e9de01a MH |
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 | ||
433efcad MH |
112 | test_expect_success 'setup' ' |
113 | ||
114 | git commit --allow-empty -m Initial && | |
19dd7d06 MH |
115 | C=$(git rev-parse HEAD) && |
116 | git commit --allow-empty -m Second && | |
c5119dcf MH |
117 | D=$(git rev-parse HEAD) && |
118 | git commit --allow-empty -m Third && | |
119 | E=$(git rev-parse HEAD) | |
433efcad MH |
120 | ' |
121 | ||
122 | test_expect_success 'existing loose ref is a simple prefix of new' ' | |
123 | ||
124 | prefix=refs/1l && | |
0e4b63b5 | 125 | test_update_rejected "a c e" false "b c/x d" \ |
5b2d8d6f | 126 | "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q" |
433efcad MH |
127 | |
128 | ' | |
129 | ||
130 | test_expect_success 'existing packed ref is a simple prefix of new' ' | |
131 | ||
132 | prefix=refs/1p && | |
0e4b63b5 | 133 | test_update_rejected "a c e" true "b c/x d" \ |
433efcad MH |
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 && | |
0e4b63b5 | 141 | test_update_rejected "a c e" false "b c/x/y d" \ |
5b2d8d6f | 142 | "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q" |
433efcad MH |
143 | |
144 | ' | |
145 | ||
146 | test_expect_success 'existing packed ref is a deeper prefix of new' ' | |
147 | ||
148 | prefix=refs/2p && | |
0e4b63b5 | 149 | test_update_rejected "a c e" true "b c/x/y d" \ |
433efcad MH |
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 && | |
0e4b63b5 | 157 | test_update_rejected "a c/x e" false "b c d" \ |
5b2d8d6f | 158 | "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q" |
433efcad MH |
159 | |
160 | ' | |
161 | ||
162 | test_expect_success 'new ref is a simple prefix of existing packed' ' | |
163 | ||
164 | prefix=refs/3p && | |
0e4b63b5 | 165 | test_update_rejected "a c/x e" true "b c d" \ |
433efcad MH |
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 && | |
0e4b63b5 | 173 | test_update_rejected "a c/x/y e" false "b c d" \ |
5b2d8d6f | 174 | "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q" |
433efcad MH |
175 | |
176 | ' | |
177 | ||
178 | test_expect_success 'new ref is a deeper prefix of existing packed' ' | |
179 | ||
180 | prefix=refs/4p && | |
0e4b63b5 | 181 | test_update_rejected "a c/x/y e" true "b c d" \ |
433efcad MH |
182 | "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q" |
183 | ||
184 | ' | |
185 | ||
e911104c | 186 | test_expect_success 'one new ref is a simple prefix of another' ' |
433efcad MH |
187 | |
188 | prefix=refs/5 && | |
0e4b63b5 | 189 | test_update_rejected "a e" false "b c c/x d" \ |
433efcad MH |
190 | "cannot process $Q$prefix/c$Q and $Q$prefix/c/x$Q at the same time" |
191 | ||
192 | ' | |
193 | ||
e167a567 | 194 | test_expect_success 'empty directory should not fool rev-parse' ' |
19dd7d06 MH |
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 | ||
2e9de01a MH |
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 | ||
da5267f1 | 274 | test_expect_success 'D/F conflict prevents delete long + add short' ' |
2e9de01a MH |
275 | df_test refs/df-dl-as --del-add foo/bar foo |
276 | ' | |
277 | ||
da5267f1 | 278 | test_expect_success 'D/F conflict prevents delete short + add long' ' |
2e9de01a MH |
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 | ||
da5267f1 | 290 | test_expect_success 'D/F conflict prevents delete long packed + add short' ' |
2e9de01a MH |
291 | df_test refs/df-dlp-as --pack --del-add foo/bar foo |
292 | ' | |
293 | ||
da5267f1 | 294 | test_expect_success 'D/F conflict prevents delete short packed + add long' ' |
2e9de01a MH |
295 | df_test refs/df-dsp-al --pack --del-add foo foo/bar |
296 | ' | |
297 | ||
298 | # Try some combinations involving symbolic refs... | |
299 | ||
da5267f1 | 300 | test_expect_success 'D/F conflict prevents indirect add long + delete short' ' |
2e9de01a MH |
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 | ||
da5267f1 | 312 | test_expect_success 'D/F conflict prevents indirect delete long + indirect add short' ' |
2e9de01a MH |
313 | df_test refs/df-idl-ias --sym-add --sym-del --del-add foo/bar foo |
314 | ' | |
315 | ||
da5267f1 | 316 | test_expect_success 'D/F conflict prevents indirect add long + delete short packed' ' |
2e9de01a MH |
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 | ||
da5267f1 | 328 | test_expect_success 'D/F conflict prevents indirect delete long packed + indirect add short' ' |
2e9de01a MH |
329 | df_test refs/df-idlp-ias --sym-add --sym-del --pack --del-add foo/bar foo |
330 | ' | |
331 | ||
c5119dcf MH |
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 && | |
e3f51039 | 381 | fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q |
c5119dcf MH |
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 && | |
e3f51039 | 428 | fatal: cannot lock ref $Q$prefix/symref$Q: reference is missing but expected $D |
c5119dcf MH |
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 | ||
e3f51039 | 447 | test_expect_success 'existing old value blocks indirect no-deref create' ' |
c5119dcf MH |
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 && | |
e3f51039 | 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 |
c5119dcf MH |
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 && | |
e3f51039 | 522 | fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q |
c5119dcf MH |
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 && | |
e3f51039 | 535 | fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken |
c5119dcf MH |
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 && | |
e3f51039 | 541 | fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken |
c5119dcf MH |
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 | ||
dc39e099 | 548 | test_expect_success 'no bogus intermediate values during delete' ' |
6a2a7736 MH |
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` | |
377d8459 SG |
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 & | |
6a2a7736 MH |
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 | ||
dc39e099 | 605 | test_expect_success 'delete fails cleanly if packed-refs file is locked' ' |
6a2a7736 MH |
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 && | |
c777cd81 | 617 | test_i18ngrep "Unable to create $Q.*packed-refs.lock$Q: " err && |
6a2a7736 MH |
618 | test_cmp unchanged actual |
619 | ' | |
620 | ||
249e8dc7 JK |
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 | ||
433efcad | 637 | test_done |