t1404: new tests of ref D/F conflicts within transactions
authorMichael Haggerty <mhagger@alum.mit.edu>
Mon, 11 May 2015 15:25:03 +0000 (17:25 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 11 May 2015 18:50:16 +0000 (11:50 -0700)
Add some tests of reference D/F conflicts (by which I mean the fact
that references like "refs/foo" and "refs/foo/bar" are not allowed to
coexist) in the context of reference transactions.

The test of creating two conflicting references in the same
transaction fails, leaving the transaction half-completed. This will
be fixed later in this patch series.

Please note that the error messages emitted in the case of conflicts
are not very user-friendly. In particular, when the conflicts involve
loose references, then the errors are reported as

error: there are still refs under 'refs/foo'
fatal: Cannot lock the ref 'refs/foo'.

or

error: unable to resolve reference refs/foo/bar: Not a directory
fatal: Cannot lock the ref 'refs/foo/bar'.

This is because lock_ref_sha1_basic() fails while trying to lock the
new reference, before it even gets to the is_refname_available()
check. This situation will also be improved later in this patch
series.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
t/t1404-update-ref-df-conflicts.sh [new file with mode: 0755]
diff --git a/t/t1404-update-ref-df-conflicts.sh b/t/t1404-update-ref-df-conflicts.sh
new file mode 100755 (executable)
index 0000000..2541a23
--- /dev/null
@@ -0,0 +1,107 @@
+#!/bin/sh
+
+test_description='Test git update-ref with D/F conflicts'
+. ./test-lib.sh
+
+test_update_rejected () {
+       prefix="$1" &&
+       before="$2" &&
+       pack="$3" &&
+       create="$4" &&
+       error="$5" &&
+       printf "create $prefix/%s $C\n" $before |
+       git update-ref --stdin &&
+       git for-each-ref $prefix >unchanged &&
+       if $pack
+       then
+               git pack-refs --all
+       fi &&
+       printf "create $prefix/%s $C\n" $create >input &&
+       test_must_fail git update-ref --stdin <input 2>output.err &&
+       grep -F "$error" output.err &&
+       git for-each-ref $prefix >actual &&
+       test_cmp unchanged actual
+}
+
+Q="'"
+
+test_expect_success 'setup' '
+
+       git commit --allow-empty -m Initial &&
+       C=$(git rev-parse HEAD)
+
+'
+
+test_expect_success 'existing loose ref is a simple prefix of new' '
+
+       prefix=refs/1l &&
+       test_update_rejected $prefix "a c e" false "b c/x d" \
+               "unable to resolve reference $prefix/c/x: Not a directory"
+
+'
+
+test_expect_success 'existing packed ref is a simple prefix of new' '
+
+       prefix=refs/1p &&
+       test_update_rejected $prefix "a c e" true "b c/x d" \
+               "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q"
+
+'
+
+test_expect_success 'existing loose ref is a deeper prefix of new' '
+
+       prefix=refs/2l &&
+       test_update_rejected $prefix "a c e" false "b c/x/y d" \
+               "unable to resolve reference $prefix/c/x/y: Not a directory"
+
+'
+
+test_expect_success 'existing packed ref is a deeper prefix of new' '
+
+       prefix=refs/2p &&
+       test_update_rejected $prefix "a c e" true "b c/x/y d" \
+               "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q"
+
+'
+
+test_expect_success 'new ref is a simple prefix of existing loose' '
+
+       prefix=refs/3l &&
+       test_update_rejected $prefix "a c/x e" false "b c d" \
+               "there are still refs under $Q$prefix/c$Q"
+
+'
+
+test_expect_success 'new ref is a simple prefix of existing packed' '
+
+       prefix=refs/3p &&
+       test_update_rejected $prefix "a c/x e" true "b c d" \
+               "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q"
+
+'
+
+test_expect_success 'new ref is a deeper prefix of existing loose' '
+
+       prefix=refs/4l &&
+       test_update_rejected $prefix "a c/x/y e" false "b c d" \
+               "there are still refs under $Q$prefix/c$Q"
+
+'
+
+test_expect_success 'new ref is a deeper prefix of existing packed' '
+
+       prefix=refs/4p &&
+       test_update_rejected $prefix "a c/x/y e" true "b c d" \
+               "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q"
+
+'
+
+test_expect_failure 'one new ref is a simple prefix of another' '
+
+       prefix=refs/5 &&
+       test_update_rejected $prefix "a e" false "b c c/x d" \
+               "cannot process $Q$prefix/c$Q and $Q$prefix/c/x$Q at the same time"
+
+'
+
+test_done