summaryrefslogtreecommitdiffstats
path: root/t/t2030-unresolve-info.sh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xt/t2030-unresolve-info.sh305
1 files changed, 305 insertions, 0 deletions
diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh
new file mode 100755
index 0000000..be3fcdd
--- /dev/null
+++ b/t/t2030-unresolve-info.sh
@@ -0,0 +1,305 @@
+#!/bin/sh
+
+test_description='undoing resolution'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+check_resolve_undo () {
+ msg=$1
+ shift
+ while case $# in
+ 0) break ;;
+ 1|2|3) die "Bug in check-resolve-undo test" ;;
+ esac
+ do
+ path=$1
+ shift
+ for stage in 1 2 3
+ do
+ sha1=$1
+ shift
+ case "$sha1" in
+ '') continue ;;
+ esac
+ sha1=$(git rev-parse --verify "$sha1")
+ printf "100644 %s %s\t%s\n" $sha1 $stage $path
+ done
+ done >"$msg.expect" &&
+ git ls-files --resolve-undo >"$msg.actual" &&
+ test_cmp "$msg.expect" "$msg.actual"
+}
+
+prime_resolve_undo () {
+ git reset --hard &&
+ git checkout second^0 &&
+ test_tick &&
+ test_must_fail git merge third^0 &&
+ check_resolve_undo empty &&
+
+ # how should the conflict be resolved?
+ case "$1" in
+ remove)
+ rm -f file/le && git rm fi/le
+ ;;
+ *) # modify
+ echo different >fi/le && git add fi/le
+ ;;
+ esac
+ check_resolve_undo recorded fi/le initial:fi/le second:fi/le third:fi/le
+}
+
+test_expect_success setup '
+ mkdir fi &&
+ printf "a\0a" >binary &&
+ git add binary &&
+ test_commit initial fi/le first &&
+ git branch side &&
+ git branch another &&
+ printf "a\0b" >binary &&
+ git add binary &&
+ test_commit second fi/le second &&
+ git checkout side &&
+ test_commit third fi/le third &&
+ git branch add-add &&
+ git checkout another &&
+ test_commit fourth fi/le fourth &&
+ git checkout add-add &&
+ test_commit fifth add-differently &&
+ git checkout main
+'
+
+test_expect_success 'add records switch clears' '
+ prime_resolve_undo &&
+ test_tick &&
+ git commit -m merged &&
+ echo committing keeps &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+ git checkout second^0 &&
+ echo switching clears &&
+ check_resolve_undo cleared
+'
+
+test_expect_success 'rm records reset clears' '
+ prime_resolve_undo &&
+ test_tick &&
+ git commit -m merged &&
+ echo committing keeps &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+
+ echo merge clears upfront &&
+ test_must_fail git merge fourth^0 &&
+ check_resolve_undo nuked &&
+
+ git rm -f fi/le &&
+ echo resolving records &&
+ check_resolve_undo recorded fi/le initial:fi/le HEAD:fi/le fourth:fi/le &&
+
+ git reset --hard &&
+ echo resetting discards &&
+ check_resolve_undo discarded
+'
+
+test_expect_success 'plumbing clears' '
+ prime_resolve_undo &&
+ test_tick &&
+ git commit -m merged &&
+ echo committing keeps &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+
+ echo plumbing clear &&
+ git update-index --clear-resolve-undo &&
+ check_resolve_undo cleared
+'
+
+test_expect_success 'add records checkout -m undoes' '
+ prime_resolve_undo &&
+ git diff HEAD &&
+ git checkout --conflict=merge fi/le &&
+ echo checkout used the record and removed it &&
+ check_resolve_undo removed &&
+ echo the index and the work tree is unmerged again &&
+ git diff >actual &&
+ grep "^++<<<<<<<" actual
+'
+
+test_expect_success 'unmerge with plumbing' '
+ prime_resolve_undo &&
+ git update-index --unresolve fi/le &&
+ git ls-files --resolve-undo fi/le >actual &&
+ test_must_be_empty actual &&
+ git ls-files -u >actual &&
+ test_line_count = 3 actual
+'
+
+test_expect_success 'unmerge can be done even after committing' '
+ prime_resolve_undo &&
+ git commit -m "record to nuke MERGE_HEAD" &&
+ git update-index --unresolve fi/le &&
+ git ls-files --resolve-undo fi/le >actual &&
+ test_must_be_empty actual &&
+ git ls-files -u >actual &&
+ test_line_count = 3 actual
+'
+
+test_expect_success 'unmerge removal' '
+ prime_resolve_undo remove &&
+ git update-index --unresolve fi/le &&
+ git ls-files --resolve-undo fi/le >actual &&
+ test_must_be_empty actual &&
+ git ls-files -u >actual &&
+ test_line_count = 3 actual
+'
+
+test_expect_success 'unmerge removal after committing' '
+ prime_resolve_undo remove &&
+ git commit -m "record to nuke MERGE_HEAD" &&
+ git update-index --unresolve fi/le &&
+ git ls-files --resolve-undo fi/le >actual &&
+ test_must_be_empty actual &&
+ git ls-files -u >actual &&
+ test_line_count = 3 actual
+'
+
+test_expect_success 'rerere and rerere forget' '
+ mkdir .git/rr-cache &&
+ prime_resolve_undo &&
+ echo record the resolution &&
+ git rerere &&
+ rerere_id=$(cd .git/rr-cache && echo */postimage) &&
+ rerere_id=${rerere_id%/postimage} &&
+ test -f .git/rr-cache/$rerere_id/postimage &&
+ git checkout -m fi/le &&
+ echo resurrect the conflict &&
+ grep "^=======" fi/le &&
+ echo reresolve the conflict &&
+ git rerere &&
+ test "z$(cat fi/le)" = zdifferent &&
+ echo register the resolution again &&
+ git add fi/le &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+ test -z "$(git ls-files -u)" &&
+ git rerere forget fi/le &&
+ ! test -f .git/rr-cache/$rerere_id/postimage &&
+ tr "\0" "\n" <.git/MERGE_RR >actual &&
+ echo "$rerere_id fi/le" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rerere and rerere forget (subdirectory)' '
+ rm -fr .git/rr-cache &&
+ mkdir .git/rr-cache &&
+ prime_resolve_undo &&
+ echo record the resolution &&
+ (cd fi && git rerere) &&
+ rerere_id=$(cd .git/rr-cache && echo */postimage) &&
+ rerere_id=${rerere_id%/postimage} &&
+ test -f .git/rr-cache/$rerere_id/postimage &&
+ (cd fi && git checkout -m le) &&
+ echo resurrect the conflict &&
+ grep "^=======" fi/le &&
+ echo reresolve the conflict &&
+ (cd fi && git rerere) &&
+ test "z$(cat fi/le)" = zdifferent &&
+ echo register the resolution again &&
+ (cd fi && git add le) &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+ test -z "$(git ls-files -u)" &&
+ (cd fi && git rerere forget le) &&
+ ! test -f .git/rr-cache/$rerere_id/postimage &&
+ tr "\0" "\n" <.git/MERGE_RR >actual &&
+ echo "$rerere_id fi/le" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rerere forget (binary)' '
+ git checkout -f side &&
+ test_commit --printf binary binary "a\0c" &&
+ test_must_fail git merge second &&
+ git rerere forget binary
+'
+
+test_expect_success 'rerere forget (add-add conflict)' '
+ git checkout -f main &&
+ echo main >add-differently &&
+ git add add-differently &&
+ git commit -m "add differently" &&
+ test_must_fail git merge fifth &&
+ git rerere forget add-differently 2>actual &&
+ test_grep "no remembered" actual
+'
+
+test_expect_success 'resolve-undo keeps blobs from gc' '
+ git checkout -f main &&
+
+ # First make sure we do not have any cruft left in the object store
+ git repack -a -d &&
+ git prune --expire=now &&
+ git prune-packed &&
+ git gc --prune=now &&
+ git fsck --unreachable >cruft &&
+ test_must_be_empty cruft &&
+
+ # Now add three otherwise unreferenced blob objects to the index
+ git reset --hard &&
+ B1=$(echo "resolve undo test data 1" | git hash-object -w --stdin) &&
+ B2=$(echo "resolve undo test data 2" | git hash-object -w --stdin) &&
+ B3=$(echo "resolve undo test data 3" | git hash-object -w --stdin) &&
+ git update-index --add --index-info <<-EOF &&
+ 100644 $B1 1 frotz
+ 100644 $B2 2 frotz
+ 100644 $B3 3 frotz
+ EOF
+
+ # These three blob objects are reachable (only) from the index
+ git fsck --unreachable >cruft &&
+ test_must_be_empty cruft &&
+ # and they should be protected from GC
+ git gc --prune=now &&
+ git cat-file -e $B1 &&
+ git cat-file -e $B2 &&
+ git cat-file -e $B3 &&
+
+ # Now resolve the conflicted path
+ B0=$(echo "resolve undo test data 0" | git hash-object -w --stdin) &&
+ git update-index --add --cacheinfo 100644,$B0,frotz &&
+
+ # These three blob objects are now reachable only from the resolve-undo
+ git fsck --unreachable >cruft &&
+ test_must_be_empty cruft &&
+
+ # and they should survive GC
+ git gc --prune=now &&
+ git cat-file -e $B0 &&
+ git cat-file -e $B1 &&
+ git cat-file -e $B2 &&
+ git cat-file -e $B3 &&
+
+ # Now we switch away, which nukes resolve-undo, and
+ # blobs B0..B3 would become dangling. fsck should
+ # notice that they are now unreachable.
+ git checkout -f side &&
+ git fsck --unreachable >cruft &&
+ sort cruft >actual &&
+ sort <<-EOF >expect &&
+ unreachable blob $B0
+ unreachable blob $B1
+ unreachable blob $B2
+ unreachable blob $B3
+ EOF
+ test_cmp expect actual &&
+
+ # And they should go away when gc runs.
+ git gc --prune=now &&
+ git fsck --unreachable >cruft &&
+ test_must_be_empty cruft &&
+
+ test_must_fail git cat-file -e $B0 &&
+ test_must_fail git cat-file -e $B1 &&
+ test_must_fail git cat-file -e $B2 &&
+ test_must_fail git cat-file -e $B3
+'
+
+test_done