t / t4150-am.shon commit tree: simplify parse_tree_indirect() (1577dc0)
   1#!/bin/sh
   2
   3test_description='git am running'
   4
   5. ./test-lib.sh
   6
   7test_expect_success 'setup: messages' '
   8        cat >msg <<-\EOF &&
   9        second
  10
  11        Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy
  12        eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
  13        voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita
  14        kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem
  15        ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
  16        tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
  17        vero eos et accusam et justo duo dolores et ea rebum.
  18
  19        EOF
  20        qz_to_tab_space <<-\EOF >>msg &&
  21        QDuis autem vel eum iriure dolor in hendrerit in vulputate velit
  22        Qesse molestie consequat, vel illum dolore eu feugiat nulla facilisis
  23        Qat vero eros et accumsan et iusto odio dignissim qui blandit
  24        Qpraesent luptatum zzril delenit augue duis dolore te feugait nulla
  25        Qfacilisi.
  26        EOF
  27        cat >>msg <<-\EOF &&
  28
  29        Lorem ipsum dolor sit amet,
  30        consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
  31        laoreet dolore magna aliquam erat volutpat.
  32
  33          git
  34          ---
  35          +++
  36
  37        Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit
  38        lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure
  39        dolor in hendrerit in vulputate velit esse molestie consequat, vel illum
  40        dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
  41        dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te
  42        feugait nulla facilisi.
  43
  44        Reported-by: A N Other <a.n.other@example.com>
  45        EOF
  46
  47        cat >failmail <<-\EOF &&
  48        From foo@example.com Fri May 23 10:43:49 2008
  49        From:   foo@example.com
  50        To:     bar@example.com
  51        Subject: Re: [RFC/PATCH] git-foo.sh
  52        Date:   Fri, 23 May 2008 05:23:42 +0200
  53
  54        Sometimes we have to find out that there'\''s nothing left.
  55
  56        EOF
  57
  58        cat >pine <<-\EOF &&
  59        From MAILER-DAEMON Fri May 23 10:43:49 2008
  60        Date: 23 May 2008 05:23:42 +0200
  61        From: Mail System Internal Data <MAILER-DAEMON@example.com>
  62        Subject: DON'\''T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA
  63        Message-ID: <foo-0001@example.com>
  64
  65        This text is part of the internal format of your mail folder, and is not
  66        a real message.  It is created automatically by the mail system software.
  67        If deleted, important folder data will be lost, and it will be re-created
  68        with the data reset to initial values.
  69
  70        EOF
  71
  72        cat >msg-without-scissors-line <<-\EOF &&
  73        Test that git-am --scissors cuts at the scissors line
  74
  75        This line should be included in the commit message.
  76        EOF
  77
  78        printf "Subject: " >subject-prefix &&
  79
  80        cat - subject-prefix msg-without-scissors-line >msg-with-scissors-line <<-\EOF
  81        This line should not be included in the commit message with --scissors enabled.
  82
  83         - - >8 - - remove everything above this line - - >8 - -
  84
  85        EOF
  86'
  87
  88test_expect_success setup '
  89        echo hello >file &&
  90        git add file &&
  91        test_tick &&
  92        git commit -m first &&
  93        git tag first &&
  94
  95        echo world >>file &&
  96        git add file &&
  97        test_tick &&
  98        git commit -F msg &&
  99        git tag second &&
 100
 101        git format-patch --stdout first >patch1 &&
 102        {
 103                echo "Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>" &&
 104                echo "X-Fake-Field: Line One" &&
 105                echo "X-Fake-Field: Line Two" &&
 106                echo "X-Fake-Field: Line Three" &&
 107                git format-patch --stdout first | sed -e "1d"
 108        } > patch1.eml &&
 109        {
 110                echo "X-Fake-Field: Line One" &&
 111                echo "X-Fake-Field: Line Two" &&
 112                echo "X-Fake-Field: Line Three" &&
 113                git format-patch --stdout first | sed -e "1d"
 114        } | append_cr >patch1-crlf.eml &&
 115        {
 116                printf "%255s\\n" ""
 117                echo "X-Fake-Field: Line One" &&
 118                echo "X-Fake-Field: Line Two" &&
 119                echo "X-Fake-Field: Line Three" &&
 120                git format-patch --stdout first | sed -e "1d"
 121        } > patch1-ws.eml &&
 122        {
 123                sed -ne "1p" msg &&
 124                echo &&
 125                echo "From: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" &&
 126                echo "Date: $GIT_AUTHOR_DATE" &&
 127                echo &&
 128                sed -e "1,2d" msg &&
 129                echo "---" &&
 130                git diff-tree --no-commit-id --stat -p second
 131        } >patch1-stgit.eml &&
 132        mkdir stgit-series &&
 133        cp patch1-stgit.eml stgit-series/patch &&
 134        {
 135                echo "# This series applies on GIT commit $(git rev-parse first)" &&
 136                echo "patch"
 137        } >stgit-series/series &&
 138        {
 139                echo "# HG changeset patch" &&
 140                echo "# User $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" &&
 141                echo "# Date $test_tick 25200" &&
 142                echo "#      $(git show --pretty="%aD" -s second)" &&
 143                echo "# Node ID $ZERO_OID" &&
 144                echo "# Parent  $ZERO_OID" &&
 145                cat msg &&
 146                echo &&
 147                git diff-tree --no-commit-id -p second
 148        } >patch1-hg.eml &&
 149
 150
 151        echo file >file &&
 152        git add file &&
 153        git commit -F msg-without-scissors-line &&
 154        git tag expected-for-scissors &&
 155        git reset --hard HEAD^ &&
 156
 157        echo file >file &&
 158        git add file &&
 159        git commit -F msg-with-scissors-line &&
 160        git tag expected-for-no-scissors &&
 161        git format-patch --stdout expected-for-no-scissors^ >patch-with-scissors-line.eml &&
 162        git reset --hard HEAD^ &&
 163
 164        sed -n -e "3,\$p" msg >file &&
 165        git add file &&
 166        test_tick &&
 167        git commit -m third &&
 168
 169        git format-patch --stdout first >patch2 &&
 170
 171        git checkout -b lorem &&
 172        sed -n -e "11,\$p" msg >file &&
 173        head -n 9 msg >>file &&
 174        test_tick &&
 175        git commit -a -m "moved stuff" &&
 176
 177        echo goodbye >another &&
 178        git add another &&
 179        test_tick &&
 180        git commit -m "added another file" &&
 181
 182        git format-patch --stdout master >lorem-move.patch &&
 183        git format-patch --no-prefix --stdout master >lorem-zero.patch &&
 184
 185        git checkout -b rename &&
 186        git mv file renamed &&
 187        git commit -m "renamed a file" &&
 188
 189        git format-patch -M --stdout lorem >rename.patch &&
 190
 191        git reset --soft lorem^ &&
 192        git commit -m "renamed a file and added another" &&
 193
 194        git format-patch -M --stdout lorem^ >rename-add.patch &&
 195
 196        # reset time
 197        sane_unset test_tick &&
 198        test_tick
 199'
 200
 201test_expect_success 'am applies patch correctly' '
 202        rm -fr .git/rebase-apply &&
 203        git reset --hard &&
 204        git checkout first &&
 205        test_tick &&
 206        git am <patch1 &&
 207        test_path_is_missing .git/rebase-apply &&
 208        git diff --exit-code second &&
 209        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 210        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 211'
 212
 213test_expect_success 'am fails if index is dirty' '
 214        test_when_finished "rm -f dirtyfile" &&
 215        rm -fr .git/rebase-apply &&
 216        git reset --hard &&
 217        git checkout first &&
 218        echo dirtyfile >dirtyfile &&
 219        git add dirtyfile &&
 220        test_must_fail git am patch1 &&
 221        test_path_is_dir .git/rebase-apply &&
 222        test_cmp_rev first HEAD
 223'
 224
 225test_expect_success 'am applies patch e-mail not in a mbox' '
 226        rm -fr .git/rebase-apply &&
 227        git reset --hard &&
 228        git checkout first &&
 229        git am patch1.eml &&
 230        test_path_is_missing .git/rebase-apply &&
 231        git diff --exit-code second &&
 232        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 233        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 234'
 235
 236test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
 237        rm -fr .git/rebase-apply &&
 238        git reset --hard &&
 239        git checkout first &&
 240        git am patch1-crlf.eml &&
 241        test_path_is_missing .git/rebase-apply &&
 242        git diff --exit-code second &&
 243        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 244        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 245'
 246
 247test_expect_success 'am applies patch e-mail with preceding whitespace' '
 248        rm -fr .git/rebase-apply &&
 249        git reset --hard &&
 250        git checkout first &&
 251        git am patch1-ws.eml &&
 252        test_path_is_missing .git/rebase-apply &&
 253        git diff --exit-code second &&
 254        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 255        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 256'
 257
 258test_expect_success 'am applies stgit patch' '
 259        rm -fr .git/rebase-apply &&
 260        git checkout -f first &&
 261        git am patch1-stgit.eml &&
 262        test_path_is_missing .git/rebase-apply &&
 263        git diff --exit-code second &&
 264        test_cmp_rev second HEAD &&
 265        test_cmp_rev second^ HEAD^
 266'
 267
 268test_expect_success 'am --patch-format=stgit applies stgit patch' '
 269        rm -fr .git/rebase-apply &&
 270        git checkout -f first &&
 271        git am --patch-format=stgit <patch1-stgit.eml &&
 272        test_path_is_missing .git/rebase-apply &&
 273        git diff --exit-code second &&
 274        test_cmp_rev second HEAD &&
 275        test_cmp_rev second^ HEAD^
 276'
 277
 278test_expect_success 'am applies stgit series' '
 279        rm -fr .git/rebase-apply &&
 280        git checkout -f first &&
 281        git am stgit-series/series &&
 282        test_path_is_missing .git/rebase-apply &&
 283        git diff --exit-code second &&
 284        test_cmp_rev second HEAD &&
 285        test_cmp_rev second^ HEAD^
 286'
 287
 288test_expect_success 'am applies hg patch' '
 289        rm -fr .git/rebase-apply &&
 290        git checkout -f first &&
 291        git am patch1-hg.eml &&
 292        test_path_is_missing .git/rebase-apply &&
 293        git diff --exit-code second &&
 294        test_cmp_rev second HEAD &&
 295        test_cmp_rev second^ HEAD^
 296'
 297
 298test_expect_success 'am --patch-format=hg applies hg patch' '
 299        rm -fr .git/rebase-apply &&
 300        git checkout -f first &&
 301        git am --patch-format=hg <patch1-hg.eml &&
 302        test_path_is_missing .git/rebase-apply &&
 303        git diff --exit-code second &&
 304        test_cmp_rev second HEAD &&
 305        test_cmp_rev second^ HEAD^
 306'
 307
 308test_expect_success 'am with applypatch-msg hook' '
 309        test_when_finished "rm -f .git/hooks/applypatch-msg" &&
 310        rm -fr .git/rebase-apply &&
 311        git reset --hard &&
 312        git checkout first &&
 313        mkdir -p .git/hooks &&
 314        write_script .git/hooks/applypatch-msg <<-\EOF &&
 315        cat "$1" >actual-msg &&
 316        echo hook-message >"$1"
 317        EOF
 318        git am patch1 &&
 319        test_path_is_missing .git/rebase-apply &&
 320        git diff --exit-code second &&
 321        echo hook-message >expected &&
 322        git log -1 --format=format:%B >actual &&
 323        test_cmp expected actual &&
 324        git log -1 --format=format:%B second >expected &&
 325        test_cmp expected actual-msg
 326'
 327
 328test_expect_success 'am with failing applypatch-msg hook' '
 329        test_when_finished "rm -f .git/hooks/applypatch-msg" &&
 330        rm -fr .git/rebase-apply &&
 331        git reset --hard &&
 332        git checkout first &&
 333        mkdir -p .git/hooks &&
 334        write_script .git/hooks/applypatch-msg <<-\EOF &&
 335        exit 1
 336        EOF
 337        test_must_fail git am patch1 &&
 338        test_path_is_dir .git/rebase-apply &&
 339        git diff --exit-code first &&
 340        test_cmp_rev first HEAD
 341'
 342
 343test_expect_success 'am with pre-applypatch hook' '
 344        test_when_finished "rm -f .git/hooks/pre-applypatch" &&
 345        rm -fr .git/rebase-apply &&
 346        git reset --hard &&
 347        git checkout first &&
 348        mkdir -p .git/hooks &&
 349        write_script .git/hooks/pre-applypatch <<-\EOF &&
 350        git diff first >diff.actual
 351        exit 0
 352        EOF
 353        git am patch1 &&
 354        test_path_is_missing .git/rebase-apply &&
 355        git diff --exit-code second &&
 356        test_cmp_rev second HEAD &&
 357        git diff first..second >diff.expected &&
 358        test_cmp diff.expected diff.actual
 359'
 360
 361test_expect_success 'am with failing pre-applypatch hook' '
 362        test_when_finished "rm -f .git/hooks/pre-applypatch" &&
 363        rm -fr .git/rebase-apply &&
 364        git reset --hard &&
 365        git checkout first &&
 366        mkdir -p .git/hooks &&
 367        write_script .git/hooks/pre-applypatch <<-\EOF &&
 368        exit 1
 369        EOF
 370        test_must_fail git am patch1 &&
 371        test_path_is_dir .git/rebase-apply &&
 372        git diff --exit-code second &&
 373        test_cmp_rev first HEAD
 374'
 375
 376test_expect_success 'am with post-applypatch hook' '
 377        test_when_finished "rm -f .git/hooks/post-applypatch" &&
 378        rm -fr .git/rebase-apply &&
 379        git reset --hard &&
 380        git checkout first &&
 381        mkdir -p .git/hooks &&
 382        write_script .git/hooks/post-applypatch <<-\EOF &&
 383        git rev-parse HEAD >head.actual
 384        git diff second >diff.actual
 385        exit 0
 386        EOF
 387        git am patch1 &&
 388        test_path_is_missing .git/rebase-apply &&
 389        test_cmp_rev second HEAD &&
 390        git rev-parse second >head.expected &&
 391        test_cmp head.expected head.actual &&
 392        git diff second >diff.expected &&
 393        test_cmp diff.expected diff.actual
 394'
 395
 396test_expect_success 'am with failing post-applypatch hook' '
 397        test_when_finished "rm -f .git/hooks/post-applypatch" &&
 398        rm -fr .git/rebase-apply &&
 399        git reset --hard &&
 400        git checkout first &&
 401        mkdir -p .git/hooks &&
 402        write_script .git/hooks/post-applypatch <<-\EOF &&
 403        git rev-parse HEAD >head.actual
 404        exit 1
 405        EOF
 406        git am patch1 &&
 407        test_path_is_missing .git/rebase-apply &&
 408        git diff --exit-code second &&
 409        test_cmp_rev second HEAD &&
 410        git rev-parse second >head.expected &&
 411        test_cmp head.expected head.actual
 412'
 413
 414test_expect_success 'am --scissors cuts the message at the scissors line' '
 415        rm -fr .git/rebase-apply &&
 416        git reset --hard &&
 417        git checkout second &&
 418        git am --scissors patch-with-scissors-line.eml &&
 419        test_path_is_missing .git/rebase-apply &&
 420        git diff --exit-code expected-for-scissors &&
 421        test_cmp_rev expected-for-scissors HEAD
 422'
 423
 424test_expect_success 'am --no-scissors overrides mailinfo.scissors' '
 425        rm -fr .git/rebase-apply &&
 426        git reset --hard &&
 427        git checkout second &&
 428        test_config mailinfo.scissors true &&
 429        git am --no-scissors patch-with-scissors-line.eml &&
 430        test_path_is_missing .git/rebase-apply &&
 431        git diff --exit-code expected-for-no-scissors &&
 432        test_cmp_rev expected-for-no-scissors HEAD
 433'
 434
 435test_expect_success 'setup: new author and committer' '
 436        GIT_AUTHOR_NAME="Another Thor" &&
 437        GIT_AUTHOR_EMAIL="a.thor@example.com" &&
 438        GIT_COMMITTER_NAME="Co M Miter" &&
 439        GIT_COMMITTER_EMAIL="c.miter@example.com" &&
 440        export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
 441'
 442
 443compare () {
 444        a=$(git cat-file commit "$2" | grep "^$1 ") &&
 445        b=$(git cat-file commit "$3" | grep "^$1 ") &&
 446        test "$a" = "$b"
 447}
 448
 449test_expect_success 'am changes committer and keeps author' '
 450        test_tick &&
 451        rm -fr .git/rebase-apply &&
 452        git reset --hard &&
 453        git checkout first &&
 454        git am patch2 &&
 455        test_path_is_missing .git/rebase-apply &&
 456        test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
 457        git diff --exit-code master..HEAD &&
 458        git diff --exit-code master^..HEAD^ &&
 459        compare author master HEAD &&
 460        compare author master^ HEAD^ &&
 461        test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
 462             "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
 463'
 464
 465test_expect_success 'am --signoff adds Signed-off-by: line' '
 466        rm -fr .git/rebase-apply &&
 467        git reset --hard &&
 468        git checkout -b master2 first &&
 469        git am --signoff <patch2 &&
 470        {
 471                printf "third\n\nSigned-off-by: %s <%s>\n\n" \
 472                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" &&
 473                cat msg &&
 474                printf "Signed-off-by: %s <%s>\n\n" \
 475                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL"
 476        } >expected-log &&
 477        git log --pretty=%B -2 HEAD >actual &&
 478        test_cmp expected-log actual
 479'
 480
 481test_expect_success 'am stays in branch' '
 482        echo refs/heads/master2 >expected &&
 483        git symbolic-ref HEAD >actual &&
 484        test_cmp expected actual
 485'
 486
 487test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
 488        git format-patch --stdout first >patch3 &&
 489        git reset --hard first &&
 490        git am --signoff <patch3 &&
 491        git log --pretty=%B -2 HEAD >actual &&
 492        test_cmp expected-log actual
 493'
 494
 495test_expect_success 'am --signoff adds Signed-off-by: if another author is preset' '
 496        NAME="A N Other" &&
 497        EMAIL="a.n.other@example.com" &&
 498        {
 499                printf "third\n\nSigned-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
 500                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
 501                        "$NAME" "$EMAIL" &&
 502                cat msg &&
 503                printf "Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
 504                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
 505                        "$NAME" "$EMAIL"
 506        } >expected-log &&
 507        git reset --hard first &&
 508        GIT_COMMITTER_NAME="$NAME" GIT_COMMITTER_EMAIL="$EMAIL" \
 509                git am --signoff <patch3 &&
 510        git log --pretty=%B -2 HEAD >actual &&
 511        test_cmp expected-log actual
 512'
 513
 514test_expect_success 'am --signoff duplicates Signed-off-by: if it is not the last one' '
 515        NAME="A N Other" &&
 516        EMAIL="a.n.other@example.com" &&
 517        {
 518                printf "third\n\nSigned-off-by: %s <%s>\n\
 519Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
 520                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
 521                        "$NAME" "$EMAIL" \
 522                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" &&
 523                cat msg &&
 524                printf "Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\
 525Signed-off-by: %s <%s>\n\n" \
 526                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
 527                        "$NAME" "$EMAIL" \
 528                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL"
 529        } >expected-log &&
 530        git format-patch --stdout first >patch3 &&
 531        git reset --hard first &&
 532        git am --signoff <patch3 &&
 533        git log --pretty=%B -2 HEAD >actual &&
 534        test_cmp expected-log actual
 535'
 536
 537test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
 538        git format-patch --stdout HEAD^ >tmp &&
 539        sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," tmp >patch4 &&
 540        git reset --hard HEAD^ &&
 541        git am <patch4 &&
 542        git rev-parse HEAD >expected &&
 543        git rev-parse master2 >actual &&
 544        test_cmp expected actual
 545'
 546
 547test_expect_success 'am --keep really keeps the subject' '
 548        rm -fr .git/rebase-apply &&
 549        git reset --hard &&
 550        git checkout HEAD^ &&
 551        git am --keep patch4 &&
 552        test_path_is_missing .git/rebase-apply &&
 553        git cat-file commit HEAD >actual &&
 554        grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual
 555'
 556
 557test_expect_success 'am --keep-non-patch really keeps the non-patch part' '
 558        rm -fr .git/rebase-apply &&
 559        git reset --hard &&
 560        git checkout HEAD^ &&
 561        git am --keep-non-patch patch4 &&
 562        test_path_is_missing .git/rebase-apply &&
 563        git cat-file commit HEAD >actual &&
 564        grep "^\[foo\] third" actual
 565'
 566
 567test_expect_success 'setup am -3' '
 568        rm -fr .git/rebase-apply &&
 569        git reset --hard &&
 570        git checkout -b base3way master2 &&
 571        sed -n -e "3,\$p" msg >file &&
 572        head -n 9 msg >>file &&
 573        git add file &&
 574        test_tick &&
 575        git commit -m "copied stuff"
 576'
 577
 578test_expect_success 'am -3 falls back to 3-way merge' '
 579        rm -fr .git/rebase-apply &&
 580        git reset --hard &&
 581        git checkout -b lorem2 base3way &&
 582        git am -3 lorem-move.patch &&
 583        test_path_is_missing .git/rebase-apply &&
 584        git diff --exit-code lorem
 585'
 586
 587test_expect_success 'am -3 -p0 can read --no-prefix patch' '
 588        rm -fr .git/rebase-apply &&
 589        git reset --hard &&
 590        git checkout -b lorem3 base3way &&
 591        git am -3 -p0 lorem-zero.patch &&
 592        test_path_is_missing .git/rebase-apply &&
 593        git diff --exit-code lorem
 594'
 595
 596test_expect_success 'am with config am.threeWay falls back to 3-way merge' '
 597        rm -fr .git/rebase-apply &&
 598        git reset --hard &&
 599        git checkout -b lorem4 base3way &&
 600        test_config am.threeWay 1 &&
 601        git am lorem-move.patch &&
 602        test_path_is_missing .git/rebase-apply &&
 603        git diff --exit-code lorem
 604'
 605
 606test_expect_success 'am with config am.threeWay overridden by --no-3way' '
 607        rm -fr .git/rebase-apply &&
 608        git reset --hard &&
 609        git checkout -b lorem5 base3way &&
 610        test_config am.threeWay 1 &&
 611        test_must_fail git am --no-3way lorem-move.patch &&
 612        test_path_is_dir .git/rebase-apply
 613'
 614
 615test_expect_success 'am can rename a file' '
 616        grep "^rename from" rename.patch &&
 617        rm -fr .git/rebase-apply &&
 618        git reset --hard &&
 619        git checkout lorem^0 &&
 620        git am rename.patch &&
 621        test_path_is_missing .git/rebase-apply &&
 622        git update-index --refresh &&
 623        git diff --exit-code rename
 624'
 625
 626test_expect_success 'am -3 can rename a file' '
 627        grep "^rename from" rename.patch &&
 628        rm -fr .git/rebase-apply &&
 629        git reset --hard &&
 630        git checkout lorem^0 &&
 631        git am -3 rename.patch &&
 632        test_path_is_missing .git/rebase-apply &&
 633        git update-index --refresh &&
 634        git diff --exit-code rename
 635'
 636
 637test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
 638        grep "^rename from" rename-add.patch &&
 639        rm -fr .git/rebase-apply &&
 640        git reset --hard &&
 641        git checkout lorem^0 &&
 642        git am -3 rename-add.patch &&
 643        test_path_is_missing .git/rebase-apply &&
 644        git update-index --refresh &&
 645        git diff --exit-code rename
 646'
 647
 648test_expect_success 'am -3 -q is quiet' '
 649        rm -fr .git/rebase-apply &&
 650        git checkout -f lorem2 &&
 651        git reset base3way --hard &&
 652        git am -3 -q lorem-move.patch >output.out 2>&1 &&
 653        test_must_be_empty output.out
 654'
 655
 656test_expect_success 'am pauses on conflict' '
 657        rm -fr .git/rebase-apply &&
 658        git reset --hard &&
 659        git checkout lorem2^^ &&
 660        test_must_fail git am lorem-move.patch &&
 661        test -d .git/rebase-apply
 662'
 663
 664test_expect_success 'am --show-current-patch' '
 665        git am --show-current-patch >actual.patch &&
 666        test_cmp .git/rebase-apply/0001 actual.patch
 667'
 668
 669test_expect_success 'am --skip works' '
 670        echo goodbye >expected &&
 671        git am --skip &&
 672        test_path_is_missing .git/rebase-apply &&
 673        git diff --exit-code lorem2^^ -- file &&
 674        test_cmp expected another
 675'
 676
 677test_expect_success 'am --abort removes a stray directory' '
 678        mkdir .git/rebase-apply &&
 679        git am --abort &&
 680        test_path_is_missing .git/rebase-apply
 681'
 682
 683test_expect_success 'am refuses patches when paused' '
 684        rm -fr .git/rebase-apply &&
 685        git reset --hard &&
 686        git checkout lorem2^^ &&
 687
 688        test_must_fail git am lorem-move.patch &&
 689        test_path_is_dir .git/rebase-apply &&
 690        test_cmp_rev lorem2^^ HEAD &&
 691
 692        test_must_fail git am <lorem-move.patch &&
 693        test_path_is_dir .git/rebase-apply &&
 694        test_cmp_rev lorem2^^ HEAD
 695'
 696
 697test_expect_success 'am --resolved works' '
 698        echo goodbye >expected &&
 699        rm -fr .git/rebase-apply &&
 700        git reset --hard &&
 701        git checkout lorem2^^ &&
 702        test_must_fail git am lorem-move.patch &&
 703        test -d .git/rebase-apply &&
 704        echo resolved >>file &&
 705        git add file &&
 706        git am --resolved &&
 707        test_path_is_missing .git/rebase-apply &&
 708        test_cmp expected another
 709'
 710
 711test_expect_success 'am --resolved fails if index has no changes' '
 712        rm -fr .git/rebase-apply &&
 713        git reset --hard &&
 714        git checkout lorem2^^ &&
 715        test_must_fail git am lorem-move.patch &&
 716        test_path_is_dir .git/rebase-apply &&
 717        test_cmp_rev lorem2^^ HEAD &&
 718        test_must_fail git am --resolved &&
 719        test_path_is_dir .git/rebase-apply &&
 720        test_cmp_rev lorem2^^ HEAD
 721'
 722
 723test_expect_success 'am --resolved fails if index has unmerged entries' '
 724        rm -fr .git/rebase-apply &&
 725        git reset --hard &&
 726        git checkout second &&
 727        test_must_fail git am -3 lorem-move.patch &&
 728        test_path_is_dir .git/rebase-apply &&
 729        test_cmp_rev second HEAD &&
 730        test_must_fail git am --resolved >err &&
 731        test_path_is_dir .git/rebase-apply &&
 732        test_cmp_rev second HEAD &&
 733        test_i18ngrep "still have unmerged paths" err
 734'
 735
 736test_expect_success 'am takes patches from a Pine mailbox' '
 737        rm -fr .git/rebase-apply &&
 738        git reset --hard &&
 739        git checkout first &&
 740        cat pine patch1 | git am &&
 741        test_path_is_missing .git/rebase-apply &&
 742        git diff --exit-code master^..HEAD
 743'
 744
 745test_expect_success 'am fails on mail without patch' '
 746        rm -fr .git/rebase-apply &&
 747        git reset --hard &&
 748        test_must_fail git am <failmail &&
 749        git am --abort &&
 750        test_path_is_missing .git/rebase-apply
 751'
 752
 753test_expect_success 'am fails on empty patch' '
 754        rm -fr .git/rebase-apply &&
 755        git reset --hard &&
 756        echo "---" >>failmail &&
 757        test_must_fail git am <failmail &&
 758        git am --skip &&
 759        test_path_is_missing .git/rebase-apply
 760'
 761
 762test_expect_success 'am works from stdin in subdirectory' '
 763        rm -fr subdir &&
 764        rm -fr .git/rebase-apply &&
 765        git reset --hard &&
 766        git checkout first &&
 767        (
 768                mkdir -p subdir &&
 769                cd subdir &&
 770                git am <../patch1
 771        ) &&
 772        git diff --exit-code second
 773'
 774
 775test_expect_success 'am works from file (relative path given) in subdirectory' '
 776        rm -fr subdir &&
 777        rm -fr .git/rebase-apply &&
 778        git reset --hard &&
 779        git checkout first &&
 780        (
 781                mkdir -p subdir &&
 782                cd subdir &&
 783                git am ../patch1
 784        ) &&
 785        git diff --exit-code second
 786'
 787
 788test_expect_success 'am works from file (absolute path given) in subdirectory' '
 789        rm -fr subdir &&
 790        rm -fr .git/rebase-apply &&
 791        git reset --hard &&
 792        git checkout first &&
 793        P=$(pwd) &&
 794        (
 795                mkdir -p subdir &&
 796                cd subdir &&
 797                git am "$P/patch1"
 798        ) &&
 799        git diff --exit-code second
 800'
 801
 802test_expect_success 'am --committer-date-is-author-date' '
 803        rm -fr .git/rebase-apply &&
 804        git reset --hard &&
 805        git checkout first &&
 806        test_tick &&
 807        git am --committer-date-is-author-date patch1 &&
 808        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 809        sed -ne "/^author /s/.*> //p" head1 >at &&
 810        sed -ne "/^committer /s/.*> //p" head1 >ct &&
 811        test_cmp at ct
 812'
 813
 814test_expect_success 'am without --committer-date-is-author-date' '
 815        rm -fr .git/rebase-apply &&
 816        git reset --hard &&
 817        git checkout first &&
 818        test_tick &&
 819        git am patch1 &&
 820        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 821        sed -ne "/^author /s/.*> //p" head1 >at &&
 822        sed -ne "/^committer /s/.*> //p" head1 >ct &&
 823        ! test_cmp at ct
 824'
 825
 826# This checks for +0000 because TZ is set to UTC and that should
 827# show up when the current time is used. The date in message is set
 828# by test_tick that uses -0700 timezone; if this feature does not
 829# work, we will see that instead of +0000.
 830test_expect_success 'am --ignore-date' '
 831        rm -fr .git/rebase-apply &&
 832        git reset --hard &&
 833        git checkout first &&
 834        test_tick &&
 835        git am --ignore-date patch1 &&
 836        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 837        sed -ne "/^author /s/.*> //p" head1 >at &&
 838        grep "+0000" at
 839'
 840
 841test_expect_success 'am into an unborn branch' '
 842        git rev-parse first^{tree} >expected &&
 843        rm -fr .git/rebase-apply &&
 844        git reset --hard &&
 845        rm -fr subdir &&
 846        mkdir subdir &&
 847        git format-patch --numbered-files -o subdir -1 first &&
 848        (
 849                cd subdir &&
 850                git init &&
 851                git am 1
 852        ) &&
 853        (
 854                cd subdir &&
 855                git rev-parse HEAD^{tree} >../actual
 856        ) &&
 857        test_cmp expected actual
 858'
 859
 860test_expect_success 'am newline in subject' '
 861        rm -fr .git/rebase-apply &&
 862        git reset --hard &&
 863        git checkout first &&
 864        test_tick &&
 865        sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
 866        git am <patchnl >output.out 2>&1 &&
 867        test_i18ngrep "^Applying: second \\\n foo$" output.out
 868'
 869
 870test_expect_success 'am -q is quiet' '
 871        rm -fr .git/rebase-apply &&
 872        git reset --hard &&
 873        git checkout first &&
 874        test_tick &&
 875        git am -q <patch1 >output.out 2>&1 &&
 876        test_must_be_empty output.out
 877'
 878
 879test_expect_success 'am empty-file does not infloop' '
 880        rm -fr .git/rebase-apply &&
 881        git reset --hard &&
 882        touch empty-file &&
 883        test_tick &&
 884        test_must_fail git am empty-file 2>actual &&
 885        echo Patch format detection failed. >expected &&
 886        test_i18ncmp expected actual
 887'
 888
 889test_expect_success 'am --message-id really adds the message id' '
 890        rm -fr .git/rebase-apply &&
 891        git reset --hard &&
 892        git checkout HEAD^ &&
 893        git am --message-id patch1.eml &&
 894        test_path_is_missing .git/rebase-apply &&
 895        git cat-file commit HEAD | tail -n1 >actual &&
 896        grep Message-Id patch1.eml >expected &&
 897        test_cmp expected actual
 898'
 899
 900test_expect_success 'am.messageid really adds the message id' '
 901        rm -fr .git/rebase-apply &&
 902        git reset --hard &&
 903        git checkout HEAD^ &&
 904        test_config am.messageid true &&
 905        git am patch1.eml &&
 906        test_path_is_missing .git/rebase-apply &&
 907        git cat-file commit HEAD | tail -n1 >actual &&
 908        grep Message-Id patch1.eml >expected &&
 909        test_cmp expected actual
 910'
 911
 912test_expect_success 'am --message-id -s signs off after the message id' '
 913        rm -fr .git/rebase-apply &&
 914        git reset --hard &&
 915        git checkout HEAD^ &&
 916        git am -s --message-id patch1.eml &&
 917        test_path_is_missing .git/rebase-apply &&
 918        git cat-file commit HEAD | tail -n2 | head -n1 >actual &&
 919        grep Message-Id patch1.eml >expected &&
 920        test_cmp expected actual
 921'
 922
 923test_expect_success 'am -3 works with rerere' '
 924        rm -fr .git/rebase-apply &&
 925        git reset --hard &&
 926
 927        # make patches one->two and two->three...
 928        test_commit one file &&
 929        test_commit two file &&
 930        test_commit three file &&
 931        git format-patch -2 --stdout >seq.patch &&
 932
 933        # and create a situation that conflicts...
 934        git reset --hard one &&
 935        test_commit other file &&
 936
 937        # enable rerere...
 938        test_config rerere.enabled true &&
 939        test_when_finished "rm -rf .git/rr-cache" &&
 940
 941        # ...and apply. Our resolution is to skip the first
 942        # patch, and the rerere the second one.
 943        test_must_fail git am -3 seq.patch &&
 944        test_must_fail git am --skip &&
 945        echo resolved >file &&
 946        git add file &&
 947        git am --resolved &&
 948
 949        # now apply again, and confirm that rerere engaged (we still
 950        # expect failure from am because rerere does not auto-commit
 951        # for us).
 952        git reset --hard other &&
 953        test_must_fail git am -3 seq.patch &&
 954        test_must_fail git am --skip &&
 955        echo resolved >expect &&
 956        test_cmp expect file
 957'
 958
 959test_expect_success 'am -s unexpected trailer block' '
 960        rm -fr .git/rebase-apply &&
 961        git reset --hard &&
 962        echo signed >file &&
 963        git add file &&
 964        cat >msg <<-EOF &&
 965        subject here
 966
 967        Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
 968        [jc: tweaked log message]
 969        Signed-off-by: J C H <j@c.h>
 970        EOF
 971        git commit -F msg &&
 972        git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
 973        git format-patch --stdout -1 >patch &&
 974
 975        git reset --hard HEAD^ &&
 976        git am -s patch &&
 977        (
 978                cat original &&
 979                echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
 980        ) >expect &&
 981        git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
 982        test_cmp expect actual &&
 983
 984        cat >msg <<-\EOF &&
 985        subject here
 986
 987        We make sure that there is a blank line between the log
 988        message proper and Signed-off-by: line added.
 989        EOF
 990        git reset HEAD^ &&
 991        git commit -F msg file &&
 992        git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
 993        git format-patch --stdout -1 >patch &&
 994
 995        git reset --hard HEAD^ &&
 996        git am -s patch &&
 997
 998        (
 999                cat original &&
1000                echo &&
1001                echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
1002        ) >expect &&
1003        git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
1004        test_cmp expect actual
1005'
1006
1007test_expect_success 'am --patch-format=mboxrd handles mboxrd' '
1008        rm -fr .git/rebase-apply &&
1009        git checkout -f first &&
1010        echo mboxrd >>file &&
1011        git add file &&
1012        cat >msg <<-\INPUT_END &&
1013        mboxrd should escape the body
1014
1015        From could trip up a loose mbox parser
1016        >From extra escape for reversibility
1017        INPUT_END
1018        git commit -F msg &&
1019        git format-patch --pretty=mboxrd --stdout -1 >mboxrd1 &&
1020        grep "^>From could trip up a loose mbox parser" mboxrd1 &&
1021        git checkout -f first &&
1022        git am --patch-format=mboxrd mboxrd1 &&
1023        git cat-file commit HEAD | tail -n4 >out &&
1024        test_cmp msg out
1025'
1026
1027test_expect_success 'am works with multi-line in-body headers' '
1028        FORTY="String that has a length of more than forty characters" &&
1029        LONG="$FORTY $FORTY" &&
1030        rm -fr .git/rebase-apply &&
1031        git checkout -f first &&
1032        echo one >> file &&
1033        git commit -am "$LONG
1034
1035    Body test" --author="$LONG <long@example.com>" &&
1036        git format-patch --stdout -1 >patch &&
1037        # bump from, date, and subject down to in-body header
1038        perl -lpe "
1039                if (/^From:/) {
1040                        print \"From: x <x\@example.com>\";
1041                        print \"Date: Sat, 1 Jan 2000 00:00:00 +0000\";
1042                        print \"Subject: x\n\";
1043                }
1044        " patch >msg &&
1045        git checkout HEAD^ &&
1046        git am msg &&
1047        # Ensure that the author and full message are present
1048        git cat-file commit HEAD | grep "^author.*long@example.com" &&
1049        git cat-file commit HEAD | grep "^$LONG$"
1050'
1051
1052test_expect_success 'am --quit keeps HEAD where it is' '
1053        mkdir .git/rebase-apply &&
1054        >.git/rebase-apply/last &&
1055        >.git/rebase-apply/next &&
1056        git rev-parse HEAD^ >.git/ORIG_HEAD &&
1057        git rev-parse HEAD >expected &&
1058        git am --quit &&
1059        test_path_is_missing .git/rebase-apply &&
1060        git rev-parse HEAD >actual &&
1061        test_cmp expected actual
1062'
1063
1064test_done