1#!/bin/sh
   2#
   3# Copyright (c) 2005 Junio C Hamano
   4#
   5test_description='Two way merge with read-tree -m $H $M
   7This test tries two-way merge (aka fast forward with carry forward).
   9There 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>.
  15In 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
  24read_tree_twoway () {
  26    git-read-tree -m "$1" "$2" && git-ls-files --stage
  27}
  28_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        diff -u expected current
  37}
  38check_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}
  52cat >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
  61sed -e 's/bozbar/gnusto (earlier bozbar)/' bozbar-old >bozbar-new
  63test_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     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'
  83test_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     diff -u M.out 1-3.out &&
  90     check_cache_at bozbar dirty &&
  91     check_cache_at frotz dirty &&
  92     check_cache_at nitfol dirty'
  93echo '+100644 X 0       yomin' >expected
  95test_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     diff -u M.out 4.out >4diff.out
 105     compare_change 4diff.out expected &&
 106     check_cache_at yomin clean'
 107test_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     diff -u M.out 5.out >5diff.out
 119     compare_change 5diff.out expected &&
 120     check_cache_at yomin dirty'
 121test_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     diff -u M.out 6.out &&
 131     check_cache_at frotz clean'
 132test_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     diff -u M.out 7.out &&
 144     check_cache_at frotz dirty'
 145test_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'
 154test_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'
 164test_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     diff -u M.out 10.out'
 175test_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'
 185test_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'
 194test_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'
 204cat >expected <<EOF
 206-100644 X 0     nitfol
 207+100644 X 0     nitfol
 208EOF
 209test_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     diff -u M.out 14.out >14diff.out
 220     compare_change 14diff.out expected &&
 221     check_cache_at nitfol clean'
 222test_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     diff -u M.out 15.out >15diff.out
 234     compare_change 15diff.out expected &&
 235     check_cache_at nitfol dirty'
 236test_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'
 245test_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'
 255test_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     diff -u M.out 18.out &&
 266     check_cache_at bozbar clean'
 267test_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     diff -u M.out 19.out &&
 279     check_cache_at bozbar dirty'
 280test_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     diff -u M.out 20.out &&
 291     check_cache_at bozbar dirty'
 292test_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# 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# 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     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'
 331test_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     diff -u DFDF.out DFDFcheck.out &&
 341     check_cache_at DF/DF dirty &&
 342     :'
 343test_done