t / t4150-am.shon commit merge-recursive: fix overwriting dirty files involved in renames (e0052f4)
   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 >scissors-msg <<-\EOF &&
  73        Test git-am with scissors line
  74
  75        This line should be included in the commit message.
  76        EOF
  77
  78        cat - scissors-msg >no-scissors-msg <<-\EOF &&
  79        This line should not be included in the commit message with --scissors enabled.
  80
  81         - - >8 - - remove everything above this line - - >8 - -
  82
  83        EOF
  84
  85        signoff="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
  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 $_z40" &&
 144                echo "# Parent  $_z40" &&
 145                cat msg &&
 146                echo &&
 147                git diff-tree --no-commit-id -p second
 148        } >patch1-hg.eml &&
 149
 150
 151        echo scissors-file >scissors-file &&
 152        git add scissors-file &&
 153        git commit -F scissors-msg &&
 154        git tag scissors &&
 155        git format-patch --stdout scissors^ >scissors-patch.eml &&
 156        git reset --hard HEAD^ &&
 157
 158        echo no-scissors-file >no-scissors-file &&
 159        git add no-scissors-file &&
 160        git commit -F no-scissors-msg &&
 161        git tag no-scissors &&
 162        git format-patch --stdout no-scissors^ >no-scissors-patch.eml &&
 163        git reset --hard HEAD^ &&
 164
 165        sed -n -e "3,\$p" msg >file &&
 166        git add file &&
 167        test_tick &&
 168        git commit -m third &&
 169
 170        git format-patch --stdout first >patch2 &&
 171
 172        git checkout -b lorem &&
 173        sed -n -e "11,\$p" msg >file &&
 174        head -n 9 msg >>file &&
 175        test_tick &&
 176        git commit -a -m "moved stuff" &&
 177
 178        echo goodbye >another &&
 179        git add another &&
 180        test_tick &&
 181        git commit -m "added another file" &&
 182
 183        git format-patch --stdout master >lorem-move.patch &&
 184        git format-patch --no-prefix --stdout master >lorem-zero.patch &&
 185
 186        git checkout -b rename &&
 187        git mv file renamed &&
 188        git commit -m "renamed a file" &&
 189
 190        git format-patch -M --stdout lorem >rename.patch &&
 191
 192        git reset --soft lorem^ &&
 193        git commit -m "renamed a file and added another" &&
 194
 195        git format-patch -M --stdout lorem^ >rename-add.patch &&
 196
 197        # reset time
 198        sane_unset test_tick &&
 199        test_tick
 200'
 201
 202test_expect_success 'am applies patch correctly' '
 203        rm -fr .git/rebase-apply &&
 204        git reset --hard &&
 205        git checkout first &&
 206        test_tick &&
 207        git am <patch1 &&
 208        test_path_is_missing .git/rebase-apply &&
 209        git diff --exit-code second &&
 210        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 211        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 212'
 213
 214test_expect_success 'am fails if index is dirty' '
 215        test_when_finished "rm -f dirtyfile" &&
 216        rm -fr .git/rebase-apply &&
 217        git reset --hard &&
 218        git checkout first &&
 219        echo dirtyfile >dirtyfile &&
 220        git add dirtyfile &&
 221        test_must_fail git am patch1 &&
 222        test_path_is_dir .git/rebase-apply &&
 223        test_cmp_rev first HEAD
 224'
 225
 226test_expect_success 'am applies patch e-mail not in a mbox' '
 227        rm -fr .git/rebase-apply &&
 228        git reset --hard &&
 229        git checkout first &&
 230        git am patch1.eml &&
 231        test_path_is_missing .git/rebase-apply &&
 232        git diff --exit-code second &&
 233        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 234        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 235'
 236
 237test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
 238        rm -fr .git/rebase-apply &&
 239        git reset --hard &&
 240        git checkout first &&
 241        git am patch1-crlf.eml &&
 242        test_path_is_missing .git/rebase-apply &&
 243        git diff --exit-code second &&
 244        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 245        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 246'
 247
 248test_expect_success 'am applies patch e-mail with preceding whitespace' '
 249        rm -fr .git/rebase-apply &&
 250        git reset --hard &&
 251        git checkout first &&
 252        git am patch1-ws.eml &&
 253        test_path_is_missing .git/rebase-apply &&
 254        git diff --exit-code second &&
 255        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 256        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 257'
 258
 259test_expect_success 'am applies stgit patch' '
 260        rm -fr .git/rebase-apply &&
 261        git checkout -f first &&
 262        git am patch1-stgit.eml &&
 263        test_path_is_missing .git/rebase-apply &&
 264        git diff --exit-code second &&
 265        test_cmp_rev second HEAD &&
 266        test_cmp_rev second^ HEAD^
 267'
 268
 269test_expect_success 'am --patch-format=stgit applies stgit patch' '
 270        rm -fr .git/rebase-apply &&
 271        git checkout -f first &&
 272        git am --patch-format=stgit <patch1-stgit.eml &&
 273        test_path_is_missing .git/rebase-apply &&
 274        git diff --exit-code second &&
 275        test_cmp_rev second HEAD &&
 276        test_cmp_rev second^ HEAD^
 277'
 278
 279test_expect_success 'am applies stgit series' '
 280        rm -fr .git/rebase-apply &&
 281        git checkout -f first &&
 282        git am stgit-series/series &&
 283        test_path_is_missing .git/rebase-apply &&
 284        git diff --exit-code second &&
 285        test_cmp_rev second HEAD &&
 286        test_cmp_rev second^ HEAD^
 287'
 288
 289test_expect_success 'am applies hg patch' '
 290        rm -fr .git/rebase-apply &&
 291        git checkout -f first &&
 292        git am patch1-hg.eml &&
 293        test_path_is_missing .git/rebase-apply &&
 294        git diff --exit-code second &&
 295        test_cmp_rev second HEAD &&
 296        test_cmp_rev second^ HEAD^
 297'
 298
 299test_expect_success 'am --patch-format=hg applies hg patch' '
 300        rm -fr .git/rebase-apply &&
 301        git checkout -f first &&
 302        git am --patch-format=hg <patch1-hg.eml &&
 303        test_path_is_missing .git/rebase-apply &&
 304        git diff --exit-code second &&
 305        test_cmp_rev second HEAD &&
 306        test_cmp_rev second^ HEAD^
 307'
 308
 309test_expect_success 'am with applypatch-msg hook' '
 310        test_when_finished "rm -f .git/hooks/applypatch-msg" &&
 311        rm -fr .git/rebase-apply &&
 312        git reset --hard &&
 313        git checkout first &&
 314        mkdir -p .git/hooks &&
 315        write_script .git/hooks/applypatch-msg <<-\EOF &&
 316        cat "$1" >actual-msg &&
 317        echo hook-message >"$1"
 318        EOF
 319        git am patch1 &&
 320        test_path_is_missing .git/rebase-apply &&
 321        git diff --exit-code second &&
 322        echo hook-message >expected &&
 323        git log -1 --format=format:%B >actual &&
 324        test_cmp expected actual &&
 325        git log -1 --format=format:%B second >expected &&
 326        test_cmp expected actual-msg
 327'
 328
 329test_expect_success 'am with failing applypatch-msg hook' '
 330        test_when_finished "rm -f .git/hooks/applypatch-msg" &&
 331        rm -fr .git/rebase-apply &&
 332        git reset --hard &&
 333        git checkout first &&
 334        mkdir -p .git/hooks &&
 335        write_script .git/hooks/applypatch-msg <<-\EOF &&
 336        exit 1
 337        EOF
 338        test_must_fail git am patch1 &&
 339        test_path_is_dir .git/rebase-apply &&
 340        git diff --exit-code first &&
 341        test_cmp_rev first HEAD
 342'
 343
 344test_expect_success 'am with pre-applypatch hook' '
 345        test_when_finished "rm -f .git/hooks/pre-applypatch" &&
 346        rm -fr .git/rebase-apply &&
 347        git reset --hard &&
 348        git checkout first &&
 349        mkdir -p .git/hooks &&
 350        write_script .git/hooks/pre-applypatch <<-\EOF &&
 351        git diff first >diff.actual
 352        exit 0
 353        EOF
 354        git am patch1 &&
 355        test_path_is_missing .git/rebase-apply &&
 356        git diff --exit-code second &&
 357        test_cmp_rev second HEAD &&
 358        git diff first..second >diff.expected &&
 359        test_cmp diff.expected diff.actual
 360'
 361
 362test_expect_success 'am with failing pre-applypatch hook' '
 363        test_when_finished "rm -f .git/hooks/pre-applypatch" &&
 364        rm -fr .git/rebase-apply &&
 365        git reset --hard &&
 366        git checkout first &&
 367        mkdir -p .git/hooks &&
 368        write_script .git/hooks/pre-applypatch <<-\EOF &&
 369        exit 1
 370        EOF
 371        test_must_fail git am patch1 &&
 372        test_path_is_dir .git/rebase-apply &&
 373        git diff --exit-code second &&
 374        test_cmp_rev first HEAD
 375'
 376
 377test_expect_success 'am with post-applypatch hook' '
 378        test_when_finished "rm -f .git/hooks/post-applypatch" &&
 379        rm -fr .git/rebase-apply &&
 380        git reset --hard &&
 381        git checkout first &&
 382        mkdir -p .git/hooks &&
 383        write_script .git/hooks/post-applypatch <<-\EOF &&
 384        git rev-parse HEAD >head.actual
 385        git diff second >diff.actual
 386        exit 0
 387        EOF
 388        git am patch1 &&
 389        test_path_is_missing .git/rebase-apply &&
 390        test_cmp_rev second HEAD &&
 391        git rev-parse second >head.expected &&
 392        test_cmp head.expected head.actual &&
 393        git diff second >diff.expected &&
 394        test_cmp diff.expected diff.actual
 395'
 396
 397test_expect_success 'am with failing post-applypatch hook' '
 398        test_when_finished "rm -f .git/hooks/post-applypatch" &&
 399        rm -fr .git/rebase-apply &&
 400        git reset --hard &&
 401        git checkout first &&
 402        mkdir -p .git/hooks &&
 403        write_script .git/hooks/post-applypatch <<-\EOF &&
 404        git rev-parse HEAD >head.actual
 405        exit 1
 406        EOF
 407        git am patch1 &&
 408        test_path_is_missing .git/rebase-apply &&
 409        git diff --exit-code second &&
 410        test_cmp_rev second HEAD &&
 411        git rev-parse second >head.expected &&
 412        test_cmp head.expected head.actual
 413'
 414
 415test_expect_success 'am --scissors cuts the message at the scissors line' '
 416        rm -fr .git/rebase-apply &&
 417        git reset --hard &&
 418        git checkout second &&
 419        git am --scissors scissors-patch.eml &&
 420        test_path_is_missing .git/rebase-apply &&
 421        git diff --exit-code scissors &&
 422        test_cmp_rev scissors HEAD
 423'
 424
 425test_expect_success 'am --no-scissors overrides mailinfo.scissors' '
 426        rm -fr .git/rebase-apply &&
 427        git reset --hard &&
 428        git checkout second &&
 429        test_config mailinfo.scissors true &&
 430        git am --no-scissors no-scissors-patch.eml &&
 431        test_path_is_missing .git/rebase-apply &&
 432        git diff --exit-code no-scissors &&
 433        test_cmp_rev no-scissors HEAD
 434'
 435
 436test_expect_success 'setup: new author and committer' '
 437        GIT_AUTHOR_NAME="Another Thor" &&
 438        GIT_AUTHOR_EMAIL="a.thor@example.com" &&
 439        GIT_COMMITTER_NAME="Co M Miter" &&
 440        GIT_COMMITTER_EMAIL="c.miter@example.com" &&
 441        export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
 442'
 443
 444compare () {
 445        a=$(git cat-file commit "$2" | grep "^$1 ") &&
 446        b=$(git cat-file commit "$3" | grep "^$1 ") &&
 447        test "$a" = "$b"
 448}
 449
 450test_expect_success 'am changes committer and keeps author' '
 451        test_tick &&
 452        rm -fr .git/rebase-apply &&
 453        git reset --hard &&
 454        git checkout first &&
 455        git am patch2 &&
 456        test_path_is_missing .git/rebase-apply &&
 457        test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
 458        git diff --exit-code master..HEAD &&
 459        git diff --exit-code master^..HEAD^ &&
 460        compare author master HEAD &&
 461        compare author master^ HEAD^ &&
 462        test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
 463             "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
 464'
 465
 466test_expect_success 'am --signoff adds Signed-off-by: line' '
 467        rm -fr .git/rebase-apply &&
 468        git reset --hard &&
 469        git checkout -b master2 first &&
 470        git am --signoff <patch2 &&
 471        {
 472                printf "third\n\nSigned-off-by: %s <%s>\n\n" \
 473                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" &&
 474                cat msg &&
 475                printf "Signed-off-by: %s <%s>\n\n" \
 476                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL"
 477        } >expected-log &&
 478        git log --pretty=%B -2 HEAD >actual &&
 479        test_cmp expected-log actual
 480'
 481
 482test_expect_success 'am stays in branch' '
 483        echo refs/heads/master2 >expected &&
 484        git symbolic-ref HEAD >actual &&
 485        test_cmp expected actual
 486'
 487
 488test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
 489        git format-patch --stdout first >patch3 &&
 490        git reset --hard first &&
 491        git am --signoff <patch3 &&
 492        git log --pretty=%B -2 HEAD >actual &&
 493        test_cmp expected-log actual
 494'
 495
 496test_expect_success 'am --signoff adds Signed-off-by: if another author is preset' '
 497        NAME="A N Other" &&
 498        EMAIL="a.n.other@example.com" &&
 499        {
 500                printf "third\n\nSigned-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
 501                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
 502                        "$NAME" "$EMAIL" &&
 503                cat msg &&
 504                printf "Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
 505                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
 506                        "$NAME" "$EMAIL"
 507        } >expected-log &&
 508        git reset --hard first &&
 509        GIT_COMMITTER_NAME="$NAME" GIT_COMMITTER_EMAIL="$EMAIL" \
 510                git am --signoff <patch3 &&
 511        git log --pretty=%B -2 HEAD >actual &&
 512        test_cmp expected-log actual
 513'
 514
 515test_expect_success 'am --signoff duplicates Signed-off-by: if it is not the last one' '
 516        NAME="A N Other" &&
 517        EMAIL="a.n.other@example.com" &&
 518        {
 519                printf "third\n\nSigned-off-by: %s <%s>\n\
 520Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
 521                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
 522                        "$NAME" "$EMAIL" \
 523                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" &&
 524                cat msg &&
 525                printf "Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\
 526Signed-off-by: %s <%s>\n\n" \
 527                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
 528                        "$NAME" "$EMAIL" \
 529                        "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL"
 530        } >expected-log &&
 531        git format-patch --stdout first >patch3 &&
 532        git reset --hard first &&
 533        git am --signoff <patch3 &&
 534        git log --pretty=%B -2 HEAD >actual &&
 535        test_cmp expected-log actual
 536'
 537
 538test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
 539        git format-patch --stdout HEAD^ >tmp &&
 540        sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," tmp >patch4 &&
 541        git reset --hard HEAD^ &&
 542        git am <patch4 &&
 543        git rev-parse HEAD >expected &&
 544        git rev-parse master2 >actual &&
 545        test_cmp expected actual
 546'
 547
 548test_expect_success 'am --keep really keeps the subject' '
 549        rm -fr .git/rebase-apply &&
 550        git reset --hard &&
 551        git checkout HEAD^ &&
 552        git am --keep patch4 &&
 553        test_path_is_missing .git/rebase-apply &&
 554        git cat-file commit HEAD >actual &&
 555        grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual
 556'
 557
 558test_expect_success 'am --keep-non-patch really keeps the non-patch part' '
 559        rm -fr .git/rebase-apply &&
 560        git reset --hard &&
 561        git checkout HEAD^ &&
 562        git am --keep-non-patch patch4 &&
 563        test_path_is_missing .git/rebase-apply &&
 564        git cat-file commit HEAD >actual &&
 565        grep "^\[foo\] third" actual
 566'
 567
 568test_expect_success 'setup am -3' '
 569        rm -fr .git/rebase-apply &&
 570        git reset --hard &&
 571        git checkout -b base3way master2 &&
 572        sed -n -e "3,\$p" msg >file &&
 573        head -n 9 msg >>file &&
 574        git add file &&
 575        test_tick &&
 576        git commit -m "copied stuff"
 577'
 578
 579test_expect_success 'am -3 falls back to 3-way merge' '
 580        rm -fr .git/rebase-apply &&
 581        git reset --hard &&
 582        git checkout -b lorem2 base3way &&
 583        git am -3 lorem-move.patch &&
 584        test_path_is_missing .git/rebase-apply &&
 585        git diff --exit-code lorem
 586'
 587
 588test_expect_success 'am -3 -p0 can read --no-prefix patch' '
 589        rm -fr .git/rebase-apply &&
 590        git reset --hard &&
 591        git checkout -b lorem3 base3way &&
 592        git am -3 -p0 lorem-zero.patch &&
 593        test_path_is_missing .git/rebase-apply &&
 594        git diff --exit-code lorem
 595'
 596
 597test_expect_success 'am with config am.threeWay falls back to 3-way merge' '
 598        rm -fr .git/rebase-apply &&
 599        git reset --hard &&
 600        git checkout -b lorem4 base3way &&
 601        test_config am.threeWay 1 &&
 602        git am lorem-move.patch &&
 603        test_path_is_missing .git/rebase-apply &&
 604        git diff --exit-code lorem
 605'
 606
 607test_expect_success 'am with config am.threeWay overridden by --no-3way' '
 608        rm -fr .git/rebase-apply &&
 609        git reset --hard &&
 610        git checkout -b lorem5 base3way &&
 611        test_config am.threeWay 1 &&
 612        test_must_fail git am --no-3way lorem-move.patch &&
 613        test_path_is_dir .git/rebase-apply
 614'
 615
 616test_expect_success 'am can rename a file' '
 617        grep "^rename from" rename.patch &&
 618        rm -fr .git/rebase-apply &&
 619        git reset --hard &&
 620        git checkout lorem^0 &&
 621        git am rename.patch &&
 622        test_path_is_missing .git/rebase-apply &&
 623        git update-index --refresh &&
 624        git diff --exit-code rename
 625'
 626
 627test_expect_success 'am -3 can rename a file' '
 628        grep "^rename from" rename.patch &&
 629        rm -fr .git/rebase-apply &&
 630        git reset --hard &&
 631        git checkout lorem^0 &&
 632        git am -3 rename.patch &&
 633        test_path_is_missing .git/rebase-apply &&
 634        git update-index --refresh &&
 635        git diff --exit-code rename
 636'
 637
 638test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
 639        grep "^rename from" rename-add.patch &&
 640        rm -fr .git/rebase-apply &&
 641        git reset --hard &&
 642        git checkout lorem^0 &&
 643        git am -3 rename-add.patch &&
 644        test_path_is_missing .git/rebase-apply &&
 645        git update-index --refresh &&
 646        git diff --exit-code rename
 647'
 648
 649test_expect_success 'am -3 -q is quiet' '
 650        rm -fr .git/rebase-apply &&
 651        git checkout -f lorem2 &&
 652        git reset base3way --hard &&
 653        git am -3 -q lorem-move.patch >output.out 2>&1 &&
 654        ! test -s output.out
 655'
 656
 657test_expect_success 'am pauses on conflict' '
 658        rm -fr .git/rebase-apply &&
 659        git reset --hard &&
 660        git checkout lorem2^^ &&
 661        test_must_fail git am lorem-move.patch &&
 662        test -d .git/rebase-apply
 663'
 664
 665test_expect_success 'am --skip works' '
 666        echo goodbye >expected &&
 667        git am --skip &&
 668        test_path_is_missing .git/rebase-apply &&
 669        git diff --exit-code lorem2^^ -- file &&
 670        test_cmp expected another
 671'
 672
 673test_expect_success 'am --abort removes a stray directory' '
 674        mkdir .git/rebase-apply &&
 675        git am --abort &&
 676        test_path_is_missing .git/rebase-apply
 677'
 678
 679test_expect_success 'am refuses patches when paused' '
 680        rm -fr .git/rebase-apply &&
 681        git reset --hard &&
 682        git checkout lorem2^^ &&
 683
 684        test_must_fail git am lorem-move.patch &&
 685        test_path_is_dir .git/rebase-apply &&
 686        test_cmp_rev lorem2^^ HEAD &&
 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
 693test_expect_success 'am --resolved works' '
 694        echo goodbye >expected &&
 695        rm -fr .git/rebase-apply &&
 696        git reset --hard &&
 697        git checkout lorem2^^ &&
 698        test_must_fail git am lorem-move.patch &&
 699        test -d .git/rebase-apply &&
 700        echo resolved >>file &&
 701        git add file &&
 702        git am --resolved &&
 703        test_path_is_missing .git/rebase-apply &&
 704        test_cmp expected another
 705'
 706
 707test_expect_success 'am --resolved fails if index has no changes' '
 708        rm -fr .git/rebase-apply &&
 709        git reset --hard &&
 710        git checkout lorem2^^ &&
 711        test_must_fail git am lorem-move.patch &&
 712        test_path_is_dir .git/rebase-apply &&
 713        test_cmp_rev lorem2^^ HEAD &&
 714        test_must_fail git am --resolved &&
 715        test_path_is_dir .git/rebase-apply &&
 716        test_cmp_rev lorem2^^ HEAD
 717'
 718
 719test_expect_success 'am --resolved fails if index has unmerged entries' '
 720        rm -fr .git/rebase-apply &&
 721        git reset --hard &&
 722        git checkout second &&
 723        test_must_fail git am -3 lorem-move.patch &&
 724        test_path_is_dir .git/rebase-apply &&
 725        test_cmp_rev second HEAD &&
 726        test_must_fail git am --resolved >err &&
 727        test_path_is_dir .git/rebase-apply &&
 728        test_cmp_rev second HEAD &&
 729        test_i18ngrep "still have unmerged paths" err
 730'
 731
 732test_expect_success 'am takes patches from a Pine mailbox' '
 733        rm -fr .git/rebase-apply &&
 734        git reset --hard &&
 735        git checkout first &&
 736        cat pine patch1 | git am &&
 737        test_path_is_missing .git/rebase-apply &&
 738        git diff --exit-code master^..HEAD
 739'
 740
 741test_expect_success 'am fails on mail without patch' '
 742        rm -fr .git/rebase-apply &&
 743        git reset --hard &&
 744        test_must_fail git am <failmail &&
 745        git am --abort &&
 746        test_path_is_missing .git/rebase-apply
 747'
 748
 749test_expect_success 'am fails on empty patch' '
 750        rm -fr .git/rebase-apply &&
 751        git reset --hard &&
 752        echo "---" >>failmail &&
 753        test_must_fail git am <failmail &&
 754        git am --skip &&
 755        test_path_is_missing .git/rebase-apply
 756'
 757
 758test_expect_success 'am works from stdin in subdirectory' '
 759        rm -fr subdir &&
 760        rm -fr .git/rebase-apply &&
 761        git reset --hard &&
 762        git checkout first &&
 763        (
 764                mkdir -p subdir &&
 765                cd subdir &&
 766                git am <../patch1
 767        ) &&
 768        git diff --exit-code second
 769'
 770
 771test_expect_success 'am works from file (relative path given) in subdirectory' '
 772        rm -fr subdir &&
 773        rm -fr .git/rebase-apply &&
 774        git reset --hard &&
 775        git checkout first &&
 776        (
 777                mkdir -p subdir &&
 778                cd subdir &&
 779                git am ../patch1
 780        ) &&
 781        git diff --exit-code second
 782'
 783
 784test_expect_success 'am works from file (absolute path given) in subdirectory' '
 785        rm -fr subdir &&
 786        rm -fr .git/rebase-apply &&
 787        git reset --hard &&
 788        git checkout first &&
 789        P=$(pwd) &&
 790        (
 791                mkdir -p subdir &&
 792                cd subdir &&
 793                git am "$P/patch1"
 794        ) &&
 795        git diff --exit-code second
 796'
 797
 798test_expect_success 'am --committer-date-is-author-date' '
 799        rm -fr .git/rebase-apply &&
 800        git reset --hard &&
 801        git checkout first &&
 802        test_tick &&
 803        git am --committer-date-is-author-date patch1 &&
 804        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 805        sed -ne "/^author /s/.*> //p" head1 >at &&
 806        sed -ne "/^committer /s/.*> //p" head1 >ct &&
 807        test_cmp at ct
 808'
 809
 810test_expect_success 'am without --committer-date-is-author-date' '
 811        rm -fr .git/rebase-apply &&
 812        git reset --hard &&
 813        git checkout first &&
 814        test_tick &&
 815        git am patch1 &&
 816        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 817        sed -ne "/^author /s/.*> //p" head1 >at &&
 818        sed -ne "/^committer /s/.*> //p" head1 >ct &&
 819        ! test_cmp at ct
 820'
 821
 822# This checks for +0000 because TZ is set to UTC and that should
 823# show up when the current time is used. The date in message is set
 824# by test_tick that uses -0700 timezone; if this feature does not
 825# work, we will see that instead of +0000.
 826test_expect_success 'am --ignore-date' '
 827        rm -fr .git/rebase-apply &&
 828        git reset --hard &&
 829        git checkout first &&
 830        test_tick &&
 831        git am --ignore-date patch1 &&
 832        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 833        sed -ne "/^author /s/.*> //p" head1 >at &&
 834        grep "+0000" at
 835'
 836
 837test_expect_success 'am into an unborn branch' '
 838        git rev-parse first^{tree} >expected &&
 839        rm -fr .git/rebase-apply &&
 840        git reset --hard &&
 841        rm -fr subdir &&
 842        mkdir subdir &&
 843        git format-patch --numbered-files -o subdir -1 first &&
 844        (
 845                cd subdir &&
 846                git init &&
 847                git am 1
 848        ) &&
 849        (
 850                cd subdir &&
 851                git rev-parse HEAD^{tree} >../actual
 852        ) &&
 853        test_cmp expected actual
 854'
 855
 856test_expect_success 'am newline in subject' '
 857        rm -fr .git/rebase-apply &&
 858        git reset --hard &&
 859        git checkout first &&
 860        test_tick &&
 861        sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
 862        git am <patchnl >output.out 2>&1 &&
 863        test_i18ngrep "^Applying: second \\\n foo$" output.out
 864'
 865
 866test_expect_success 'am -q is quiet' '
 867        rm -fr .git/rebase-apply &&
 868        git reset --hard &&
 869        git checkout first &&
 870        test_tick &&
 871        git am -q <patch1 >output.out 2>&1 &&
 872        ! test -s output.out
 873'
 874
 875test_expect_success 'am empty-file does not infloop' '
 876        rm -fr .git/rebase-apply &&
 877        git reset --hard &&
 878        touch empty-file &&
 879        test_tick &&
 880        test_must_fail git am empty-file 2>actual &&
 881        echo Patch format detection failed. >expected &&
 882        test_i18ncmp expected actual
 883'
 884
 885test_expect_success 'am --message-id really adds the message id' '
 886        rm -fr .git/rebase-apply &&
 887        git reset --hard &&
 888        git checkout HEAD^ &&
 889        git am --message-id patch1.eml &&
 890        test_path_is_missing .git/rebase-apply &&
 891        git cat-file commit HEAD | tail -n1 >actual &&
 892        grep Message-Id patch1.eml >expected &&
 893        test_cmp expected actual
 894'
 895
 896test_expect_success 'am.messageid really adds the message id' '
 897        rm -fr .git/rebase-apply &&
 898        git reset --hard &&
 899        git checkout HEAD^ &&
 900        test_config am.messageid true &&
 901        git am patch1.eml &&
 902        test_path_is_missing .git/rebase-apply &&
 903        git cat-file commit HEAD | tail -n1 >actual &&
 904        grep Message-Id patch1.eml >expected &&
 905        test_cmp expected actual
 906'
 907
 908test_expect_success 'am --message-id -s signs off after the message id' '
 909        rm -fr .git/rebase-apply &&
 910        git reset --hard &&
 911        git checkout HEAD^ &&
 912        git am -s --message-id patch1.eml &&
 913        test_path_is_missing .git/rebase-apply &&
 914        git cat-file commit HEAD | tail -n2 | head -n1 >actual &&
 915        grep Message-Id patch1.eml >expected &&
 916        test_cmp expected actual
 917'
 918
 919test_expect_success 'am -3 works with rerere' '
 920        rm -fr .git/rebase-apply &&
 921        git reset --hard &&
 922
 923        # make patches one->two and two->three...
 924        test_commit one file &&
 925        test_commit two file &&
 926        test_commit three file &&
 927        git format-patch -2 --stdout >seq.patch &&
 928
 929        # and create a situation that conflicts...
 930        git reset --hard one &&
 931        test_commit other file &&
 932
 933        # enable rerere...
 934        test_config rerere.enabled true &&
 935        test_when_finished "rm -rf .git/rr-cache" &&
 936
 937        # ...and apply. Our resolution is to skip the first
 938        # patch, and the rerere the second one.
 939        test_must_fail git am -3 seq.patch &&
 940        test_must_fail git am --skip &&
 941        echo resolved >file &&
 942        git add file &&
 943        git am --resolved &&
 944
 945        # now apply again, and confirm that rerere engaged (we still
 946        # expect failure from am because rerere does not auto-commit
 947        # for us).
 948        git reset --hard other &&
 949        test_must_fail git am -3 seq.patch &&
 950        test_must_fail git am --skip &&
 951        echo resolved >expect &&
 952        test_cmp expect file
 953'
 954
 955test_expect_success 'am -s unexpected trailer block' '
 956        rm -fr .git/rebase-apply &&
 957        git reset --hard &&
 958        echo signed >file &&
 959        git add file &&
 960        cat >msg <<-EOF &&
 961        subject here
 962
 963        Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
 964        [jc: tweaked log message]
 965        Signed-off-by: J C H <j@c.h>
 966        EOF
 967        git commit -F msg &&
 968        git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
 969        git format-patch --stdout -1 >patch &&
 970
 971        git reset --hard HEAD^ &&
 972        git am -s patch &&
 973        (
 974                cat original &&
 975                echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
 976        ) >expect &&
 977        git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
 978        test_cmp expect actual &&
 979
 980        cat >msg <<-\EOF &&
 981        subject here
 982
 983        We make sure that there is a blank line between the log
 984        message proper and Signed-off-by: line added.
 985        EOF
 986        git reset HEAD^ &&
 987        git commit -F msg file &&
 988        git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
 989        git format-patch --stdout -1 >patch &&
 990
 991        git reset --hard HEAD^ &&
 992        git am -s patch &&
 993
 994        (
 995                cat original &&
 996                echo &&
 997                echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
 998        ) >expect &&
 999        git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
