Skip to content

Commit 2e9de01

Browse files
mhaggergitster
authored andcommitted
t1404: add a bunch of tests of D/F conflicts
It is currently not allowed, in a single transaction, to add one reference and delete another reference if the two reference names D/F conflict with each other (e.g., like `refs/foo/bar` and `refs/foo`). The reason is that the code would need to take locks $GIT_DIR/refs/foo.lock $GIT_DIR/refs/foo/bar.lock But the latter lock couldn't coexist with the loose reference file $GIT_DIR/refs/foo , because `$GIT_DIR/refs/foo` cannot be both a directory and a file at the same time (hence the name "D/F conflict). Add a bunch of tests that we cleanly reject such transactions. In fact, many of the new tests currently fail. They will be fixed in the next commit along with an explanation. Reported-by: Jeff King <[email protected]> Signed-off-by: Michael Haggerty <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5e00a6c commit 2e9de01

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

t/t1404-update-ref-errors.sh

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,81 @@ test_update_rejected () {
3434

3535
Q="'"
3636

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_cmp 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+
37112
test_expect_success 'setup' '
38113
39114
git commit --allow-empty -m Initial &&
@@ -188,6 +263,72 @@ test_expect_success 'empty directory should not fool 1-arg delete' '
188263
git update-ref --stdin
189264
'
190265

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_failure '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_failure '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_failure '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_failure '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_failure '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_failure '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_failure '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_failure '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+
191332
# Test various errors when reading the old values of references...
192333

193334
test_expect_success 'missing old value blocks update' '

0 commit comments

Comments
 (0)