1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
|
#!/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-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 'invalid conflict-marker-size 3a' '
cp .gitattributes .gitattributes.bak &&
echo "text conflict-marker-size=3a" >>.gitattributes &&
test_when_finished "mv .gitattributes.bak .gitattributes" &&
git checkout -m text 2>err &&
test_grep "warning: invalid marker-size ${SQ}3a${SQ}, expecting an integer" err
'
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 &&
test_must_fail git merge bin-main >output &&
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
|