#!/bin/sh # # Copyright (c) 2007 Junio C Hamano # test_description='per path merge controlled by merge attribute' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' for f in text binary union do echo Initial >$f && git add $f || return 1 done && test_tick && git commit -m Initial && git branch side && for f in text binary union do echo Main >>$f && git add $f || return 1 done && test_tick && git commit -m Main && git checkout side && for f in text binary union do echo Side >>$f && git add $f || return 1 done && test_tick && git commit -m Side && git tag anchor && cat >./custom-merge <<-\EOF && #!/bin/sh orig="$1" ours="$2" theirs="$3" exit="$4" path=$5 orig_name="$6" our_name="$7" their_name="$8" ( echo "orig is $orig" echo "ours is $ours" echo "theirs is $theirs" echo "path is $path" echo "orig_name is $orig_name" echo "our_name is $our_name" echo "their_name is $their_name" echo "=== orig ===" cat "$orig" echo "=== ours ===" cat "$ours" echo "=== theirs ===" cat "$theirs" ) >"$ours+" cat "$ours+" >"$ours" rm -f "$ours+" if test -f ./please-abort then echo >>./please-abort killing myself kill -9 $$ fi exit "$exit" EOF chmod +x ./custom-merge ' test_expect_success merge ' cat >.gitattributes <<-\EOF && binary -merge union merge=union EOF if git merge main then echo Gaah, should have conflicted false else echo Ok, conflicted. fi ' test_expect_success 'check merge result in index' ' git ls-files -u | grep binary && git ls-files -u | grep text && ! (git ls-files -u | grep union) ' test_expect_success 'check merge result in working tree' ' git cat-file -p HEAD:binary >binary-orig && grep "<<<<<<<" text && cmp binary-orig binary && ! grep "<<<<<<<" union && grep Main union && grep Side union ' test_expect_success 'retry the merge with longer context' ' echo text conflict-marker-size=32 >>.gitattributes && git checkout -m text && sed -ne "/^\([<=>]\)\1\1\1*/{ s/ .*$// p }" >actual text && grep ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" actual && grep "================================" actual && grep "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" actual ' test_expect_success 'custom merge backend' ' echo "* merge=union" >.gitattributes && echo "text merge=custom" >>.gitattributes && git reset --hard anchor && git config --replace-all \ merge.custom.driver "./custom-merge %O %A %B 0 %P %S %X %Y" && git config --replace-all \ merge.custom.name "custom merge driver for testing" && git merge main && cmp binary union && sed -e 1,3d text >check-1 && o=$(git unpack-file main^:text) && a=$(git unpack-file side^:text) && b=$(git unpack-file main:text) && base_revid=$(git rev-parse --short main^) && sh -c "./custom-merge $o $a $b 0 text $base_revid HEAD main" && sed -e 1,3d $a >check-2 && cmp check-1 check-2 && rm -f $o $a $b ' test_expect_success 'custom merge backend' ' git reset --hard anchor && git config --replace-all \ merge.custom.driver "./custom-merge %O %A %B 1 %P %S %X %Y" && git config --replace-all \ merge.custom.name "custom merge driver for testing" && if git merge main then echo "Eh? should have conflicted" false else echo "Ok, conflicted" fi && cmp binary union && sed -e 1,3d text >check-1 && o=$(git unpack-file main^:text) && a=$(git unpack-file anchor:text) && b=$(git unpack-file main:text) && base_revid=$(git rev-parse --short main^) && sh -c "./custom-merge $o $a $b 0 text $base_revid HEAD main" && sed -e 1,3d $a >check-2 && cmp check-1 check-2 && sed -e 1,3d -e 4q $a >check-3 && echo "path is text" >expect && cmp expect check-3 && rm -f $o $a $b ' test_expect_success !WINDOWS 'custom merge driver that is killed with a signal' ' test_when_finished "rm -f output please-abort" && git reset --hard anchor && git config --replace-all \ merge.custom.driver "./custom-merge %O %A %B 0 %P %S %X %Y" && git config --replace-all \ merge.custom.name "custom merge driver for testing" && >./please-abort && echo "* merge=custom" >.gitattributes && test_must_fail git merge main 2>err && grep "^error: failed to execute internal merge" err && git ls-files -u >output && git diff --name-only HEAD >>output && test_must_be_empty output ' test_expect_success 'up-to-date merge without common ancestor' ' git init repo1 && git init repo2 && test_tick && ( cd repo1 && >a && git add a && git commit -m initial ) && test_tick && ( cd repo2 && git commit --allow-empty -m initial ) && test_tick && ( cd repo1 && git fetch ../repo2 main && git merge --allow-unrelated-histories FETCH_HEAD ) ' test_expect_success 'custom merge does not lock index' ' git reset --hard anchor && write_script sleep-an-hour.sh <<-\EOF && sleep 3600 & echo $! >sleep.pid EOF test_write_lines >.gitattributes \ "* merge=ours" "text merge=sleep-an-hour" && test_config merge.ours.driver true && test_config merge.sleep-an-hour.driver ./sleep-an-hour.sh && # We are testing that the custom merge driver does not block # index.lock on Windows due to an inherited file handle. # To ensure that the backgrounded process ran sufficiently # long (and has been started in the first place), we do not # ignore the result of the kill command. # By packaging the command in test_when_finished, we get both # the correctness check and the clean-up. test_when_finished "kill \$(cat sleep.pid)" && git merge main ' test_expect_success 'binary files with union attribute' ' git checkout -b bin-main && printf "base\0" >bin.txt && echo "bin.txt merge=union" >.gitattributes && git add bin.txt .gitattributes && git commit -m base && printf "one\0" >bin.txt && git commit -am one && git checkout -b bin-side HEAD^ && printf "two\0" >bin.txt && git commit -am two && if test "$GIT_TEST_MERGE_ALGORITHM" = ort then test_must_fail git merge bin-main >output else test_must_fail git merge bin-main 2>output fi && grep -i "warning.*cannot merge.*HEAD vs. bin-main" output ' test_done