a85e06aa033d11fce4b561df559925febce7914f
   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        EOF
  44
  45        cat >failmail <<-\EOF &&
  46        From foo@example.com Fri May 23 10:43:49 2008
  47        From:   foo@example.com
  48        To:     bar@example.com
  49        Subject: Re: [RFC/PATCH] git-foo.sh
  50        Date:   Fri, 23 May 2008 05:23:42 +0200
  51
  52        Sometimes we have to find out that there'\''s nothing left.
  53
  54        EOF
  55
  56        cat >pine <<-\EOF &&
  57        From MAILER-DAEMON Fri May 23 10:43:49 2008
  58        Date: 23 May 2008 05:23:42 +0200
  59        From: Mail System Internal Data <MAILER-DAEMON@example.com>
  60        Subject: DON'\''T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA
  61        Message-ID: <foo-0001@example.com>
  62
  63        This text is part of the internal format of your mail folder, and is not
  64        a real message.  It is created automatically by the mail system software.
  65        If deleted, important folder data will be lost, and it will be re-created
  66        with the data reset to initial values.
  67
  68        EOF
  69
  70        signoff="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
  71'
  72
  73test_expect_success setup '
  74        echo hello >file &&
  75        git add file &&
  76        test_tick &&
  77        git commit -m first &&
  78        git tag first &&
  79
  80        echo world >>file &&
  81        git add file &&
  82        test_tick &&
  83        git commit -s -F msg &&
  84        git tag second &&
  85
  86        git format-patch --stdout first >patch1 &&
  87        {
  88                echo "Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>" &&
  89                echo "X-Fake-Field: Line One" &&
  90                echo "X-Fake-Field: Line Two" &&
  91                echo "X-Fake-Field: Line Three" &&
  92                git format-patch --stdout first | sed -e "1d"
  93        } > patch1.eml &&
  94        {
  95                echo "X-Fake-Field: Line One" &&
  96                echo "X-Fake-Field: Line Two" &&
  97                echo "X-Fake-Field: Line Three" &&
  98                git format-patch --stdout first | sed -e "1d"
  99        } | append_cr >patch1-crlf.eml &&
 100        {
 101                printf "%255s\\n" ""
 102                echo "X-Fake-Field: Line One" &&
 103                echo "X-Fake-Field: Line Two" &&
 104                echo "X-Fake-Field: Line Three" &&
 105                git format-patch --stdout first | sed -e "1d"
 106        } > patch1-ws.eml &&
 107
 108        sed -n -e "3,\$p" msg >file &&
 109        git add file &&
 110        test_tick &&
 111        git commit -m third &&
 112
 113        git format-patch --stdout first >patch2 &&
 114
 115        git checkout -b lorem &&
 116        sed -n -e "11,\$p" msg >file &&
 117        head -n 9 msg >>file &&
 118        test_tick &&
 119        git commit -a -m "moved stuff" &&
 120
 121        echo goodbye >another &&
 122        git add another &&
 123        test_tick &&
 124        git commit -m "added another file" &&
 125
 126        git format-patch --stdout master >lorem-move.patch &&
 127        git format-patch --no-prefix --stdout master >lorem-zero.patch &&
 128
 129        git checkout -b rename &&
 130        git mv file renamed &&
 131        git commit -m "renamed a file" &&
 132
 133        git format-patch -M --stdout lorem >rename.patch &&
 134
 135        git reset --soft lorem^ &&
 136        git commit -m "renamed a file and added another" &&
 137
 138        git format-patch -M --stdout lorem^ >rename-add.patch &&
 139
 140        # reset time
 141        sane_unset test_tick &&
 142        test_tick
 143'
 144
 145test_expect_success 'am applies patch correctly' '
 146        rm -fr .git/rebase-apply &&
 147        git reset --hard &&
 148        git checkout first &&
 149        test_tick &&
 150        git am <patch1 &&
 151        test_path_is_missing .git/rebase-apply &&
 152        git diff --exit-code second &&
 153        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 154        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 155'
 156
 157test_expect_success 'am fails if index is dirty' '
 158        test_when_finished "rm -f dirtyfile" &&
 159        rm -fr .git/rebase-apply &&
 160        git reset --hard &&
 161        git checkout first &&
 162        echo dirtyfile >dirtyfile &&
 163        git add dirtyfile &&
 164        test_must_fail git am patch1 &&
 165        test_path_is_dir .git/rebase-apply &&
 166        test_cmp_rev first HEAD
 167'
 168
 169test_expect_success 'am applies patch e-mail not in a mbox' '
 170        rm -fr .git/rebase-apply &&
 171        git reset --hard &&
 172        git checkout first &&
 173        git am patch1.eml &&
 174        test_path_is_missing .git/rebase-apply &&
 175        git diff --exit-code second &&
 176        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 177        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 178'
 179
 180test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
 181        rm -fr .git/rebase-apply &&
 182        git reset --hard &&
 183        git checkout first &&
 184        git am patch1-crlf.eml &&
 185        test_path_is_missing .git/rebase-apply &&
 186        git diff --exit-code second &&
 187        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 188        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 189'
 190
 191test_expect_success 'am applies patch e-mail with preceding whitespace' '
 192        rm -fr .git/rebase-apply &&
 193        git reset --hard &&
 194        git checkout first &&
 195        git am patch1-ws.eml &&
 196        test_path_is_missing .git/rebase-apply &&
 197        git diff --exit-code second &&
 198        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 199        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 200'
 201
 202test_expect_success 'setup: new author and committer' '
 203        GIT_AUTHOR_NAME="Another Thor" &&
 204        GIT_AUTHOR_EMAIL="a.thor@example.com" &&
 205        GIT_COMMITTER_NAME="Co M Miter" &&
 206        GIT_COMMITTER_EMAIL="c.miter@example.com" &&
 207        export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
 208'
 209
 210compare () {
 211        a=$(git cat-file commit "$2" | grep "^$1 ") &&
 212        b=$(git cat-file commit "$3" | grep "^$1 ") &&
 213        test "$a" = "$b"
 214}
 215
 216test_expect_success 'am changes committer and keeps author' '
 217        test_tick &&
 218        rm -fr .git/rebase-apply &&
 219        git reset --hard &&
 220        git checkout first &&
 221        git am patch2 &&
 222        test_path_is_missing .git/rebase-apply &&
 223        test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
 224        git diff --exit-code master..HEAD &&
 225        git diff --exit-code master^..HEAD^ &&
 226        compare author master HEAD &&
 227        compare author master^ HEAD^ &&
 228        test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
 229             "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
 230'
 231
 232test_expect_success 'am --signoff adds Signed-off-by: line' '
 233        rm -fr .git/rebase-apply &&
 234        git reset --hard &&
 235        git checkout -b master2 first &&
 236        git am --signoff <patch2 &&
 237        printf "%s\n" "$signoff" >expected &&
 238        echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected &&
 239        git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
 240        test_cmp expected actual &&
 241        echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
 242        git cat-file commit HEAD | grep "Signed-off-by:" >actual &&
 243        test_cmp expected actual
 244'
 245
 246test_expect_success 'am stays in branch' '
 247        echo refs/heads/master2 >expected &&
 248        git symbolic-ref HEAD >actual &&
 249        test_cmp expected actual
 250'
 251
 252test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
 253        git format-patch --stdout HEAD^ >patch3 &&
 254        sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," patch3 >patch4 &&
 255        rm -fr .git/rebase-apply &&
 256        git reset --hard &&
 257        git checkout HEAD^ &&
 258        git am --signoff patch4 &&
 259        git cat-file commit HEAD >actual &&
 260        test $(grep -c "^Signed-off-by:" actual) -eq 1
 261'
 262
 263test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
 264        git rev-parse HEAD >expected &&
 265        git rev-parse master2 >actual &&
 266        test_cmp expected actual
 267'
 268
 269test_expect_success 'am --keep really keeps the subject' '
 270        rm -fr .git/rebase-apply &&
 271        git reset --hard &&
 272        git checkout HEAD^ &&
 273        git am --keep patch4 &&
 274        test_path_is_missing .git/rebase-apply &&
 275        git cat-file commit HEAD >actual &&
 276        grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual
 277'
 278
 279test_expect_success 'am --keep-non-patch really keeps the non-patch part' '
 280        rm -fr .git/rebase-apply &&
 281        git reset --hard &&
 282        git checkout HEAD^ &&
 283        git am --keep-non-patch patch4 &&
 284        test_path_is_missing .git/rebase-apply &&
 285        git cat-file commit HEAD >actual &&
 286        grep "^\[foo\] third" actual
 287'
 288
 289test_expect_success 'setup am -3' '
 290        rm -fr .git/rebase-apply &&
 291        git reset --hard &&
 292        git checkout -b base3way master2 &&
 293        sed -n -e "3,\$p" msg >file &&
 294        head -n 9 msg >>file &&
 295        git add file &&
 296        test_tick &&
 297        git commit -m "copied stuff"
 298'
 299
 300test_expect_success 'am -3 falls back to 3-way merge' '
 301        rm -fr .git/rebase-apply &&
 302        git reset --hard &&
 303        git checkout -b lorem2 base3way &&
 304        git am -3 lorem-move.patch &&
 305        test_path_is_missing .git/rebase-apply &&
 306        git diff --exit-code lorem
 307'
 308
 309test_expect_success 'am -3 -p0 can read --no-prefix patch' '
 310        rm -fr .git/rebase-apply &&
 311        git reset --hard &&
 312        git checkout -b lorem3 base3way &&
 313        git am -3 -p0 lorem-zero.patch &&
 314        test_path_is_missing .git/rebase-apply &&
 315        git diff --exit-code lorem
 316'
 317
 318test_expect_success 'am with config am.threeWay falls back to 3-way merge' '
 319        rm -fr .git/rebase-apply &&
 320        git reset --hard &&
 321        git checkout -b lorem4 base3way &&
 322        test_config am.threeWay 1 &&
 323        git am lorem-move.patch &&
 324        test_path_is_missing .git/rebase-apply &&
 325        git diff --exit-code lorem
 326'
 327
 328test_expect_success 'am with config am.threeWay overridden by --no-3way' '
 329        rm -fr .git/rebase-apply &&
 330        git reset --hard &&
 331        git checkout -b lorem5 base3way &&
 332        test_config am.threeWay 1 &&
 333        test_must_fail git am --no-3way lorem-move.patch &&
 334        test_path_is_dir .git/rebase-apply
 335'
 336
 337test_expect_success 'am can rename a file' '
 338        grep "^rename from" rename.patch &&
 339        rm -fr .git/rebase-apply &&
 340        git reset --hard &&
 341        git checkout lorem^0 &&
 342        git am rename.patch &&
 343        test_path_is_missing .git/rebase-apply &&
 344        git update-index --refresh &&
 345        git diff --exit-code rename
 346'
 347
 348test_expect_success 'am -3 can rename a file' '
 349        grep "^rename from" rename.patch &&
 350        rm -fr .git/rebase-apply &&
 351        git reset --hard &&
 352        git checkout lorem^0 &&
 353        git am -3 rename.patch &&
 354        test_path_is_missing .git/rebase-apply &&
 355        git update-index --refresh &&
 356        git diff --exit-code rename
 357'
 358
 359test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
 360        grep "^rename from" rename-add.patch &&
 361        rm -fr .git/rebase-apply &&
 362        git reset --hard &&
 363        git checkout lorem^0 &&
 364        git am -3 rename-add.patch &&
 365        test_path_is_missing .git/rebase-apply &&
 366        git update-index --refresh &&
 367        git diff --exit-code rename
 368'
 369
 370test_expect_success 'am -3 -q is quiet' '
 371        rm -fr .git/rebase-apply &&
 372        git checkout -f lorem2 &&
 373        git reset base3way --hard &&
 374        git am -3 -q lorem-move.patch >output.out 2>&1 &&
 375        ! test -s output.out
 376'
 377
 378test_expect_success 'am pauses on conflict' '
 379        rm -fr .git/rebase-apply &&
 380        git reset --hard &&
 381        git checkout lorem2^^ &&
 382        test_must_fail git am lorem-move.patch &&
 383        test -d .git/rebase-apply
 384'
 385
 386test_expect_success 'am --skip works' '
 387        echo goodbye >expected &&
 388        git am --skip &&
 389        test_path_is_missing .git/rebase-apply &&
 390        git diff --exit-code lorem2^^ -- file &&
 391        test_cmp expected another
 392'
 393
 394test_expect_success 'am --abort removes a stray directory' '
 395        mkdir .git/rebase-apply &&
 396        git am --abort &&
 397        test_path_is_missing .git/rebase-apply
 398'
 399
 400test_expect_success 'am --resolved works' '
 401        echo goodbye >expected &&
 402        rm -fr .git/rebase-apply &&
 403        git reset --hard &&
 404        git checkout lorem2^^ &&
 405        test_must_fail git am lorem-move.patch &&
 406        test -d .git/rebase-apply &&
 407        echo resolved >>file &&
 408        git add file &&
 409        git am --resolved &&
 410        test_path_is_missing .git/rebase-apply &&
 411        test_cmp expected another
 412'
 413
 414test_expect_success 'am takes patches from a Pine mailbox' '
 415        rm -fr .git/rebase-apply &&
 416        git reset --hard &&
 417        git checkout first &&
 418        cat pine patch1 | git am &&
 419        test_path_is_missing .git/rebase-apply &&
 420        git diff --exit-code master^..HEAD
 421'
 422
 423test_expect_success 'am fails on mail without patch' '
 424        rm -fr .git/rebase-apply &&
 425        git reset --hard &&
 426        test_must_fail git am <failmail &&
 427        git am --abort &&
 428        test_path_is_missing .git/rebase-apply
 429'
 430
 431test_expect_success 'am fails on empty patch' '
 432        rm -fr .git/rebase-apply &&
 433        git reset --hard &&
 434        echo "---" >>failmail &&
 435        test_must_fail git am <failmail &&
 436        git am --skip &&
 437        test_path_is_missing .git/rebase-apply
 438'
 439
 440test_expect_success 'am works from stdin in subdirectory' '
 441        rm -fr subdir &&
 442        rm -fr .git/rebase-apply &&
 443        git reset --hard &&
 444        git checkout first &&
 445        (
 446                mkdir -p subdir &&
 447                cd subdir &&
 448                git am <../patch1
 449        ) &&
 450        git diff --exit-code second
 451'
 452
 453test_expect_success 'am works from file (relative path given) in subdirectory' '
 454        rm -fr subdir &&
 455        rm -fr .git/rebase-apply &&
 456        git reset --hard &&
 457        git checkout first &&
 458        (
 459                mkdir -p subdir &&
 460                cd subdir &&
 461                git am ../patch1
 462        ) &&
 463        git diff --exit-code second
 464'
 465
 466test_expect_success 'am works from file (absolute path given) in subdirectory' '
 467        rm -fr subdir &&
 468        rm -fr .git/rebase-apply &&
 469        git reset --hard &&
 470        git checkout first &&
 471        P=$(pwd) &&
 472        (
 473                mkdir -p subdir &&
 474                cd subdir &&
 475                git am "$P/patch1"
 476        ) &&
 477        git diff --exit-code second
 478'
 479
 480test_expect_success 'am --committer-date-is-author-date' '
 481        rm -fr .git/rebase-apply &&
 482        git reset --hard &&
 483        git checkout first &&
 484        test_tick &&
 485        git am --committer-date-is-author-date patch1 &&
 486        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 487        sed -ne "/^author /s/.*> //p" head1 >at &&
 488        sed -ne "/^committer /s/.*> //p" head1 >ct &&
 489        test_cmp at ct
 490'
 491
 492test_expect_success 'am without --committer-date-is-author-date' '
 493        rm -fr .git/rebase-apply &&
 494        git reset --hard &&
 495        git checkout first &&
 496        test_tick &&
 497        git am patch1 &&
 498        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 499        sed -ne "/^author /s/.*> //p" head1 >at &&
 500        sed -ne "/^committer /s/.*> //p" head1 >ct &&
 501        ! test_cmp at ct
 502'
 503
 504# This checks for +0000 because TZ is set to UTC and that should
 505# show up when the current time is used. The date in message is set
 506# by test_tick that uses -0700 timezone; if this feature does not
 507# work, we will see that instead of +0000.
 508test_expect_success 'am --ignore-date' '
 509        rm -fr .git/rebase-apply &&
 510        git reset --hard &&
 511        git checkout first &&
 512        test_tick &&
 513        git am --ignore-date patch1 &&
 514        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 515        sed -ne "/^author /s/.*> //p" head1 >at &&
 516        grep "+0000" at
 517'
 518
 519test_expect_success 'am into an unborn branch' '
 520        git rev-parse first^{tree} >expected &&
 521        rm -fr .git/rebase-apply &&
 522        git reset --hard &&
 523        rm -fr subdir &&
 524        mkdir subdir &&
 525        git format-patch --numbered-files -o subdir -1 first &&
 526        (
 527                cd subdir &&
 528                git init &&
 529                git am 1
 530        ) &&
 531        (
 532                cd subdir &&
 533                git rev-parse HEAD^{tree} >../actual
 534        ) &&
 535        test_cmp expected actual
 536'
 537
 538test_expect_success 'am newline in subject' '
 539        rm -fr .git/rebase-apply &&
 540        git reset --hard &&
 541        git checkout first &&
 542        test_tick &&
 543        sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
 544        git am <patchnl >output.out 2>&1 &&
 545        test_i18ngrep "^Applying: second \\\n foo$" output.out
 546'
 547
 548test_expect_success 'am -q is quiet' '
 549        rm -fr .git/rebase-apply &&
 550        git reset --hard &&
 551        git checkout first &&
 552        test_tick &&
 553        git am -q <patch1 >output.out 2>&1 &&
 554        ! test -s output.out
 555'
 556
 557test_expect_success 'am empty-file does not infloop' '
 558        rm -fr .git/rebase-apply &&
 559        git reset --hard &&
 560        touch empty-file &&
 561        test_tick &&
 562        test_must_fail git am empty-file 2>actual &&
 563        echo Patch format detection failed. >expected &&
 564        test_i18ncmp expected actual
 565'
 566
 567test_expect_success 'am --message-id really adds the message id' '
 568        rm -fr .git/rebase-apply &&
 569        git reset --hard &&
 570        git checkout HEAD^ &&
 571        git am --message-id patch1.eml &&
 572        test_path_is_missing .git/rebase-apply &&
 573        git cat-file commit HEAD | tail -n1 >actual &&
 574        grep Message-Id patch1.eml >expected &&
 575        test_cmp expected actual
 576'
 577
 578test_expect_success 'am.messageid really adds the message id' '
 579        rm -fr .git/rebase-apply &&
 580        git reset --hard &&
 581        git checkout HEAD^ &&
 582        test_config am.messageid true &&
 583        git am patch1.eml &&
 584        test_path_is_missing .git/rebase-apply &&
 585        git cat-file commit HEAD | tail -n1 >actual &&
 586        grep Message-Id patch1.eml >expected &&
 587        test_cmp expected actual
 588'
 589
 590test_expect_success 'am --message-id -s signs off after the message id' '
 591        rm -fr .git/rebase-apply &&
 592        git reset --hard &&
 593        git checkout HEAD^ &&
 594        git am -s --message-id patch1.eml &&
 595        test_path_is_missing .git/rebase-apply &&
 596        git cat-file commit HEAD | tail -n2 | head -n1 >actual &&
 597        grep Message-Id patch1.eml >expected &&
 598        test_cmp expected actual
 599'
 600
 601test_done