t / t1000-read-tree-m-3way.shon commit revision: new rev^-n shorthand for rev^n..rev (8779351)
   1#!/bin/sh
   2#
   3# Copyright (c) 2005 Junio C Hamano
   4#
   5
   6test_description='Three way merge with read-tree -m
   7
   8This test tries three-way merge with read-tree -m
   9
  10There is one ancestor (called O for Original) and two branches A
  11and B derived from it.  We want to do a 3-way merge between A and
  12B, using O as the common ancestor.
  13
  14    merge A O B
  15
  16Decisions are made by comparing contents of O, A and B pathname
  17by pathname.  The result is determined by the following guiding
  18principle:
  19
  20 - If only A does something to it and B does not touch it, take
  21   whatever A does.
  22
  23 - If only B does something to it and A does not touch it, take
  24   whatever B does.
  25
  26 - If both A and B does something but in the same way, take
  27   whatever they do.
  28
  29 - If A and B does something but different things, we need a
  30   3-way merge:
  31
  32   - We cannot do anything about the following cases:
  33
  34     * O does not have it.  A and B both must be adding to the
  35       same path independently.
  36
  37     * A deletes it.  B must be modifying.
  38
  39   - Otherwise, A and B are modifying.  Run 3-way merge.
  40
  41First, the case matrix.
  42
  43 - Vertical axis is for A'\''s actions.
  44 - Horizontal axis is for B'\''s actions.
  45
  46.----------------------------------------------------------------.
  47| A        B | No Action  |   Delete   |   Modify   |    Add     |
  48|------------+------------+------------+------------+------------|
  49| No Action  |            |            |            |            |
  50|            | select O   | delete     | select B   | select B   |
  51|            |            |            |            |            |
  52|------------+------------+------------+------------+------------|
  53| Delete     |            |            | ********** |    can     |
  54|            | delete     | delete     | merge      |    not     |
  55|            |            |            |            |  happen    |
  56|------------+------------+------------+------------+------------|
  57| Modify     |            | ********** | ?????????? |    can     |
  58|            | select A   | merge      | select A=B |    not     |
  59|            |            |            | merge      |  happen    |
  60|------------+------------+------------+------------+------------|
  61| Add        |            |    can     |    can     | ?????????? |
  62|            | select A   |    not     |    not     | select A=B |
  63|            |            |  happen    |  happen    | merge      |
  64.----------------------------------------------------------------.
  65
  66In addition:
  67
  68 SS: a special case of MM, where A and B makes the same modification.
  69 LL: a special case of AA, where A and B creates the same file.
  70 TT: a special case of MM, where A and B makes mergeable changes.
  71 DF: a special case, where A makes a directory and B makes a file.
  72
  73'
  74. ./test-lib.sh
  75. "$TEST_DIRECTORY"/lib-read-tree.sh
  76. "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh
  77
  78################################################################
  79# Trivial "majority when 3 stages exist" merge plus #2ALT, #3ALT
  80# and #5ALT trivial merges.
  81
  82cat >expected <<\EOF
  83100644 X 2      AA
  84100644 X 3      AA
  85100644 X 0      AN
  86100644 X 1      DD
  87100644 X 3      DF
  88100644 X 2      DF/DF
  89100644 X 1      DM
  90100644 X 3      DM
  91100644 X 1      DN
  92100644 X 3      DN
  93100644 X 0      LL
  94100644 X 1      MD
  95100644 X 2      MD
  96100644 X 1      MM
  97100644 X 2      MM
  98100644 X 3      MM
  99100644 X 0      MN
 100100644 X 0      NA
 101100644 X 1      ND
 102100644 X 2      ND
 103100644 X 0      NM
 104100644 X 0      NN
 105100644 X 0      SS
 106100644 X 1      TT
 107100644 X 2      TT
 108100644 X 3      TT
 109100644 X 2      Z/AA
 110100644 X 3      Z/AA
 111100644 X 0      Z/AN
 112100644 X 1      Z/DD
 113100644 X 1      Z/DM
 114100644 X 3      Z/DM
 115100644 X 1      Z/DN
 116100644 X 3      Z/DN
 117100644 X 1      Z/MD
 118100644 X 2      Z/MD
 119100644 X 1      Z/MM
 120100644 X 2      Z/MM
 121100644 X 3      Z/MM
 122100644 X 0      Z/MN
 123100644 X 0      Z/NA
 124100644 X 1      Z/ND
 125100644 X 2      Z/ND
 126100644 X 0      Z/NM
 127100644 X 0      Z/NN
 128EOF
 129
 130check_result () {
 131    git ls-files --stage | sed -e 's/ '"$_x40"' / X /' >current &&
 132    test_cmp expected current
 133}
 134
 135# This is done on an empty work directory, which is the normal
 136# merge person behaviour.
 137test_expect_success \
 138    '3-way merge with git read-tree -m, empty cache' \
 139    "rm -fr [NDMALTS][NDMALTSF] Z &&
 140     rm .git/index &&
 141     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 142     check_result"
 143
 144# This starts out with the first head, which is the normal
 145# patch submitter behaviour.
 146test_expect_success \
 147    '3-way merge with git read-tree -m, match H' \
 148    "rm -fr [NDMALTS][NDMALTSF] Z &&
 149     rm .git/index &&
 150     read_tree_must_succeed $tree_A &&
 151     git checkout-index -f -u -a &&
 152     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 153     check_result"
 154
 155: <<\END_OF_CASE_TABLE
 156
 157We have so far tested only empty index and clean-and-matching-A index
 158case which are trivial.  Make sure index requirements are also
 159checked.
 160
 161"git read-tree -m O A B"
 162
 163     O       A       B         result      index requirements
 164-------------------------------------------------------------------
 165  1  missing missing missing   -           must not exist.
 166 ------------------------------------------------------------------
 167  2  missing missing exists    take B*     must match B, if exists.
 168 ------------------------------------------------------------------
 169  3  missing exists  missing   take A*     must match A, if exists.
 170 ------------------------------------------------------------------
 171  4  missing exists  A!=B      no merge    must match A and be
 172                                           up-to-date, if exists.
 173 ------------------------------------------------------------------
 174  5  missing exists  A==B      take A      must match A, if exists.
 175 ------------------------------------------------------------------
 176  6  exists  missing missing   remove      must not exist.
 177 ------------------------------------------------------------------
 178  7  exists  missing O!=B      no merge    must not exist.
 179 ------------------------------------------------------------------
 180  8  exists  missing O==B      remove      must not exist.
 181 ------------------------------------------------------------------
 182  9  exists  O!=A    missing   no merge    must match A and be
 183                                           up-to-date, if exists.
 184 ------------------------------------------------------------------
 185 10  exists  O==A    missing   no merge    must match A
 186 ------------------------------------------------------------------
 187 11  exists  O!=A    O!=B      no merge    must match A and be
 188                     A!=B                  up-to-date, if exists.
 189 ------------------------------------------------------------------
 190 12  exists  O!=A    O!=B      take A      must match A, if exists.
 191                     A==B
 192 ------------------------------------------------------------------
 193 13  exists  O!=A    O==B      take A      must match A, if exists.
 194 ------------------------------------------------------------------
 195 14  exists  O==A    O!=B      take B      if exists, must either (1)
 196                                           match A and be up-to-date,
 197                                           or (2) match B.
 198 ------------------------------------------------------------------
 199 15  exists  O==A    O==B      take B      must match A if exists.
 200 ------------------------------------------------------------------
 201 16  exists  O==A    O==B      barf        must match A if exists.
 202     *multi* in one  in another
 203-------------------------------------------------------------------
 204
 205Note: we need to be careful in case 2 and 3.  The tree A may contain
 206DF (file) when tree B require DF to be a directory by having DF/DF
 207(file).
 208
 209END_OF_CASE_TABLE
 210
 211test_expect_success '1 - must not have an entry not in A.' "
 212     rm -f .git/index XX &&
 213     echo XX >XX &&
 214     git update-index --add XX &&
 215     read_tree_must_fail -m $tree_O $tree_A $tree_B
 216"
 217
 218test_expect_success \
 219    '2 - must match B in !O && !A && B case.' \
 220    "rm -f .git/index NA &&
 221     cp .orig-B/NA NA &&
 222     git update-index --add NA &&
 223     read_tree_must_succeed -m $tree_O $tree_A $tree_B"
 224
 225test_expect_success \
 226    '2 - matching B alone is OK in !O && !A && B case.' \
 227    "rm -f .git/index NA &&
 228     cp .orig-B/NA NA &&
 229     git update-index --add NA &&
 230     echo extra >>NA &&
 231     read_tree_must_succeed -m $tree_O $tree_A $tree_B"
 232
 233test_expect_success \
 234    '3 - must match A in !O && A && !B case.' \
 235    "rm -f .git/index AN &&
 236     cp .orig-A/AN AN &&
 237     git update-index --add AN &&
 238     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 239     check_result"
 240
 241test_expect_success \
 242    '3 - matching A alone is OK in !O && A && !B case.' \
 243    "rm -f .git/index AN &&
 244     cp .orig-A/AN AN &&
 245     git update-index --add AN &&
 246     echo extra >>AN &&
 247     read_tree_must_succeed -m $tree_O $tree_A $tree_B"
 248
 249test_expect_success \
 250    '3 (fail) - must match A in !O && A && !B case.' "
 251     rm -f .git/index AN &&
 252     cp .orig-A/AN AN &&
 253     echo extra >>AN &&
 254     git update-index --add AN &&
 255     read_tree_must_fail -m $tree_O $tree_A $tree_B
 256"
 257
 258test_expect_success \
 259    '4 - must match and be up-to-date in !O && A && B && A!=B case.' \
 260    "rm -f .git/index AA &&
 261     cp .orig-A/AA AA &&
 262     git update-index --add AA &&
 263     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 264     check_result"
 265
 266test_expect_success \
 267    '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' "
 268     rm -f .git/index AA &&
 269     cp .orig-A/AA AA &&
 270     git update-index --add AA &&
 271     echo extra >>AA &&
 272     read_tree_must_fail -m $tree_O $tree_A $tree_B
 273"
 274
 275test_expect_success \
 276    '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' "
 277     rm -f .git/index AA &&
 278     cp .orig-A/AA AA &&
 279     echo extra >>AA &&
 280     git update-index --add AA &&
 281     read_tree_must_fail -m $tree_O $tree_A $tree_B
 282"
 283
 284test_expect_success \
 285    '5 - must match in !O && A && B && A==B case.' \
 286    "rm -f .git/index LL &&
 287     cp .orig-A/LL LL &&
 288     git update-index --add LL &&
 289     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 290     check_result"
 291
 292test_expect_success \
 293    '5 - must match in !O && A && B && A==B case.' \
 294    "rm -f .git/index LL &&
 295     cp .orig-A/LL LL &&
 296     git update-index --add LL &&
 297     echo extra >>LL &&
 298     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 299     check_result"
 300
 301test_expect_success \
 302    '5 (fail) - must match A in !O && A && B && A==B case.' "
 303     rm -f .git/index LL &&
 304     cp .orig-A/LL LL &&
 305     echo extra >>LL &&
 306     git update-index --add LL &&
 307     read_tree_must_fail -m $tree_O $tree_A $tree_B
 308"
 309
 310test_expect_success \
 311    '6 - must not exist in O && !A && !B case' "
 312     rm -f .git/index DD &&
 313     echo DD >DD &&
 314     git update-index --add DD &&
 315     read_tree_must_fail -m $tree_O $tree_A $tree_B
 316"
 317
 318test_expect_success \
 319    '7 - must not exist in O && !A && B && O!=B case' "
 320     rm -f .git/index DM &&
 321     cp .orig-B/DM DM &&
 322     git update-index --add DM &&
 323     read_tree_must_fail -m $tree_O $tree_A $tree_B
 324"
 325
 326test_expect_success \
 327    '8 - must not exist in O && !A && B && O==B case' "
 328     rm -f .git/index DN &&
 329     cp .orig-B/DN DN &&
 330     git update-index --add DN &&
 331     read_tree_must_fail -m $tree_O $tree_A $tree_B
 332"
 333
 334test_expect_success \
 335    '9 - must match and be up-to-date in O && A && !B && O!=A case' \
 336    "rm -f .git/index MD &&
 337     cp .orig-A/MD MD &&
 338     git update-index --add MD &&
 339     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 340     check_result"
 341
 342test_expect_success \
 343    '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' "
 344     rm -f .git/index MD &&
 345     cp .orig-A/MD MD &&
 346     git update-index --add MD &&
 347     echo extra >>MD &&
 348     read_tree_must_fail -m $tree_O $tree_A $tree_B
 349"
 350
 351test_expect_success \
 352    '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' "
 353     rm -f .git/index MD &&
 354     cp .orig-A/MD MD &&
 355     echo extra >>MD &&
 356     git update-index --add MD &&
 357     read_tree_must_fail -m $tree_O $tree_A $tree_B
 358"
 359
 360test_expect_success \
 361    '10 - must match and be up-to-date in O && A && !B && O==A case' \
 362    "rm -f .git/index ND &&
 363     cp .orig-A/ND ND &&
 364     git update-index --add ND &&
 365     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 366     check_result"
 367
 368test_expect_success \
 369    '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' "
 370     rm -f .git/index ND &&
 371     cp .orig-A/ND ND &&
 372     git update-index --add ND &&
 373     echo extra >>ND &&
 374     read_tree_must_fail -m $tree_O $tree_A $tree_B
 375"
 376
 377test_expect_success \
 378    '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' "
 379     rm -f .git/index ND &&
 380     cp .orig-A/ND ND &&
 381     echo extra >>ND &&
 382     git update-index --add ND &&
 383     read_tree_must_fail -m $tree_O $tree_A $tree_B
 384"
 385
 386test_expect_success \
 387    '11 - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' \
 388    "rm -f .git/index MM &&
 389     cp .orig-A/MM MM &&
 390     git update-index --add MM &&
 391     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 392     check_result"
 393
 394test_expect_success \
 395    '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' "
 396     rm -f .git/index MM &&
 397     cp .orig-A/MM MM &&
 398     git update-index --add MM &&
 399     echo extra >>MM &&
 400     read_tree_must_fail -m $tree_O $tree_A $tree_B
 401"
 402
 403test_expect_success \
 404    '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' "
 405     rm -f .git/index MM &&
 406     cp .orig-A/MM MM &&
 407     echo extra >>MM &&
 408     git update-index --add MM &&
 409     read_tree_must_fail -m $tree_O $tree_A $tree_B
 410"
 411
 412test_expect_success \
 413    '12 - must match A in O && A && B && O!=A && A==B case' \
 414    "rm -f .git/index SS &&
 415     cp .orig-A/SS SS &&
 416     git update-index --add SS &&
 417     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 418     check_result"
 419
 420test_expect_success \
 421    '12 - must match A in O && A && B && O!=A && A==B case' \
 422    "rm -f .git/index SS &&
 423     cp .orig-A/SS SS &&
 424     git update-index --add SS &&
 425     echo extra >>SS &&
 426     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 427     check_result"
 428
 429test_expect_success \
 430    '12 (fail) - must match A in O && A && B && O!=A && A==B case' "
 431     rm -f .git/index SS &&
 432     cp .orig-A/SS SS &&
 433     echo extra >>SS &&
 434     git update-index --add SS &&
 435     read_tree_must_fail -m $tree_O $tree_A $tree_B
 436"
 437
 438test_expect_success \
 439    '13 - must match A in O && A && B && O!=A && O==B case' \
 440    "rm -f .git/index MN &&
 441     cp .orig-A/MN MN &&
 442     git update-index --add MN &&
 443     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 444     check_result"
 445
 446test_expect_success \
 447    '13 - must match A in O && A && B && O!=A && O==B case' \
 448    "rm -f .git/index MN &&
 449     cp .orig-A/MN MN &&
 450     git update-index --add MN &&
 451     echo extra >>MN &&
 452     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 453     check_result"
 454
 455test_expect_success \
 456    '14 - must match and be up-to-date in O && A && B && O==A && O!=B case' \
 457    "rm -f .git/index NM &&
 458     cp .orig-A/NM NM &&
 459     git update-index --add NM &&
 460     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 461     check_result"
 462
 463test_expect_success \
 464    '14 - may match B in O && A && B && O==A && O!=B case' \
 465    "rm -f .git/index NM &&
 466     cp .orig-B/NM NM &&
 467     git update-index --add NM &&
 468     echo extra >>NM &&
 469     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 470     check_result"
 471
 472test_expect_success \
 473    '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' "
 474     rm -f .git/index NM &&
 475     cp .orig-A/NM NM &&
 476     git update-index --add NM &&
 477     echo extra >>NM &&
 478     read_tree_must_fail -m $tree_O $tree_A $tree_B
 479"
 480
 481test_expect_success \
 482    '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' "
 483     rm -f .git/index NM &&
 484     cp .orig-A/NM NM &&
 485     echo extra >>NM &&
 486     git update-index --add NM &&
 487     read_tree_must_fail -m $tree_O $tree_A $tree_B
 488"
 489
 490test_expect_success \
 491    '15 - must match A in O && A && B && O==A && O==B case' \
 492    "rm -f .git/index NN &&
 493     cp .orig-A/NN NN &&
 494     git update-index --add NN &&
 495     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 496     check_result"
 497
 498test_expect_success \
 499    '15 - must match A in O && A && B && O==A && O==B case' \
 500    "rm -f .git/index NN &&
 501     cp .orig-A/NN NN &&
 502     git update-index --add NN &&
 503     echo extra >>NN &&
 504     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 505     check_result"
 506
 507test_expect_success \
 508    '15 (fail) - must match A in O && A && B && O==A && O==B case' "
 509     rm -f .git/index NN &&
 510     cp .orig-A/NN NN &&
 511     echo extra >>NN &&
 512     git update-index --add NN &&
 513     read_tree_must_fail -m $tree_O $tree_A $tree_B
 514"
 515
 516# #16
 517test_expect_success \
 518    '16 - A matches in one and B matches in another.' \
 519    'rm -f .git/index F16 &&
 520    echo F16 >F16 &&
 521    git update-index --add F16 &&
 522    tree0=$(git write-tree) &&
 523    echo E16 >F16 &&
 524    git update-index F16 &&
 525    tree1=$(git write-tree) &&
 526    read_tree_must_succeed -m $tree0 $tree1 $tree1 $tree0 &&
 527    git ls-files --stage'
 528
 529test_done