t / t1001-read-tree-m-2way.shon commit merge-octopus: abort if index does not match HEAD (3ec62ad)
   1#!/bin/sh
   2#
   3# Copyright (c) 2005 Junio C Hamano
   4#
   5
   6test_description='Two way merge with read-tree -m $H $M
   7
   8This test tries two-way merge (aka fast-forward with carry forward).
   9
  10There is the head (called H) and another commit (called M), which is
  11simply ahead of H.  The index and the work tree contains a state that
  12is derived from H, but may also have local changes.  This test checks
  13all the combinations described in the two-tree merge "carry forward"
  14rules, found in <Documentation/git read-tree.txt>.
  15
  16In the test, these paths are used:
  17        bozbar  - in H, stays in M, modified from bozbar to gnusto
  18        frotz   - not in H added in M
  19        nitfol  - in H, stays in M unmodified
  20        rezrov  - in H, deleted in M
  21        yomin   - not in H or M
  22'
  23. ./test-lib.sh
  24. "$TEST_DIRECTORY"/lib-read-tree.sh
  25
  26read_tree_twoway () {
  27    git read-tree -m "$1" "$2" && git ls-files --stage
  28}
  29
  30compare_change () {
  31        sed -n >current \
  32            -e '/^--- /d; /^+++ /d; /^@@ /d;' \
  33            -e 's/^\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /p' \
  34            "$1"
  35        test_cmp expected current
  36}
  37
  38check_cache_at () {
  39        clean_if_empty=$(git diff-files -- "$1")
  40        case "$clean_if_empty" in
  41        '')  echo "$1: clean" ;;
  42        ?*)  echo "$1: dirty" ;;
  43        esac
  44        case "$2,$clean_if_empty" in
  45        clean,)         :     ;;
  46        clean,?*)       false ;;
  47        dirty,)         false ;;
  48        dirty,?*)       :     ;;
  49        esac
  50}
  51
  52cat >bozbar-old <<\EOF
  53This is a sample file used in two-way fast-forward merge
  54tests.  Its second line ends with a magic word bozbar
  55which will be modified by the merged head to gnusto.
  56It has some extra lines so that external tools can
  57successfully merge independent changes made to later
  58lines (such as this one), avoiding line conflicts.
  59EOF
  60
  61sed -e 's/bozbar/gnusto (earlier bozbar)/' bozbar-old >bozbar-new
  62
  63test_expect_success \
  64    setup \
  65    'echo frotz >frotz &&
  66     echo nitfol >nitfol &&
  67     cat bozbar-old >bozbar &&
  68     echo rezrov >rezrov &&
  69     echo yomin >yomin &&
  70     git update-index --add nitfol bozbar rezrov &&
  71     treeH=$(git write-tree) &&
  72     echo treeH $treeH &&
  73     git ls-tree $treeH &&
  74
  75     cat bozbar-new >bozbar &&
  76     git update-index --add frotz bozbar --force-remove rezrov &&
  77     git ls-files --stage >M.out &&
  78     treeM=$(git write-tree) &&
  79     echo treeM $treeM &&
  80     git ls-tree $treeM &&
  81     git diff-tree $treeH $treeM'
  82
  83test_expect_success \
  84    '1, 2, 3 - no carry forward' \
  85    'rm -f .git/index &&
  86     read_tree_twoway $treeH $treeM &&
  87     git ls-files --stage >1-3.out &&
  88     test_cmp M.out 1-3.out &&
  89     check_cache_at bozbar dirty &&
  90     check_cache_at frotz dirty &&
  91     check_cache_at nitfol dirty'
  92
  93echo '+100644 X 0       yomin' >expected
  94
  95test_expect_success \
  96    '4 - carry forward local addition.' \
  97    'rm -f .git/index &&
  98     read_tree_must_succeed $treeH &&
  99     git checkout-index -u -f -q -a &&
 100     git update-index --add yomin &&
 101     read_tree_twoway $treeH $treeM &&
 102     git ls-files --stage >4.out &&
 103     test_must_fail git diff --no-index M.out 4.out >4diff.out &&
 104     compare_change 4diff.out expected &&
 105     check_cache_at yomin clean'
 106
 107test_expect_success \
 108    '5 - carry forward local addition.' \
 109    'rm -f .git/index &&
 110     read_tree_must_succeed $treeH &&
 111     git checkout-index -u -f -q -a &&
 112     echo yomin >yomin &&
 113     git update-index --add yomin &&
 114     echo yomin yomin >yomin &&
 115     read_tree_twoway $treeH $treeM &&
 116     git ls-files --stage >5.out &&
 117     test_must_fail git diff --no-index M.out 5.out >5diff.out &&
 118     compare_change 5diff.out expected &&
 119     check_cache_at yomin dirty'
 120
 121test_expect_success \
 122    '6 - local addition already has the same.' \
 123    'rm -f .git/index &&
 124     read_tree_must_succeed $treeH &&
 125     git checkout-index -u -f -q -a &&
 126     git update-index --add frotz &&
 127     read_tree_twoway $treeH $treeM &&
 128     git ls-files --stage >6.out &&
 129     test_cmp M.out 6.out &&
 130     check_cache_at frotz clean'
 131
 132test_expect_success \
 133    '7 - local addition already has the same.' \
 134    'rm -f .git/index &&
 135     read_tree_must_succeed $treeH &&
 136     git checkout-index -u -f -q -a &&
 137     echo frotz >frotz &&
 138     git update-index --add frotz &&
 139     echo frotz frotz >frotz &&
 140     read_tree_twoway $treeH $treeM &&
 141     git ls-files --stage >7.out &&
 142     test_cmp M.out 7.out &&
 143     check_cache_at frotz dirty'
 144
 145test_expect_success \
 146    '8 - conflicting addition.' \
 147    'rm -f .git/index &&
 148     read_tree_must_succeed $treeH &&
 149     git checkout-index -u -f -q -a &&
 150     echo frotz frotz >frotz &&
 151     git update-index --add frotz &&
 152     if read_tree_twoway $treeH $treeM; then false; else :; fi'
 153
 154test_expect_success \
 155    '9 - conflicting addition.' \
 156    'rm -f .git/index &&
 157     read_tree_must_succeed $treeH &&
 158     git checkout-index -u -f -q -a &&
 159     echo frotz frotz >frotz &&
 160     git update-index --add frotz &&
 161     echo frotz >frotz &&
 162     if read_tree_twoway $treeH $treeM; then false; else :; fi'
 163
 164test_expect_success \
 165    '10 - path removed.' \
 166    'rm -f .git/index &&
 167     read_tree_must_succeed $treeH &&
 168     git checkout-index -u -f -q -a &&
 169     echo rezrov >rezrov &&
 170     git update-index --add rezrov &&
 171     read_tree_twoway $treeH $treeM &&
 172     git ls-files --stage >10.out &&
 173     test_cmp M.out 10.out'
 174
 175test_expect_success \
 176    '11 - dirty path removed.' \
 177    'rm -f .git/index &&
 178     read_tree_must_succeed $treeH &&
 179     git checkout-index -u -f -q -a &&
 180     echo rezrov >rezrov &&
 181     git update-index --add rezrov &&
 182     echo rezrov rezrov >rezrov &&
 183     if read_tree_twoway $treeH $treeM; then false; else :; fi'
 184
 185test_expect_success \
 186    '12 - unmatching local changes being removed.' \
 187    'rm -f .git/index &&
 188     read_tree_must_succeed $treeH &&
 189     git checkout-index -u -f -q -a &&
 190     echo rezrov rezrov >rezrov &&
 191     git update-index --add rezrov &&
 192     if read_tree_twoway $treeH $treeM; then false; else :; fi'
 193
 194test_expect_success \
 195    '13 - unmatching local changes being removed.' \
 196    'rm -f .git/index &&
 197     read_tree_must_succeed $treeH &&
 198     git checkout-index -u -f -q -a &&
 199     echo rezrov rezrov >rezrov &&
 200     git update-index --add rezrov &&
 201     echo rezrov >rezrov &&
 202     if read_tree_twoway $treeH $treeM; then false; else :; fi'
 203
 204cat >expected <<EOF
 205-100644 X 0     nitfol
 206+100644 X 0     nitfol
 207EOF
 208
 209test_expect_success \
 210    '14 - unchanged in two heads.' \
 211    'rm -f .git/index &&
 212     read_tree_must_succeed $treeH &&
 213     git checkout-index -u -f -q -a &&
 214     echo nitfol nitfol >nitfol &&
 215     git update-index --add nitfol &&
 216     read_tree_twoway $treeH $treeM &&
 217     git ls-files --stage >14.out &&
 218     test_must_fail git diff --no-index M.out 14.out >14diff.out &&
 219     compare_change 14diff.out expected &&
 220     check_cache_at nitfol clean'
 221
 222test_expect_success \
 223    '15 - unchanged in two heads.' \
 224    'rm -f .git/index &&
 225     read_tree_must_succeed $treeH &&
 226     git checkout-index -u -f -q -a &&
 227     echo nitfol nitfol >nitfol &&
 228     git update-index --add nitfol &&
 229     echo nitfol nitfol nitfol >nitfol &&
 230     read_tree_twoway $treeH $treeM &&
 231     git ls-files --stage >15.out &&
 232     test_must_fail git diff --no-index M.out 15.out >15diff.out &&
 233     compare_change 15diff.out expected &&
 234     check_cache_at nitfol dirty'
 235
 236test_expect_success \
 237    '16 - conflicting local change.' \
 238    'rm -f .git/index &&
 239     read_tree_must_succeed $treeH &&
 240     git checkout-index -u -f -q -a &&
 241     echo bozbar bozbar >bozbar &&
 242     git update-index --add bozbar &&
 243     if read_tree_twoway $treeH $treeM; then false; else :; fi'
 244
 245test_expect_success \
 246    '17 - conflicting local change.' \
 247    'rm -f .git/index &&
 248     read_tree_must_succeed $treeH &&
 249     git checkout-index -u -f -q -a &&
 250     echo bozbar bozbar >bozbar &&
 251     git update-index --add bozbar &&
 252     echo bozbar bozbar bozbar >bozbar &&
 253     if read_tree_twoway $treeH $treeM; then false; else :; fi'
 254
 255test_expect_success \
 256    '18 - local change already having a good result.' \
 257    'rm -f .git/index &&
 258     read_tree_must_succeed $treeH &&
 259     git checkout-index -u -f -q -a &&
 260     cat bozbar-new >bozbar &&
 261     git update-index --add bozbar &&
 262     read_tree_twoway $treeH $treeM &&
 263     git ls-files --stage >18.out &&
 264     test_cmp M.out 18.out &&
 265     check_cache_at bozbar clean'
 266
 267test_expect_success \
 268    '19 - local change already having a good result, further modified.' \
 269    'rm -f .git/index &&
 270     read_tree_must_succeed $treeH &&
 271     git checkout-index -u -f -q -a &&
 272     cat bozbar-new >bozbar &&
 273     git update-index --add bozbar &&
 274     echo gnusto gnusto >bozbar &&
 275     read_tree_twoway $treeH $treeM &&
 276     git ls-files --stage >19.out &&
 277     test_cmp M.out 19.out &&
 278     check_cache_at bozbar dirty'
 279
 280test_expect_success \
 281    '20 - no local change, use new tree.' \
 282    'rm -f .git/index &&
 283     read_tree_must_succeed $treeH &&
 284     git checkout-index -u -f -q -a &&
 285     cat bozbar-old >bozbar &&
 286     git update-index --add bozbar &&
 287     read_tree_twoway $treeH $treeM &&
 288     git ls-files --stage >20.out &&
 289     test_cmp M.out 20.out &&
 290     check_cache_at bozbar dirty'
 291
 292test_expect_success \
 293    '21 - no local change, dirty cache.' \
 294    'rm -f .git/index &&
 295     read_tree_must_succeed $treeH &&
 296     git checkout-index -u -f -q -a &&
 297     cat bozbar-old >bozbar &&
 298     git update-index --add bozbar &&
 299     echo gnusto gnusto >bozbar &&
 300     if read_tree_twoway $treeH $treeM; then false; else :; fi'
 301
 302# This fails with straight two-way fast-forward.
 303test_expect_success \
 304    '22 - local change cache updated.' \
 305    'rm -f .git/index &&
 306     read_tree_must_succeed $treeH &&
 307     git checkout-index -u -f -q -a &&
 308     sed -e "s/such as/SUCH AS/" bozbar-old >bozbar &&
 309     git update-index --add bozbar &&
 310     if read_tree_twoway $treeH $treeM; then false; else :; fi'
 311
 312# Also make sure we did not break DF vs DF/DF case.
 313test_expect_success \
 314    'DF vs DF/DF case setup.' \
 315    'rm -f .git/index &&
 316     echo DF >DF &&
 317     git update-index --add DF &&
 318     treeDF=$(git write-tree) &&
 319     echo treeDF $treeDF &&
 320     git ls-tree $treeDF &&
 321
 322     rm -f DF &&
 323     mkdir DF &&
 324     echo DF/DF >DF/DF &&
 325     git update-index --add --remove DF DF/DF &&
 326     treeDFDF=$(git write-tree) &&
 327     echo treeDFDF $treeDFDF &&
 328     git ls-tree $treeDFDF &&
 329     git ls-files --stage >DFDF.out'
 330
 331test_expect_success \
 332    'DF vs DF/DF case test.' \
 333    'rm -f .git/index &&
 334     rm -fr DF &&
 335     echo DF >DF &&
 336     git update-index --add DF &&
 337     read_tree_twoway $treeDF $treeDFDF &&
 338     git ls-files --stage >DFDFcheck.out &&
 339     test_cmp DFDF.out DFDFcheck.out &&
 340     check_cache_at DF/DF dirty &&
 341     :'
 342
 343test_expect_success \
 344    'a/b (untracked) vs a case setup.' \
 345    'rm -f .git/index &&
 346     : >a &&
 347     git update-index --add a &&
 348     treeM=$(git write-tree) &&
 349     echo treeM $treeM &&
 350     git ls-tree $treeM &&
 351     git ls-files --stage >treeM.out &&
 352
 353     rm -f a &&
 354     git update-index --remove a &&
 355     mkdir a &&
 356     : >a/b &&
 357     treeH=$(git write-tree) &&
 358     echo treeH $treeH &&
 359     git ls-tree $treeH'
 360
 361test_expect_success \
 362    'a/b (untracked) vs a, plus c/d case test.' \
 363    'read_tree_u_must_fail -u -m "$treeH" "$treeM" &&
 364     git ls-files --stage &&
 365     test -f a/b'
 366
 367test_expect_success \
 368    'a/b vs a, plus c/d case setup.' \
 369    'rm -f .git/index &&
 370     rm -fr a &&
 371     : >a &&
 372     mkdir c &&
 373     : >c/d &&
 374     git update-index --add a c/d &&
 375     treeM=$(git write-tree) &&
 376     echo treeM $treeM &&
 377     git ls-tree $treeM &&
 378     git ls-files --stage >treeM.out &&
 379
 380     rm -f a &&
 381     mkdir a &&
 382     : >a/b &&
 383     git update-index --add --remove a a/b &&
 384     treeH=$(git write-tree) &&
 385     echo treeH $treeH &&
 386     git ls-tree $treeH'
 387
 388test_expect_success \
 389    'a/b vs a, plus c/d case test.' \
 390    'read_tree_u_must_succeed -u -m "$treeH" "$treeM" &&
 391     git ls-files --stage | tee >treeMcheck.out &&
 392     test_cmp treeM.out treeMcheck.out'
 393
 394test_expect_success '-m references the correct modified tree' '
 395        echo >file-a &&
 396        echo >file-b &&
 397        git add file-a file-b &&
 398        git commit -a -m "test for correct modified tree" &&
 399        git branch initial-mod &&
 400        echo b >file-b &&
 401        git commit -a -m "B" &&
 402        echo a >file-a &&
 403        git add file-a &&
 404        git ls-tree $(git write-tree) file-a >expect &&
 405        read_tree_must_succeed -m HEAD initial-mod &&
 406        git ls-tree $(git write-tree) file-a >actual &&
 407        test_cmp expect actual
 408'
 409
 410test_done