Git fork
at 3da4413dbcdb8df021739ca6f20fe4f0bcd1fd3c 657 lines 18 kB view raw
1# This script can be run in two different contexts: 2# 3# - From git, when the user invokes the "vimdiff" merge tool. In this context 4# this script expects the following environment variables (among others) to 5# be defined (which is something "git" takes care of): 6# 7# - $BASE 8# - $LOCAL 9# - $REMOTE 10# - $MERGED 11# 12# In this mode, all this script does is to run the next command: 13# 14# vim -f -c ... $LOCAL $BASE $REMOTE $MERGED 15# 16# ...where the "..." string depends on the value of the 17# "mergetool.vimdiff.layout" configuration variable and is used to open vim 18# with a certain layout of buffers, windows and tabs. 19# 20# - From a script inside the unit tests framework folder ("t" folder) by 21# sourcing this script and then manually calling "run_unit_tests", which 22# will run a battery of unit tests to make sure nothing breaks. 23# In this context this script does not expect any particular environment 24# variable to be set. 25 26 27################################################################################ 28## Internal functions (not meant to be used outside this script) 29################################################################################ 30 31debug_print () { 32 # Send message to stderr if global variable GIT_MERGETOOL_VIMDIFF_DEBUG 33 # is set. 34 35 if test -n "$GIT_MERGETOOL_VIMDIFF_DEBUG" 36 then 37 >&2 echo "$@" 38 fi 39} 40 41substring () { 42 # Return a substring of $1 containing $3 characters starting at 43 # zero-based offset $2. 44 # 45 # Examples: 46 # 47 # substring "Hello world" 0 4 --> "Hell" 48 # substring "Hello world" 3 4 --> "lo w" 49 # substring "Hello world" 3 10 --> "lo world" 50 51 STRING=$1 52 START=$2 53 LEN=$3 54 55 echo "$STRING" | cut -c$(( START + 1 ))-$(( START + $LEN )) 56} 57 58gen_cmd_aux () { 59 # Auxiliary function used from "gen_cmd()". 60 # Read that other function documentation for more details. 61 62 LAYOUT=$1 63 CMD=$2 # This is a second (hidden) argument used for recursion 64 65 debug_print 66 debug_print "LAYOUT : $LAYOUT" 67 debug_print "CMD : $CMD" 68 69 start=0 70 end=${#LAYOUT} 71 72 nested=0 73 nested_min=100 74 75 # Step 1: 76 # 77 # Increase/decrease "start"/"end" indices respectively to get rid of 78 # outer parenthesis. 79 # 80 # Example: 81 # 82 # - BEFORE: (( LOCAL , BASE ) / MERGED ) 83 # - AFTER : ( LOCAL , BASE ) / MERGED 84 85 oldIFS=$IFS 86 IFS=# 87 for c in $(echo "$LAYOUT" | sed 's:.:&#:g') 88 do 89 if test -z "$c" || test "$c" = " " 90 then 91 continue 92 fi 93 94 if test "$c" = "(" 95 then 96 nested=$(( nested + 1 )) 97 continue 98 fi 99 100 if test "$c" = ")" 101 then 102 nested=$(( nested - 1 )) 103 continue 104 fi 105 106 if test "$nested" -lt "$nested_min" 107 then 108 nested_min=$nested 109 fi 110 done 111 IFS=$oldIFS 112 113 debug_print "NESTED MIN: $nested_min" 114 115 while test "$nested_min" -gt "0" 116 do 117 start=$(( start + 1 )) 118 end=$(( end - 1 )) 119 120 start_minus_one=$(( start - 1 )) 121 122 while ! test "$(substring "$LAYOUT" "$start_minus_one" 1)" = "(" 123 do 124 start=$(( start + 1 )) 125 start_minus_one=$(( start_minus_one + 1 )) 126 done 127 128 while ! test "$(substring "$LAYOUT" "$end" 1)" = ")" 129 do 130 end=$(( end - 1 )) 131 done 132 133 nested_min=$(( nested_min - 1 )) 134 done 135 136 debug_print "CLEAN : $(substring "$LAYOUT" "$start" "$(( end - start ))")" 137 138 139 # Step 2: 140 # 141 # Search for all valid separators ("/" or ",") which are *not* 142 # inside parenthesis. Save the index at which each of them makes the 143 # first appearance. 144 145 index_horizontal_split="" 146 index_vertical_split="" 147 148 nested=0 149 i=$(( start - 1 )) 150 151 oldIFS=$IFS 152 IFS=# 153 for c in $(substring "$LAYOUT" "$start" "$(( end - start ))" | sed 's:.:&#:g'); 154 do 155 i=$(( i + 1 )) 156 157 if test "$c" = " " 158 then 159 continue 160 fi 161 162 if test "$c" = "(" 163 then 164 nested=$(( nested + 1 )) 165 continue 166 fi 167 168 if test "$c" = ")" 169 then 170 nested=$(( nested - 1 )) 171 continue 172 fi 173 174 if test "$nested" = 0 175 then 176 current=$c 177 178 if test "$current" = "/" 179 then 180 if test -z "$index_horizontal_split" 181 then 182 index_horizontal_split=$i 183 fi 184 185 elif test "$current" = "," 186 then 187 if test -z "$index_vertical_split" 188 then 189 index_vertical_split=$i 190 fi 191 fi 192 fi 193 done 194 IFS=$oldIFS 195 196 197 # Step 3: 198 # 199 # Process the separator with the highest order of precedence 200 # (";" has the highest precedence and "|" the lowest one). 201 # 202 # By "process" I mean recursively call this function twice: the first 203 # one with the substring at the left of the separator and the second one 204 # with the one at its right. 205 206 terminate="false" 207 208 if ! test -z "$index_horizontal_split" 209 then 210 before="leftabove split" 211 after="wincmd j" 212 index=$index_horizontal_split 213 terminate="true" 214 215 elif ! test -z "$index_vertical_split" 216 then 217 before="leftabove vertical split" 218 after="wincmd l" 219 index=$index_vertical_split 220 terminate="true" 221 fi 222 223 if test "$terminate" = "true" 224 then 225 CMD="$CMD | $before" 226 CMD=$(gen_cmd_aux "$(substring "$LAYOUT" "$start" "$(( index - start ))")" "$CMD") 227 CMD="$CMD | $after" 228 CMD=$(gen_cmd_aux "$(substring "$LAYOUT" "$(( index + 1 ))" "$(( ${#LAYOUT} - index ))")" "$CMD") 229 echo "$CMD" 230 return 231 fi 232 233 234 # Step 4: 235 # 236 # If we reach this point, it means there are no separators and we just 237 # need to print the command to display the specified buffer 238 239 target=$(substring "$LAYOUT" "$start" "$(( end - start ))" | sed 's:[ @();|-]::g') 240 241 if test "$target" = "LOCAL" 242 then 243 CMD="$CMD | 1b" 244 245 elif test "$target" = "BASE" 246 then 247 CMD="$CMD | 2b" 248 249 elif test "$target" = "REMOTE" 250 then 251 CMD="$CMD | 3b" 252 253 elif test "$target" = "MERGED" 254 then 255 CMD="$CMD | 4b" 256 257 else 258 CMD="$CMD | ERROR: >$target<" 259 fi 260 261 echo "$CMD" 262 return 263} 264 265 266gen_cmd () { 267 # This function returns (in global variable FINAL_CMD) the string that 268 # you can use when invoking "vim" (as shown next) to obtain a given 269 # layout: 270 # 271 # $ vim -f $FINAL_CMD "$LOCAL" "$BASE" "$REMOTE" "$MERGED" 272 # 273 # It takes one single argument: a string containing the desired layout 274 # definition. 275 # 276 # The syntax of the "layout definitions" is explained in "Documentation/ 277 # mergetools/vimdiff.adoc" but you can already intuitively understand 278 # how it works by knowing that... 279 # 280 # * "+" means "a new vim tab" 281 # * "/" means "a new vim horizontal split" 282 # * "," means "a new vim vertical split" 283 # 284 # It also returns (in global variable FINAL_TARGET) the name ("LOCAL", 285 # "BASE", "REMOTE" or "MERGED") of the file that is marked with an "@", 286 # or "MERGED" if none of them is. 287 # 288 # Example: 289 # 290 # gen_cmd "@LOCAL , REMOTE" 291 # | 292 # `-> FINAL_CMD == "-c \"echo | leftabove vertical split | 1b | wincmd l | 3b | tabdo windo diffthis\" -c \"tabfirst\"" 293 # FINAL_TARGET == "LOCAL" 294 295 LAYOUT=$1 296 297 298 # Search for a "@" in one of the files identifiers ("LOCAL", "BASE", 299 # "REMOTE", "MERGED"). If not found, use "MERGE" as the default file 300 # where changes will be saved. 301 302 if echo "$LAYOUT" | grep @LOCAL >/dev/null 303 then 304 FINAL_TARGET="LOCAL" 305 elif echo "$LAYOUT" | grep @BASE >/dev/null 306 then 307 FINAL_TARGET="BASE" 308 elif echo "$LAYOUT" | grep @REMOTE >/dev/null 309 then 310 FINAL_TARGET="REMOTE" 311 else 312 FINAL_TARGET="MERGED" 313 fi 314 315 316 # Obtain the first part of vim "-c" option to obtain the desired layout 317 318 CMD= 319 oldIFS=$IFS 320 IFS=+ 321 for tab in $LAYOUT 322 do 323 if test -z "$CMD" 324 then 325 CMD="echo" # vim "nop" operator 326 else 327 CMD="$CMD | tabnew" 328 fi 329 330 # If this is a single window diff with all the buffers 331 if ! echo "$tab" | grep -E ",|/" >/dev/null 332 then 333 CMD="$CMD | silent execute 'bufdo diffthis'" 334 fi 335 336 CMD=$(gen_cmd_aux "$tab" "$CMD") 337 done 338 IFS=$oldIFS 339 340 CMD="$CMD | execute 'tabdo windo diffthis'" 341 342 FINAL_CMD="-c \"set hidden diffopt-=hiddenoff | $CMD | tabfirst\"" 343} 344 345 346################################################################################ 347## API functions (called from "git-mergetool--lib.sh") 348################################################################################ 349 350diff_cmd () { 351 "$merge_tool_path" -R -f -d \ 352 -c 'wincmd l' -c 'cd $GIT_PREFIX' "$LOCAL" "$REMOTE" 353} 354 355 356diff_cmd_help () { 357 TOOL=$1 358 359 case "$TOOL" in 360 nvimdiff*) 361 printf "Use Neovim" 362 ;; 363 gvimdiff*) 364 printf "Use gVim (requires a graphical session)" 365 ;; 366 vimdiff*) 367 printf "Use Vim" 368 ;; 369 esac 370 371 return 0 372} 373 374 375merge_cmd () { 376 TOOL=$1 377 378 layout=$(git config "mergetool.$TOOL.layout") 379 380 # backward compatibility: 381 if test -z "$layout" 382 then 383 layout=$(git config mergetool.vimdiff.layout) 384 fi 385 386 case "$TOOL" in 387 *vimdiff) 388 if test -z "$layout" 389 then 390 # Default layout when none is specified 391 layout="(LOCAL,BASE,REMOTE)/MERGED" 392 fi 393 ;; 394 *vimdiff1) 395 layout="@LOCAL,REMOTE" 396 ;; 397 *vimdiff2) 398 layout="LOCAL,MERGED,REMOTE" 399 ;; 400 *vimdiff3) 401 layout="MERGED" 402 ;; 403 esac 404 405 gen_cmd "$layout" 406 407 debug_print "" 408 debug_print "FINAL CMD : $FINAL_CMD" 409 debug_print "FINAL TAR : $FINAL_TARGET" 410 411 if $base_present 412 then 413 eval '"$merge_tool_path"' \ 414 -f "$FINAL_CMD" '"$LOCAL"' '"$BASE"' '"$REMOTE"' '"$MERGED"' 415 else 416 # If there is no BASE (example: a merge conflict in a new file 417 # with the same name created in both branches which didn't exist 418 # before), close all BASE windows using vim's "quit" command 419 420 FINAL_CMD=$(echo "$FINAL_CMD" | \ 421 sed -e 's:2b:quit:g' -e 's:3b:2b:g' -e 's:4b:3b:g') 422 423 eval '"$merge_tool_path"' \ 424 -f "$FINAL_CMD" '"$LOCAL"' '"$REMOTE"' '"$MERGED"' 425 fi 426 427 ret="$?" 428 429 if test "$ret" -eq 0 430 then 431 case "$FINAL_TARGET" in 432 LOCAL) 433 source_path="$LOCAL" 434 ;; 435 REMOTE) 436 source_path="$REMOTE" 437 ;; 438 MERGED|*) 439 # Do nothing 440 source_path= 441 ;; 442 esac 443 444 if test -n "$source_path" 445 then 446 cp "$source_path" "$MERGED" 447 fi 448 fi 449 450 return "$ret" 451} 452 453 454merge_cmd_help () { 455 TOOL=$1 456 457 case "$TOOL" in 458 nvimdiff*) 459 printf "Use Neovim " 460 ;; 461 gvimdiff*) 462 printf "Use gVim (requires a graphical session) " 463 ;; 464 vimdiff*) 465 printf "Use Vim " 466 ;; 467 esac 468 469 case "$TOOL" in 470 *1) 471 echo "with a 2 panes layout (LOCAL and REMOTE)" 472 ;; 473 *2) 474 echo "with a 3 panes layout (LOCAL, MERGED and REMOTE)" 475 ;; 476 *3) 477 echo "where only the MERGED file is shown" 478 ;; 479 *) 480 echo "with a custom layout (see \`git help mergetool\`'s \`BACKEND SPECIFIC HINTS\` section)" 481 ;; 482 esac 483 484 return 0 485} 486 487 488translate_merge_tool_path () { 489 case "$1" in 490 nvimdiff*) 491 echo nvim 492 ;; 493 gvimdiff*) 494 echo gvim 495 ;; 496 vimdiff*) 497 echo vim 498 ;; 499 esac 500} 501 502 503exit_code_trustable () { 504 true 505} 506 507 508list_tool_variants () { 509 if test "$TOOL_MODE" = "diff" 510 then 511 for prefix in '' g n 512 do 513 echo "${prefix}vimdiff" 514 done 515 else 516 for prefix in '' g n 517 do 518 for suffix in '' 1 2 3 519 do 520 echo "${prefix}vimdiff${suffix}" 521 done 522 done 523 fi 524} 525 526 527################################################################################ 528## Unit tests (called from scripts inside the "t" folder) 529################################################################################ 530 531run_unit_tests () { 532 # Function to make sure that we don't break anything when modifying this 533 # script. 534 535 NUMBER_OF_TEST_CASES=19 536 537 TEST_CASE_01="(LOCAL,BASE,REMOTE)/MERGED" # default behaviour 538 TEST_CASE_02="@LOCAL,REMOTE" # when using vimdiff1 539 TEST_CASE_03="LOCAL,MERGED,REMOTE" # when using vimdiff2 540 TEST_CASE_04="MERGED" # when using vimdiff3 541 TEST_CASE_05="LOCAL/MERGED/REMOTE" 542 TEST_CASE_06="(LOCAL/REMOTE),MERGED" 543 TEST_CASE_07="MERGED,(LOCAL/REMOTE)" 544 TEST_CASE_08="(LOCAL,REMOTE)/MERGED" 545 TEST_CASE_09="MERGED/(LOCAL,REMOTE)" 546 TEST_CASE_10="(LOCAL/BASE/REMOTE),MERGED" 547 TEST_CASE_11="(LOCAL,BASE,REMOTE)/MERGED+BASE,LOCAL+BASE,REMOTE+(LOCAL/BASE/REMOTE),MERGED" 548 TEST_CASE_12="((LOCAL,REMOTE)/BASE),MERGED" 549 TEST_CASE_13="((LOCAL,REMOTE)/BASE),((LOCAL/REMOTE),MERGED)" 550 TEST_CASE_14="BASE,REMOTE+BASE,LOCAL" 551 TEST_CASE_15=" (( (LOCAL , BASE , REMOTE) / MERGED)) +(BASE) , LOCAL+ BASE , REMOTE+ (((LOCAL / BASE / REMOTE)) , MERGED ) " 552 TEST_CASE_16="LOCAL,BASE,REMOTE / MERGED + BASE,LOCAL + BASE,REMOTE + (LOCAL / BASE / REMOTE),MERGED" 553 TEST_CASE_17="(LOCAL,@BASE,REMOTE)/MERGED" 554 TEST_CASE_18="LOCAL,@REMOTE" 555 TEST_CASE_19="@REMOTE" 556 557 EXPECTED_CMD_01="-c \"set hidden diffopt-=hiddenoff | echo | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 2b | wincmd l | 3b | wincmd j | 4b | execute 'tabdo windo diffthis' | tabfirst\"" 558 EXPECTED_CMD_02="-c \"set hidden diffopt-=hiddenoff | echo | leftabove vertical split | 1b | wincmd l | 3b | execute 'tabdo windo diffthis' | tabfirst\"" 559 EXPECTED_CMD_03="-c \"set hidden diffopt-=hiddenoff | echo | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 4b | wincmd l | 3b | execute 'tabdo windo diffthis' | tabfirst\"" 560 EXPECTED_CMD_04="-c \"set hidden diffopt-=hiddenoff | echo | silent execute 'bufdo diffthis' | 4b | execute 'tabdo windo diffthis' | tabfirst\"" 561 EXPECTED_CMD_05="-c \"set hidden diffopt-=hiddenoff | echo | leftabove split | 1b | wincmd j | leftabove split | 4b | wincmd j | 3b | execute 'tabdo windo diffthis' | tabfirst\"" 562 EXPECTED_CMD_06="-c \"set hidden diffopt-=hiddenoff | echo | leftabove vertical split | leftabove split | 1b | wincmd j | 3b | wincmd l | 4b | execute 'tabdo windo diffthis' | tabfirst\"" 563 EXPECTED_CMD_07="-c \"set hidden diffopt-=hiddenoff | echo | leftabove vertical split | 4b | wincmd l | leftabove split | 1b | wincmd j | 3b | execute 'tabdo windo diffthis' | tabfirst\"" 564 EXPECTED_CMD_08="-c \"set hidden diffopt-=hiddenoff | echo | leftabove split | leftabove vertical split | 1b | wincmd l | 3b | wincmd j | 4b | execute 'tabdo windo diffthis' | tabfirst\"" 565 EXPECTED_CMD_09="-c \"set hidden diffopt-=hiddenoff | echo | leftabove split | 4b | wincmd j | leftabove vertical split | 1b | wincmd l | 3b | execute 'tabdo windo diffthis' | tabfirst\"" 566 EXPECTED_CMD_10="-c \"set hidden diffopt-=hiddenoff | echo | leftabove vertical split | leftabove split | 1b | wincmd j | leftabove split | 2b | wincmd j | 3b | wincmd l | 4b | execute 'tabdo windo diffthis' | tabfirst\"" 567 EXPECTED_CMD_11="-c \"set hidden diffopt-=hiddenoff | echo | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnew | leftabove vertical split | 2b | wincmd l | 1b | tabnew | leftabove vertical split | 2b | wincmd l | 3b | tabnew | leftabove vertical split | leftabove split | 1b | wincmd j | leftabove split | 2b | wincmd j | 3b | wincmd l | 4b | execute 'tabdo windo diffthis' | tabfirst\"" 568 EXPECTED_CMD_12="-c \"set hidden diffopt-=hiddenoff | echo | leftabove vertical split | leftabove split | leftabove vertical split | 1b | wincmd l | 3b | wincmd j | 2b | wincmd l | 4b | execute 'tabdo windo diffthis' | tabfirst\"" 569 EXPECTED_CMD_13="-c \"set hidden diffopt-=hiddenoff | echo | leftabove vertical split | leftabove split | leftabove vertical split | 1b | wincmd l | 3b | wincmd j | 2b | wincmd l | leftabove vertical split | leftabove split | 1b | wincmd j | 3b | wincmd l | 4b | execute 'tabdo windo diffthis' | tabfirst\"" 570 EXPECTED_CMD_14="-c \"set hidden diffopt-=hiddenoff | echo | leftabove vertical split | 2b | wincmd l | 3b | tabnew | leftabove vertical split | 2b | wincmd l | 1b | execute 'tabdo windo diffthis' | tabfirst\"" 571 EXPECTED_CMD_15="-c \"set hidden diffopt-=hiddenoff | echo | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnew | leftabove vertical split | 2b | wincmd l | 1b | tabnew | leftabove vertical split | 2b | wincmd l | 3b | tabnew | leftabove vertical split | leftabove split | 1b | wincmd j | leftabove split | 2b | wincmd j | 3b | wincmd l | 4b | execute 'tabdo windo diffthis' | tabfirst\"" 572 EXPECTED_CMD_16="-c \"set hidden diffopt-=hiddenoff | echo | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnew | leftabove vertical split | 2b | wincmd l | 1b | tabnew | leftabove vertical split | 2b | wincmd l | 3b | tabnew | leftabove vertical split | leftabove split | 1b | wincmd j | leftabove split | 2b | wincmd j | 3b | wincmd l | 4b | execute 'tabdo windo diffthis' | tabfirst\"" 573 EXPECTED_CMD_17="-c \"set hidden diffopt-=hiddenoff | echo | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 2b | wincmd l | 3b | wincmd j | 4b | execute 'tabdo windo diffthis' | tabfirst\"" 574 EXPECTED_CMD_18="-c \"set hidden diffopt-=hiddenoff | echo | leftabove vertical split | 1b | wincmd l | 3b | execute 'tabdo windo diffthis' | tabfirst\"" 575 EXPECTED_CMD_19="-c \"set hidden diffopt-=hiddenoff | echo | silent execute 'bufdo diffthis' | 3b | execute 'tabdo windo diffthis' | tabfirst\"" 576 577 EXPECTED_TARGET_01="MERGED" 578 EXPECTED_TARGET_02="LOCAL" 579 EXPECTED_TARGET_03="MERGED" 580 EXPECTED_TARGET_04="MERGED" 581 EXPECTED_TARGET_05="MERGED" 582 EXPECTED_TARGET_06="MERGED" 583 EXPECTED_TARGET_07="MERGED" 584 EXPECTED_TARGET_08="MERGED" 585 EXPECTED_TARGET_09="MERGED" 586 EXPECTED_TARGET_10="MERGED" 587 EXPECTED_TARGET_11="MERGED" 588 EXPECTED_TARGET_12="MERGED" 589 EXPECTED_TARGET_13="MERGED" 590 EXPECTED_TARGET_14="MERGED" 591 EXPECTED_TARGET_15="MERGED" 592 EXPECTED_TARGET_16="MERGED" 593 EXPECTED_TARGET_17="BASE" 594 EXPECTED_TARGET_18="REMOTE" 595 EXPECTED_TARGET_19="REMOTE" 596 597 at_least_one_ko="false" 598 599 for i in $(seq -w 1 99) 600 do 601 if test "$i" -gt $NUMBER_OF_TEST_CASES 602 then 603 break 604 fi 605 606 gen_cmd "$(eval echo \${TEST_CASE_"$i"})" 607 608 if test "$FINAL_CMD" = "$(eval echo \${EXPECTED_CMD_"$i"})" \ 609 && test "$FINAL_TARGET" = "$(eval echo \${EXPECTED_TARGET_"$i"})" 610 then 611 printf "Test Case #%02d: OK\n" "$(echo "$i" | sed 's/^0*//')" 612 else 613 printf "Test Case #%02d: KO !!!!\n" "$(echo "$i" | sed 's/^0*//')" 614 echo " FINAL_CMD : $FINAL_CMD" 615 echo " FINAL_CMD (expected) : $(eval echo \${EXPECTED_CMD_"$i"})" 616 echo " FINAL_TARGET : $FINAL_TARGET" 617 echo " FINAL_TARGET (expected): $(eval echo \${EXPECTED_TARGET_"$i"})" 618 at_least_one_ko="true" 619 fi 620 done 621 622 # verify that `merge_cmd` handles paths with spaces 623 record_parameters () { 624 >actual 625 for arg 626 do 627 echo "$arg" >>actual 628 done 629 } 630 631 base_present=false 632 LOCAL='lo cal' 633 BASE='ba se' 634 REMOTE="' '" 635 MERGED='mer ged' 636 merge_tool_path=record_parameters 637 638 merge_cmd vimdiff || at_least_one_ko=true 639 640 cat >expect <<-\EOF 641 -f 642 -c 643 set hidden diffopt-=hiddenoff | echo | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | quit | wincmd l | 2b | wincmd j | 3b | execute 'tabdo windo diffthis' | tabfirst 644 lo cal 645 ' ' 646 mer ged 647 EOF 648 649 diff -u expect actual || at_least_one_ko=true 650 651 if test "$at_least_one_ko" = "true" 652 then 653 return 255 654 else 655 return 0 656 fi 657}