| #!/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 |