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