mirror of
https://github.com/git/git.git
synced 2024-12-12 03:14:11 +08:00
f19b916535
merge_submodule() stores errors using path_msg(), whereas other call sites make use of the error() function. This is inconsistent, and moving towards path_msg() seems more friendly for libification efforts since it will allow the caller to determine whether the error messages need to be printed. Note that this deferred handling of error messages changes the error message in a recursive merge from error: failed to execute internal merge to From inner merge: error: failed to execute internal merge which provides a little more information about the error which may be useful. Since the recursive merge strategy still only shows the older error, we had to adjust the new testcase introduced a few commits ago to just search for the older message somewhere in the output. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
305 lines
7.1 KiB
Bash
Executable File
305 lines
7.1 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_expect_code 2 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_expect_success !WINDOWS 'custom merge driver that is killed with a signal on recursive merge' '
|
|
test_when_finished "rm -f output please-abort" &&
|
|
test_when_finished "git checkout side" &&
|
|
|
|
git reset --hard anchor &&
|
|
|
|
git checkout -b base-a main^ &&
|
|
echo base-a >text &&
|
|
git commit -m base-a text &&
|
|
|
|
git checkout -b base-b main^ &&
|
|
echo base-b >text &&
|
|
git commit -m base-b text &&
|
|
|
|
git checkout -b recursive-a base-a &&
|
|
test_must_fail git merge base-b &&
|
|
echo recursive-a >text &&
|
|
git add text &&
|
|
git commit -m recursive-a &&
|
|
|
|
git checkout -b recursive-b base-b &&
|
|
test_must_fail git merge base-a &&
|
|
echo recursive-b >text &&
|
|
git add text &&
|
|
git commit -m recursive-b &&
|
|
|
|
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_expect_code 2 git merge recursive-a 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_done
|