1000        test_cmp expect actual
1001'
1002
1003test_expect_success 'am --patch-format=mboxrd handles mboxrd' '
1004        rm -fr .git/rebase-apply &&
1005        git checkout -f first &&
1006        echo mboxrd >>file &&
1007        git add file &&
1008        cat >msg <<-\INPUT_END &&
1009        mboxrd should escape the body
1010
1011        From could trip up a loose mbox parser
1012        >From extra escape for reversibility
1013        INPUT_END
1014        git commit -F msg &&
1015        git format-patch --pretty=mboxrd --stdout -1 >mboxrd1 &&
1016        grep "^>From could trip up a loose mbox parser" mboxrd1 &&
1017        git checkout -f first &&
1018        git am --patch-format=mboxrd mboxrd1 &&
1019        git cat-file commit HEAD | tail -n4 >out &&
1020        test_cmp msg out
1021'
1022
1023test_expect_success 'am works with multi-line in-body headers' '
1024        FORTY="String that has a length of more than forty characters" &&
1025        LONG="$FORTY $FORTY" &&
1026        rm -fr .git/rebase-apply &&
1027        git checkout -f first &&
1028        echo one >> file &&
1029        git commit -am "$LONG
1030
1031    Body test" --author="$LONG <long@example.com>" &&
1032        git format-patch --stdout -1 >patch &&
1033        # bump from, date, and subject down to in-body header
1034        perl -lpe "
1035                if (/^From:/) {
1036                        print \"From: x <x\@example.com>\";
1037                        print \"Date: Sat, 1 Jan 2000 00:00:00 +0000\";
1038                        print \"Subject: x\n\";
1039                }
1040        " patch >msg &&
1041        git checkout HEAD^ &&
1042        git am msg &&
1043        # Ensure that the author and full message are present
1044        git cat-file commit HEAD | grep "^author.*long@example.com" &&
1045        git cat-file commit HEAD | grep "^$LONG$"
1046'
1047
1048test_done