t / t1000-read-tree-m-3way.shon commit Merge branch 'jk/pack-idx-corruption-safety' into maint (7deb48a)
   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 '3-way merge with git read-tree -m, empty cache' '
 138        rm -fr [NDMALTS][NDMALTSF] Z &&
 139        rm .git/index &&
 140        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 141        check_result
 142'
 143
 144# This starts out with the first head, which is the normal
 145# patch submitter behaviour.
 146test_expect_success '3-way merge with git read-tree -m, match H' '
 147        rm -fr [NDMALTS][NDMALTSF] Z &&
 148        rm .git/index &&
 149        read_tree_must_succeed $tree_A &&
 150        git checkout-index -f -u -a &&
 151        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 152        check_result
 153'
 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 '2 - must match B in !O && !A && B case.' '
 219        rm -f .git/index NA &&
 220        cp .orig-B/NA NA &&
 221        git update-index --add NA &&
 222        read_tree_must_succeed -m $tree_O $tree_A $tree_B
 223'
 224
 225test_expect_success '2 - matching B alone is OK in !O && !A && B case.' '
 226        rm -f .git/index NA &&
 227        cp .orig-B/NA NA &&
 228        git update-index --add NA &&
 229        echo extra >>NA &&
 230        read_tree_must_succeed -m $tree_O $tree_A $tree_B
 231'
 232
 233test_expect_success '3 - must match A in !O && A && !B case.' '
 234        rm -f .git/index AN &&
 235        cp .orig-A/AN AN &&
 236        git update-index --add AN &&
 237        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 238        check_result
 239'
 240
 241test_expect_success '3 - matching A alone is OK in !O && A && !B case.' '
 242        rm -f .git/index AN &&
 243        cp .orig-A/AN AN &&
 244        git update-index --add AN &&
 245        echo extra >>AN &&
 246        read_tree_must_succeed -m $tree_O $tree_A $tree_B
 247'
 248
 249test_expect_success '3 (fail) - must match A in !O && A && !B case.' '
 250        rm -f .git/index AN &&
 251        cp .orig-A/AN AN &&
 252        echo extra >>AN &&
 253        git update-index --add AN &&
 254        read_tree_must_fail -m $tree_O $tree_A $tree_B
 255'
 256
 257test_expect_success '4 - must match and be up-to-date in !O && A && B && A!=B case.' '
 258        rm -f .git/index AA &&
 259        cp .orig-A/AA AA &&
 260        git update-index --add AA &&
 261        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 262        check_result
 263'
 264
 265test_expect_success '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' '
 266        rm -f .git/index AA &&
 267        cp .orig-A/AA AA &&
 268        git update-index --add AA &&
 269        echo extra >>AA &&
 270        read_tree_must_fail -m $tree_O $tree_A $tree_B
 271'
 272
 273test_expect_success '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' '
 274        rm -f .git/index AA &&
 275        cp .orig-A/AA AA &&
 276        echo extra >>AA &&
 277        git update-index --add AA &&
 278        read_tree_must_fail -m $tree_O $tree_A $tree_B
 279'
 280
 281test_expect_success '5 - must match in !O && A && B && A==B case.' '
 282        rm -f .git/index LL &&
 283        cp .orig-A/LL LL &&
 284        git update-index --add LL &&
 285        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 286        check_result
 287'
 288
 289test_expect_success '5 - must match in !O && A && B && A==B case.' '
 290        rm -f .git/index LL &&
 291        cp .orig-A/LL LL &&
 292        git update-index --add LL &&
 293        echo extra >>LL &&
 294        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 295        check_result
 296'
 297
 298test_expect_success '5 (fail) - must match A in !O && A && B && A==B case.' '
 299        rm -f .git/index LL &&
 300        cp .orig-A/LL LL &&
 301        echo extra >>LL &&
 302        git update-index --add LL &&
 303        read_tree_must_fail -m $tree_O $tree_A $tree_B
 304'
 305
 306test_expect_success '6 - must not exist in O && !A && !B case' '
 307        rm -f .git/index DD &&
 308        echo DD >DD &&
 309        git update-index --add DD &&
 310        read_tree_must_fail -m $tree_O $tree_A $tree_B
 311'
 312
 313test_expect_success '7 - must not exist in O && !A && B && O!=B case' '
 314        rm -f .git/index DM &&
 315        cp .orig-B/DM DM &&
 316        git update-index --add DM &&
 317        read_tree_must_fail -m $tree_O $tree_A $tree_B
 318'
 319
 320test_expect_success '8 - must not exist in O && !A && B && O==B case' '
 321        rm -f .git/index DN &&
 322        cp .orig-B/DN DN &&
 323        git update-index --add DN &&
 324        read_tree_must_fail -m $tree_O $tree_A $tree_B
 325'
 326
 327test_expect_success '9 - must match and be up-to-date in O && A && !B && O!=A case' '
 328        rm -f .git/index MD &&
 329        cp .orig-A/MD MD &&
 330        git update-index --add MD &&
 331        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 332        check_result
 333'
 334
 335test_expect_success '9 (fail) - 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        echo extra >>MD &&
 340        read_tree_must_fail -m $tree_O $tree_A $tree_B
 341'
 342
 343test_expect_success '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        echo extra >>MD &&
 347        git update-index --add MD &&
 348        read_tree_must_fail -m $tree_O $tree_A $tree_B
 349'
 350
 351test_expect_success '10 - must match and be up-to-date in O && A && !B && O==A case' '
 352        rm -f .git/index ND &&
 353        cp .orig-A/ND ND &&
 354        git update-index --add ND &&
 355        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 356        check_result
 357'
 358
 359test_expect_success '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' '
 360        rm -f .git/index ND &&
 361        cp .orig-A/ND ND &&
 362        git update-index --add ND &&
 363        echo extra >>ND &&
 364        read_tree_must_fail -m $tree_O $tree_A $tree_B
 365'
 366
 367test_expect_success '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' '
 368        rm -f .git/index ND &&
 369        cp .orig-A/ND ND &&
 370        echo extra >>ND &&
 371        git update-index --add ND &&
 372        read_tree_must_fail -m $tree_O $tree_A $tree_B
 373'
 374
 375test_expect_success '11 - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' '
 376        rm -f .git/index MM &&
 377        cp .orig-A/MM MM &&
 378        git update-index --add MM &&
 379        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 380        check_result
 381'
 382
 383test_expect_success '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' '
 384        rm -f .git/index MM &&
 385        cp .orig-A/MM MM &&
 386        git update-index --add MM &&
 387        echo extra >>MM &&
 388        read_tree_must_fail -m $tree_O $tree_A $tree_B
 389'
 390
 391test_expect_success '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' '
 392        rm -f .git/index MM &&
 393        cp .orig-A/MM MM &&
 394        echo extra >>MM &&
 395        git update-index --add MM &&
 396        read_tree_must_fail -m $tree_O $tree_A $tree_B
 397'
 398
 399test_expect_success '12 - must match A in O && A && B && O!=A && A==B case' '
 400        rm -f .git/index SS &&
 401        cp .orig-A/SS SS &&
 402        git update-index --add SS &&
 403        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 404        check_result
 405'
 406
 407test_expect_success '12 - must match A in O && A && B && O!=A && A==B case' '
 408        rm -f .git/index SS &&
 409        cp .orig-A/SS SS &&
 410        git update-index --add SS &&
 411        echo extra >>SS &&
 412        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 413        check_result
 414'
 415
 416test_expect_success '12 (fail) - must match A in O && A && B && O!=A && A==B case' '
 417        rm -f .git/index SS &&
 418        cp .orig-A/SS SS &&
 419        echo extra >>SS &&
 420        git update-index --add SS &&
 421        read_tree_must_fail -m $tree_O $tree_A $tree_B
 422'
 423
 424test_expect_success '13 - must match A in O && A && B && O!=A && O==B case' '
 425        rm -f .git/index MN &&
 426        cp .orig-A/MN MN &&
 427        git update-index --add MN &&
 428        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 429        check_result
 430'
 431
 432test_expect_success '13 - must match A in O && A && B && O!=A && O==B case' '
 433        rm -f .git/index MN &&
 434        cp .orig-A/MN MN &&
 435        git update-index --add MN &&
 436        echo extra >>MN &&
 437        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 438        check_result
 439'
 440
 441test_expect_success '14 - must match and be up-to-date in O && A && B && O==A && O!=B case' '
 442        rm -f .git/index NM &&
 443        cp .orig-A/NM NM &&
 444        git update-index --add NM &&
 445        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 446        check_result
 447'
 448
 449test_expect_success '14 - may match B in O && A && B && O==A && O!=B case' '
 450        rm -f .git/index NM &&
 451        cp .orig-B/NM NM &&
 452        git update-index --add NM &&
 453        echo extra >>NM &&
 454        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 455        check_result
 456'
 457
 458test_expect_success '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' '
 459        rm -f .git/index NM &&
 460        cp .orig-A/NM NM &&
 461        git update-index --add NM &&
 462        echo extra >>NM &&
 463        read_tree_must_fail -m $tree_O $tree_A $tree_B
 464'
 465
 466test_expect_success '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' '
 467        rm -f .git/index NM &&
 468        cp .orig-A/NM NM &&
 469        echo extra >>NM &&
 470        git update-index --add NM &&
 471        read_tree_must_fail -m $tree_O $tree_A $tree_B
 472'
 473
 474test_expect_success '15 - must match A in O && A && B && O==A && O==B case' '
 475        rm -f .git/index NN &&
 476        cp .orig-A/NN NN &&
 477        git update-index --add NN &&
 478        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 479        check_result
 480'
 481
 482test_expect_success '15 - must match A in O && A && B && O==A && O==B case' '
 483        rm -f .git/index NN &&
 484        cp .orig-A/NN NN &&
 485        git update-index --add NN &&
 486        echo extra >>NN &&
 487        read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
 488        check_result
 489'
 490
 491test_expect_success '15 (fail) - 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        echo extra >>NN &&
 495        git update-index --add NN &&
 496        read_tree_must_fail -m $tree_O $tree_A $tree_B
 497'
 498
 499test_expect_success '16 - A matches in one and B matches in another.' '
 500        rm -f .git/index F16 &&
 501        echo F16 >F16 &&
 502        git update-index --add F16 &&
 503        tree0=$(git write-tree) &&
 504        echo E16 >F16 &&
 505        git update-index F16 &&
 506        tree1=$(git write-tree) &&
 507        read_tree_must_succeed -m $tree0 $tree1 $tree1 $tree0 &&
 508        git ls-files --stage
 509'
 510
 511test_done