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