t / t1000-read-tree-m-3way.shon commit Introduce "base_name_compare()" helper function (958ba6c)
   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
  75. ./test-lib.sh
  76
  77# Original tree.
  78mkdir Z
  79for a in N D M
  80do
  81    for b in N D M
  82    do
  83        p=$a$b
  84        echo This is $p from the original tree. >$p
  85        echo This is Z/$p from the original tree. >Z/$p
  86        test_expect_success \
  87            "adding test file $p and Z/$p" \
  88            'git-update-cache --add $p &&
  89            git-update-cache --add Z/$p'
  90    done
  91done
  92echo This is SS from the original tree. >SS
  93test_expect_success \
  94    'adding test file SS' \
  95    'git-update-cache --add SS'
  96cat >TT <<\EOF
  97This is a trivial merge sample text.
  98Branch A is expected to upcase this word, here.
  99There are some filler lines to avoid diff context
 100conflicts here,
 101like this one,
 102and this one,
 103and this one is yet another one of them.
 104At the very end, here comes another line, that is
 105the word, expected to be upcased by Branch B.
 106This concludes the trivial merge sample file.
 107EOF
 108test_expect_success \
 109    'adding test file TT' \
 110    'git-update-cache --add TT'
 111test_expect_success \
 112    'prepare initial tree' \
 113    'tree_O=$(git-write-tree)'
 114
 115test_expect_success \
 116    'commit initial tree' \
 117    'commit_O=$(echo "Original tree for the merge test." |
 118     git-commit-tree $tree_O)'
 119echo $commit_O >.git/HEAD-O
 120
 121################################################################
 122# Branch A and B makes the changes according to the above matrix.
 123
 124################################################################
 125# Branch A
 126
 127to_remove=$(echo D? Z/D?)
 128rm -f $to_remove
 129test_expect_success \
 130    'change in branch A (removal)' \
 131    'git-update-cache --remove $to_remove'
 132
 133for p in M? Z/M?
 134do
 135    echo This is modified $p in the branch A. >$p
 136    test_expect_success \
 137        'change in branch A (modification)' \
 138        "git-update-cache $p"
 139done
 140
 141for p in AN AA Z/AN Z/AA
 142do
 143    echo This is added $p in the branch A. >$p
 144    test_expect_success \
 145        'change in branch A (addition)' \
 146        "git-update-cache --add $p"
 147done
 148
 149echo This is SS from the modified tree. >SS
 150echo This is LL from the modified tree. >LL
 151test_expect_success \
 152    'change in branch A (addition)' \
 153    'git-update-cache --add LL &&
 154     git-update-cache SS'
 155mv TT TT-
 156sed -e '/Branch A/s/word/WORD/g' <TT- >TT
 157rm -f TT-
 158test_expect_success \
 159    'change in branch A (edit)' \
 160    'git-update-cache TT'
 161
 162mkdir DF
 163echo Branch A makes a file at DF/DF, creating a directory DF. >DF/DF
 164test_expect_success \
 165    'change in branch A (change file to directory)' \
 166    'git-update-cache --add DF/DF'
 167
 168test_expect_success \
 169    'recording branch A tree' \
 170    'tree_A=$(git-write-tree)'
 171test_expect_success \
 172    'committing branch A changes' \
 173    'commit_A=$(echo "Branch A for the merge test." |
 174           git-commit-tree $tree_A -p $commit_O)'
 175echo $commit_A >.git/HEAD-A
 176           
 177################################################################
 178# Branch B
 179# Start from O
 180
 181rm -rf [NDMASLT][NDMASLT] Z DF
 182mkdir Z
 183test_expect_success \
 184    'reading original tree and checking out' \
 185    'git-read-tree $tree_O &&
 186     git-checkout-cache -a'
 187
 188to_remove=$(echo ?D Z/?D)
 189rm -f $to_remove
 190test_expect_success \
 191    'change in branch B (removal)' \
 192    "git-update-cache --remove $to_remove"
 193
 194for p in ?M Z/?M
 195do
 196    echo This is modified $p in the branch B. >$p
 197    test_expect_success \
 198        'change in branch B (modification)' \
 199        "git-update-cache $p"
 200done
 201
 202for p in NA AA Z/NA Z/AA
 203do
 204    echo This is added $p in the branch B. >$p
 205    test_expect_success \
 206        'change in branch B (addition)' \
 207        "git-update-cache --add $p"
 208done
 209echo This is SS from the modified tree. >SS
 210echo This is LL from the modified tree. >LL
 211test_expect_success \
 212    'change in branch B (addition and modification)' \
 213    'git-update-cache --add LL &&
 214     git-update-cache SS'
 215mv TT TT-
 216sed -e '/Branch B/s/word/WORD/g' <TT- >TT
 217rm -f TT-
 218test_expect_success \
 219    'change in branch B (modification)' \
 220    'git-update-cache TT'
 221
 222echo Branch B makes a file at DF. >DF
 223test_expect_success \
 224    'change in branch B (addition of a file to conflict with directory)' \
 225    'git-update-cache --add DF'
 226
 227test_expect_success \
 228    'recording branch B tree' \
 229    'tree_B=$(git-write-tree)'
 230test_expect_success \
 231    'committing branch B changes' \
 232    'commit_B=$(echo "Branch B for the merge test." |
 233           git-commit-tree $tree_B -p $commit_O)'
 234echo $commit_B >.git/HEAD-B
 235
 236################################################################
 237# Done preparation.
 238
 239test_debug '
 240    for T in O A B
 241    do
 242        echo "# $T $(eval git-cat-file commit \$commit_$T | sed -e 1q)"
 243    done
 244'
 245
 246################################################################
 247# Try merging and showing the various diffs
 248
 249test_expect_success \
 250    '3-way merge with git-read-tree -m' \
 251    "git-read-tree -m $tree_O $tree_A $tree_B"
 252
 253strip_object_id='s/^\([0-7]*\) [0-9a-f]* \([0-3].*\)$/\1 \2/'
 254
 255test_expect_success \
 256    'git-ls-files --stage of the merge result' \
 257    'git-ls-files --stage >current- &&
 258     sed -e "$strip_object_id" <current- >current'
 259
 260cat >expected <<\EOF
 261100644 2 AA
 262100644 3 AA
 263100644 2 AN
 264100644 1 DD
 265100644 3 DF
 266100644 2 DF/DF
 267100644 1 DM
 268100644 3 DM
 269100644 1 DN
 270100644 3 DN
 271100644 2 LL
 272100644 3 LL
 273100644 1 MD
 274100644 2 MD
 275100644 1 MM
 276100644 2 MM
 277100644 3 MM
 278100644 0 MN
 279100644 3 NA
 280100644 1 ND
 281100644 2 ND
 282100644 0 NM
 283100644 0 NN
 284100644 0 SS
 285100644 1 TT
 286100644 2 TT
 287100644 3 TT
 288100644 2 Z/AA
 289100644 3 Z/AA
 290100644 2 Z/AN
 291100644 1 Z/DD
 292100644 1 Z/DM
 293100644 3 Z/DM
 294100644 1 Z/DN
 295100644 3 Z/DN
 296100644 1 Z/MD
 297100644 2 Z/MD
 298100644 1 Z/MM
 299100644 2 Z/MM
 300100644 3 Z/MM
 301100644 0 Z/MN
 302100644 3 Z/NA
 303100644 1 Z/ND
 304100644 2 Z/ND
 305100644 0 Z/NM
 306100644 0 Z/NN
 307EOF
 308
 309test_expect_success \
 310    'validate merge result' \
 311    'diff current expected'
 312
 313test_done