mirror of
https://github.com/git/git
synced 2024-11-05 18:59:29 +00:00
81effe9468
Custom merge drivers need access to the names of the revisions they are working on, so that the merge conflict markers they introduce can refer to those revisions. The placeholders '%S', '%X' and '%Y' are introduced to this end. Signed-off-by: Antonin Delpeuch <antonin@delpeuch.eu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
264 lines
6 KiB
Bash
Executable file
264 lines
6 KiB
Bash
Executable file
#!/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
|