| 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 | |
| 31 | debug_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 | |
| 41 | substring () { |
| 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 | |
| 58 | gen_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 | |
| 266 | gen_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 | |
| 350 | diff_cmd () { |
| 351 | "$merge_tool_path" -R -f -d \ |
| 352 | -c 'wincmd l' -c 'cd $GIT_PREFIX' "$LOCAL" "$REMOTE" |
| 353 | } |
| 354 | |
| 355 | |
| 356 | diff_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 | |
| 375 | merge_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 | |
| 454 | merge_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 | |
| 488 | translate_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 | |
| 503 | exit_code_trustable () { |
| 504 | true |
| 505 | } |
| 506 | |
| 507 | |
| 508 | list_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 | |
| 531 | run_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 | } |