Git fork
1#!/bin/sh
2
3test_description='Test git update-ref error handling'
4
5. ./test-lib.sh
6
7# Create some references, perhaps run pack-refs --all, then try to
8# create some more references. Ensure that the second creation fails
9# with the correct error message.
10# Usage: test_update_rejected <before> <pack> <create> <error>
11# <before> is a ws-separated list of refs to create before the test
12# <pack> (true or false) tells whether to pack the refs before the test
13# <create> is a list of variables to attempt creating
14# <error> is a string to look for in the stderr of update-ref.
15# All references are created in the namespace specified by the current
16# value of $prefix.
17test_update_rejected () {
18 before="$1" &&
19 pack="$2" &&
20 create="$3" &&
21 error="$4" &&
22 printf "create $prefix/%s $C\n" $before |
23 git update-ref --stdin &&
24 git for-each-ref $prefix >unchanged &&
25 if $pack
26 then
27 git pack-refs --all
28 fi &&
29 printf "create $prefix/%s $C\n" $create >input &&
30 test_must_fail git update-ref --stdin <input 2>output.err &&
31 test_grep -F "$error" output.err &&
32 git for-each-ref $prefix >actual &&
33 test_cmp unchanged actual
34}
35
36# Test adding and deleting D/F-conflicting references in a single
37# transaction.
38df_test() {
39 prefix="$1"
40 pack=: symadd=false symdel=false add_del=false addref= delref=
41 shift
42 while test $# -gt 0
43 do
44 case "$1" in
45 --pack)
46 pack="git pack-refs --all"
47 shift
48 ;;
49 --sym-add)
50 # Perform the add via a symbolic reference
51 symadd=true
52 shift
53 ;;
54 --sym-del)
55 # Perform the del via a symbolic reference
56 symdel=true
57 shift
58 ;;
59 --del-add)
60 # Delete first reference then add second
61 add_del=false
62 delref="$prefix/r/$2"
63 addref="$prefix/r/$3"
64 shift 3
65 ;;
66 --add-del)
67 # Add first reference then delete second
68 add_del=true
69 addref="$prefix/r/$2"
70 delref="$prefix/r/$3"
71 shift 3
72 ;;
73 *)
74 echo 1>&2 "Extra args to df_test: $*"
75 return 1
76 ;;
77 esac
78 done
79 git update-ref "$delref" $C &&
80 if $symadd
81 then
82 addname="$prefix/s/symadd" &&
83 git symbolic-ref "$addname" "$addref"
84 else
85 addname="$addref"
86 fi &&
87 if $symdel
88 then
89 delname="$prefix/s/symdel" &&
90 git symbolic-ref "$delname" "$delref"
91 else
92 delname="$delref"
93 fi &&
94 $pack &&
95 if $add_del
96 then
97 printf "%s\n" "create $addname $D" "delete $delname"
98 else
99 printf "%s\n" "delete $delname" "create $addname $D"
100 fi >commands &&
101 test_must_fail git update-ref --stdin <commands 2>output.err &&
102 grep -E "fatal:( cannot lock ref '$addname':)? '$delref' exists; cannot create '$addref'" output.err &&
103 printf "%s\n" "$C $delref" >expected-refs &&
104 git for-each-ref --format="%(objectname) %(refname)" $prefix/r >actual-refs &&
105 test_cmp expected-refs actual-refs
106}
107
108test_expect_success 'setup' - <<\EOT
109
110 git commit --allow-empty -m Initial &&
111 C=$(git rev-parse HEAD) &&
112 git commit --allow-empty -m Second &&
113 D=$(git rev-parse HEAD) &&
114 git commit --allow-empty -m Third &&
115 E=$(git rev-parse HEAD)
116EOT
117
118test_expect_success 'existing loose ref is a simple prefix of new' - <<\EOT
119
120 prefix=refs/1l &&
121 test_update_rejected "a c e" false "b c/x d" \
122 "'$prefix/c' exists; cannot create '$prefix/c/x'"
123
124EOT
125
126test_expect_success 'existing packed ref is a simple prefix of new' - <<\EOT
127
128 prefix=refs/1p &&
129 test_update_rejected "a c e" true "b c/x d" \
130 "'$prefix/c' exists; cannot create '$prefix/c/x'"
131
132EOT
133
134test_expect_success 'existing loose ref is a deeper prefix of new' - <<\EOT
135
136 prefix=refs/2l &&
137 test_update_rejected "a c e" false "b c/x/y d" \
138 "'$prefix/c' exists; cannot create '$prefix/c/x/y'"
139
140EOT
141
142test_expect_success 'existing packed ref is a deeper prefix of new' - <<\EOT
143
144 prefix=refs/2p &&
145 test_update_rejected "a c e" true "b c/x/y d" \
146 "'$prefix/c' exists; cannot create '$prefix/c/x/y'"
147
148EOT
149
150test_expect_success 'new ref is a simple prefix of existing loose' - <<\EOT
151
152 prefix=refs/3l &&
153 test_update_rejected "a c/x e" false "b c d" \
154 "'$prefix/c/x' exists; cannot create '$prefix/c'"
155
156EOT
157
158test_expect_success 'new ref is a simple prefix of existing packed' - <<\EOT
159
160 prefix=refs/3p &&
161 test_update_rejected "a c/x e" true "b c d" \
162 "'$prefix/c/x' exists; cannot create '$prefix/c'"
163
164EOT
165
166test_expect_success 'new ref is a deeper prefix of existing loose' - <<\EOT
167
168 prefix=refs/4l &&
169 test_update_rejected "a c/x/y e" false "b c d" \
170 "'$prefix/c/x/y' exists; cannot create '$prefix/c'"
171
172EOT
173
174test_expect_success 'new ref is a deeper prefix of existing packed' - <<\EOT
175
176 prefix=refs/4p &&
177 test_update_rejected "a c/x/y e" true "b c d" \
178 "'$prefix/c/x/y' exists; cannot create '$prefix/c'"
179
180EOT
181
182test_expect_success 'one new ref is a simple prefix of another' - <<\EOT
183
184 prefix=refs/5 &&
185 test_update_rejected "a e" false "b c c/x d" \
186 "cannot process '$prefix/c' and '$prefix/c/x' at the same time"
187
188EOT
189
190test_expect_success 'D/F conflict prevents add long + delete short' - <<\EOT
191 df_test refs/df-al-ds --add-del foo/bar foo
192EOT
193
194test_expect_success 'D/F conflict prevents add short + delete long' - <<\EOT
195 df_test refs/df-as-dl --add-del foo foo/bar
196EOT
197
198test_expect_success 'D/F conflict prevents delete long + add short' - <<\EOT
199 df_test refs/df-dl-as --del-add foo/bar foo
200EOT
201
202test_expect_success 'D/F conflict prevents delete short + add long' - <<\EOT
203 df_test refs/df-ds-al --del-add foo foo/bar
204EOT
205
206test_expect_success 'D/F conflict prevents add long + delete short packed' - <<\EOT
207 df_test refs/df-al-dsp --pack --add-del foo/bar foo
208EOT
209
210test_expect_success 'D/F conflict prevents add short + delete long packed' - <<\EOT
211 df_test refs/df-as-dlp --pack --add-del foo foo/bar
212EOT
213
214test_expect_success 'D/F conflict prevents delete long packed + add short' - <<\EOT
215 df_test refs/df-dlp-as --pack --del-add foo/bar foo
216EOT
217
218test_expect_success 'D/F conflict prevents delete short packed + add long' - <<\EOT
219 df_test refs/df-dsp-al --pack --del-add foo foo/bar
220EOT
221
222# Try some combinations involving symbolic refs...
223
224test_expect_success 'D/F conflict prevents indirect add long + delete short' - <<\EOT
225 df_test refs/df-ial-ds --sym-add --add-del foo/bar foo
226EOT
227
228test_expect_success 'D/F conflict prevents indirect add long + indirect delete short' - <<\EOT
229 df_test refs/df-ial-ids --sym-add --sym-del --add-del foo/bar foo
230EOT
231
232test_expect_success 'D/F conflict prevents indirect add short + indirect delete long' - <<\EOT
233 df_test refs/df-ias-idl --sym-add --sym-del --add-del foo foo/bar
234EOT
235
236test_expect_success 'D/F conflict prevents indirect delete long + indirect add short' - <<\EOT
237 df_test refs/df-idl-ias --sym-add --sym-del --del-add foo/bar foo
238EOT
239
240test_expect_success 'D/F conflict prevents indirect add long + delete short packed' - <<\EOT
241 df_test refs/df-ial-dsp --sym-add --pack --add-del foo/bar foo
242EOT
243
244test_expect_success 'D/F conflict prevents indirect add long + indirect delete short packed' - <<\EOT
245 df_test refs/df-ial-idsp --sym-add --sym-del --pack --add-del foo/bar foo
246EOT
247
248test_expect_success 'D/F conflict prevents add long + indirect delete short packed' - <<\EOT
249 df_test refs/df-al-idsp --sym-del --pack --add-del foo/bar foo
250EOT
251
252test_expect_success 'D/F conflict prevents indirect delete long packed + indirect add short' - <<\EOT
253 df_test refs/df-idlp-ias --sym-add --sym-del --pack --del-add foo/bar foo
254EOT
255
256# Test various errors when reading the old values of references...
257
258test_expect_success 'missing old value blocks update' - <<\EOT
259 prefix=refs/missing-update &&
260 cat >expected <<-EOF &&
261 fatal: cannot lock ref '$prefix/foo': unable to resolve reference '$prefix/foo'
262 EOF
263 printf "%s\n" "update $prefix/foo $E $D" |
264 test_must_fail git update-ref --stdin 2>output.err &&
265 test_cmp expected output.err
266EOT
267
268test_expect_success 'incorrect old value blocks update' - <<\EOT
269 prefix=refs/incorrect-update &&
270 git update-ref $prefix/foo $C &&
271 cat >expected <<-EOF &&
272 fatal: cannot lock ref '$prefix/foo': is at $C but expected $D
273 EOF
274 printf "%s\n" "update $prefix/foo $E $D" |
275 test_must_fail git update-ref --stdin 2>output.err &&
276 test_cmp expected output.err
277EOT
278
279test_expect_success 'existing old value blocks create' - <<\EOT
280 prefix=refs/existing-create &&
281 git update-ref $prefix/foo $C &&
282 cat >expected <<-EOF &&
283 fatal: cannot lock ref '$prefix/foo': reference already exists
284 EOF
285 printf "%s\n" "create $prefix/foo $E" |
286 test_must_fail git update-ref --stdin 2>output.err &&
287 test_cmp expected output.err
288EOT
289
290test_expect_success 'incorrect old value blocks delete' - <<\EOT
291 prefix=refs/incorrect-delete &&
292 git update-ref $prefix/foo $C &&
293 cat >expected <<-EOF &&
294 fatal: cannot lock ref '$prefix/foo': is at $C but expected $D
295 EOF
296 printf "%s\n" "delete $prefix/foo $D" |
297 test_must_fail git update-ref --stdin 2>output.err &&
298 test_cmp expected output.err
299EOT
300
301test_expect_success 'missing old value blocks indirect update' - <<\EOT
302 prefix=refs/missing-indirect-update &&
303 git symbolic-ref $prefix/symref $prefix/foo &&
304 cat >expected <<-EOF &&
305 fatal: cannot lock ref '$prefix/symref': unable to resolve reference '$prefix/foo'
306 EOF
307 printf "%s\n" "update $prefix/symref $E $D" |
308 test_must_fail git update-ref --stdin 2>output.err &&
309 test_cmp expected output.err
310EOT
311
312test_expect_success 'incorrect old value blocks indirect update' - <<\EOT
313 prefix=refs/incorrect-indirect-update &&
314 git symbolic-ref $prefix/symref $prefix/foo &&
315 git update-ref $prefix/foo $C &&
316 cat >expected <<-EOF &&
317 fatal: cannot lock ref '$prefix/symref': is at $C but expected $D
318 EOF
319 printf "%s\n" "update $prefix/symref $E $D" |
320 test_must_fail git update-ref --stdin 2>output.err &&
321 test_cmp expected output.err
322EOT
323
324test_expect_success 'existing old value blocks indirect create' - <<\EOT
325 prefix=refs/existing-indirect-create &&
326 git symbolic-ref $prefix/symref $prefix/foo &&
327 git update-ref $prefix/foo $C &&
328 cat >expected <<-EOF &&
329 fatal: cannot lock ref '$prefix/symref': reference already exists
330 EOF
331 printf "%s\n" "create $prefix/symref $E" |
332 test_must_fail git update-ref --stdin 2>output.err &&
333 test_cmp expected output.err
334EOT
335
336test_expect_success 'incorrect old value blocks indirect delete' - <<\EOT
337 prefix=refs/incorrect-indirect-delete &&
338 git symbolic-ref $prefix/symref $prefix/foo &&
339 git update-ref $prefix/foo $C &&
340 cat >expected <<-EOF &&
341 fatal: cannot lock ref '$prefix/symref': is at $C but expected $D
342 EOF
343 printf "%s\n" "delete $prefix/symref $D" |
344 test_must_fail git update-ref --stdin 2>output.err &&
345 test_cmp expected output.err
346EOT
347
348test_expect_success 'missing old value blocks indirect no-deref update' - <<\EOT
349 prefix=refs/missing-noderef-update &&
350 git symbolic-ref $prefix/symref $prefix/foo &&
351 cat >expected <<-EOF &&
352 fatal: cannot lock ref '$prefix/symref': reference is missing but expected $D
353 EOF
354 printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
355 test_must_fail git update-ref --stdin 2>output.err &&
356 test_cmp expected output.err
357EOT
358
359test_expect_success 'incorrect old value blocks indirect no-deref update' - <<\EOT
360 prefix=refs/incorrect-noderef-update &&
361 git symbolic-ref $prefix/symref $prefix/foo &&
362 git update-ref $prefix/foo $C &&
363 cat >expected <<-EOF &&
364 fatal: cannot lock ref '$prefix/symref': is at $C but expected $D
365 EOF
366 printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
367 test_must_fail git update-ref --stdin 2>output.err &&
368 test_cmp expected output.err
369EOT
370
371test_expect_success 'existing old value blocks indirect no-deref create' - <<\EOT
372 prefix=refs/existing-noderef-create &&
373 git symbolic-ref $prefix/symref $prefix/foo &&
374 git update-ref $prefix/foo $C &&
375 cat >expected <<-EOF &&
376 fatal: cannot lock ref '$prefix/symref': reference already exists
377 EOF
378 printf "%s\n" "option no-deref" "create $prefix/symref $E" |
379 test_must_fail git update-ref --stdin 2>output.err &&
380 test_cmp expected output.err
381EOT
382
383test_expect_success 'incorrect old value blocks indirect no-deref delete' - <<\EOT
384 prefix=refs/incorrect-noderef-delete &&
385 git symbolic-ref $prefix/symref $prefix/foo &&
386 git update-ref $prefix/foo $C &&
387 cat >expected <<-EOF &&
388 fatal: cannot lock ref '$prefix/symref': is at $C but expected $D
389 EOF
390 printf "%s\n" "option no-deref" "delete $prefix/symref $D" |
391 test_must_fail git update-ref --stdin 2>output.err &&
392 test_cmp expected output.err
393EOT
394
395test_done