t / t4150-am.shon commit apply: reject input that touches outside the working area (c536c07)
   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 "X-Fake-Field: Line One" &&
  89                echo "X-Fake-Field: Line Two" &&
  90                echo "X-Fake-Field: Line Three" &&
  91                git format-patch --stdout first | sed -e "1d"
  92        } > patch1.eml &&
  93        {
  94                echo "X-Fake-Field: Line One" &&
  95                echo "X-Fake-Field: Line Two" &&
  96                echo "X-Fake-Field: Line Three" &&
  97                git format-patch --stdout first | sed -e "1d"
  98        } | append_cr >patch1-crlf.eml &&
  99        {
 100                printf "%255s\\n" ""
 101                echo "X-Fake-Field: Line One" &&
 102                echo "X-Fake-Field: Line Two" &&
 103                echo "X-Fake-Field: Line Three" &&
 104                git format-patch --stdout first | sed -e "1d"
 105        } > patch1-ws.eml &&
 106
 107        sed -n -e "3,\$p" msg >file &&
 108        git add file &&
 109        test_tick &&
 110        git commit -m third &&
 111
 112        git format-patch --stdout first >patch2 &&
 113
 114        git checkout -b lorem &&
 115        sed -n -e "11,\$p" msg >file &&
 116        head -n 9 msg >>file &&
 117        test_tick &&
 118        git commit -a -m "moved stuff" &&
 119
 120        echo goodbye >another &&
 121        git add another &&
 122        test_tick &&
 123        git commit -m "added another file" &&
 124
 125        git format-patch --stdout master >lorem-move.patch &&
 126        git format-patch --no-prefix --stdout master >lorem-zero.patch &&
 127
 128        git checkout -b rename &&
 129        git mv file renamed &&
 130        git commit -m "renamed a file" &&
 131
 132        git format-patch -M --stdout lorem >rename.patch &&
 133
 134        git reset --soft lorem^ &&
 135        git commit -m "renamed a file and added another" &&
 136
 137        git format-patch -M --stdout lorem^ >rename-add.patch &&
 138
 139        # reset time
 140        sane_unset test_tick &&
 141        test_tick
 142'
 143
 144test_expect_success 'am applies patch correctly' '
 145        rm -fr .git/rebase-apply &&
 146        git reset --hard &&
 147        git checkout first &&
 148        test_tick &&
 149        git am <patch1 &&
 150        test_path_is_missing .git/rebase-apply &&
 151        git diff --exit-code second &&
 152        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 153        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 154'
 155
 156test_expect_success 'am applies patch e-mail not in a mbox' '
 157        rm -fr .git/rebase-apply &&
 158        git reset --hard &&
 159        git checkout first &&
 160        git am patch1.eml &&
 161        test_path_is_missing .git/rebase-apply &&
 162        git diff --exit-code second &&
 163        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 164        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 165'
 166
 167test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
 168        rm -fr .git/rebase-apply &&
 169        git reset --hard &&
 170        git checkout first &&
 171        git am patch1-crlf.eml &&
 172        test_path_is_missing .git/rebase-apply &&
 173        git diff --exit-code second &&
 174        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 175        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 176'
 177
 178test_expect_success 'am applies patch e-mail with preceding whitespace' '
 179        rm -fr .git/rebase-apply &&
 180        git reset --hard &&
 181        git checkout first &&
 182        git am patch1-ws.eml &&
 183        test_path_is_missing .git/rebase-apply &&
 184        git diff --exit-code second &&
 185        test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 186        test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
 187'
 188
 189test_expect_success 'setup: new author and committer' '
 190        GIT_AUTHOR_NAME="Another Thor" &&
 191        GIT_AUTHOR_EMAIL="a.thor@example.com" &&
 192        GIT_COMMITTER_NAME="Co M Miter" &&
 193        GIT_COMMITTER_EMAIL="c.miter@example.com" &&
 194        export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
 195'
 196
 197compare () {
 198        a=$(git cat-file commit "$2" | grep "^$1 ") &&
 199        b=$(git cat-file commit "$3" | grep "^$1 ") &&
 200        test "$a" = "$b"
 201}
 202
 203test_expect_success 'am changes committer and keeps author' '
 204        test_tick &&
 205        rm -fr .git/rebase-apply &&
 206        git reset --hard &&
 207        git checkout first &&
 208        git am patch2 &&
 209        test_path_is_missing .git/rebase-apply &&
 210        test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
 211        git diff --exit-code master..HEAD &&
 212        git diff --exit-code master^..HEAD^ &&
 213        compare author master HEAD &&
 214        compare author master^ HEAD^ &&
 215        test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
 216             "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
 217'
 218
 219test_expect_success 'am --signoff adds Signed-off-by: line' '
 220        rm -fr .git/rebase-apply &&
 221        git reset --hard &&
 222        git checkout -b master2 first &&
 223        git am --signoff <patch2 &&
 224        printf "%s\n" "$signoff" >expected &&
 225        echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected &&
 226        git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
 227        test_cmp expected actual &&
 228        echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
 229        git cat-file commit HEAD | grep "Signed-off-by:" >actual &&
 230        test_cmp expected actual
 231'
 232
 233test_expect_success 'am stays in branch' '
 234        echo refs/heads/master2 >expected &&
 235        git symbolic-ref HEAD >actual &&
 236        test_cmp expected actual
 237'
 238
 239test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
 240        git format-patch --stdout HEAD^ >patch3 &&
 241        sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," patch3 >patch4 &&
 242        rm -fr .git/rebase-apply &&
 243        git reset --hard &&
 244        git checkout HEAD^ &&
 245        git am --signoff patch4 &&
 246        git cat-file commit HEAD >actual &&
 247        test $(grep -c "^Signed-off-by:" actual) -eq 1
 248'
 249
 250test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
 251        git rev-parse HEAD >expected &&
 252        git rev-parse master2 >actual &&
 253        test_cmp expected actual
 254'
 255
 256test_expect_success 'am --keep really keeps the subject' '
 257        rm -fr .git/rebase-apply &&
 258        git reset --hard &&
 259        git checkout HEAD^ &&
 260        git am --keep patch4 &&
 261        test_path_is_missing .git/rebase-apply &&
 262        git cat-file commit HEAD >actual &&
 263        grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual
 264'
 265
 266test_expect_success 'am --keep-non-patch really keeps the non-patch part' '
 267        rm -fr .git/rebase-apply &&
 268        git reset --hard &&
 269        git checkout HEAD^ &&
 270        git am --keep-non-patch patch4 &&
 271        test_path_is_missing .git/rebase-apply &&
 272        git cat-file commit HEAD >actual &&
 273        grep "^\[foo\] third" actual
 274'
 275
 276test_expect_success 'am -3 falls back to 3-way merge' '
 277        rm -fr .git/rebase-apply &&
 278        git reset --hard &&
 279        git checkout -b lorem2 master2 &&
 280        sed -n -e "3,\$p" msg >file &&
 281        head -n 9 msg >>file &&
 282        git add file &&
 283        test_tick &&
 284        git commit -m "copied stuff" &&
 285        git am -3 lorem-move.patch &&
 286        test_path_is_missing .git/rebase-apply &&
 287        git diff --exit-code lorem
 288'
 289
 290test_expect_success 'am -3 -p0 can read --no-prefix patch' '
 291        rm -fr .git/rebase-apply &&
 292        git reset --hard &&
 293        git checkout -b lorem3 master2 &&
 294        sed -n -e "3,\$p" msg >file &&
 295        head -n 9 msg >>file &&
 296        git add file &&
 297        test_tick &&
 298        git commit -m "copied stuff" &&
 299        git am -3 -p0 lorem-zero.patch &&
 300        test_path_is_missing .git/rebase-apply &&
 301        git diff --exit-code lorem
 302'
 303
 304test_expect_success 'am can rename a file' '
 305        grep "^rename from" rename.patch &&
 306        rm -fr .git/rebase-apply &&
 307        git reset --hard &&
 308        git checkout lorem^0 &&
 309        git am rename.patch &&
 310        test_path_is_missing .git/rebase-apply &&
 311        git update-index --refresh &&
 312        git diff --exit-code rename
 313'
 314
 315test_expect_success 'am -3 can rename a file' '
 316        grep "^rename from" rename.patch &&
 317        rm -fr .git/rebase-apply &&
 318        git reset --hard &&
 319        git checkout lorem^0 &&
 320        git am -3 rename.patch &&
 321        test_path_is_missing .git/rebase-apply &&
 322        git update-index --refresh &&
 323        git diff --exit-code rename
 324'
 325
 326test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
 327        grep "^rename from" rename-add.patch &&
 328        rm -fr .git/rebase-apply &&
 329        git reset --hard &&
 330        git checkout lorem^0 &&
 331        git am -3 rename-add.patch &&
 332        test_path_is_missing .git/rebase-apply &&
 333        git update-index --refresh &&
 334        git diff --exit-code rename
 335'
 336
 337test_expect_success 'am -3 -q is quiet' '
 338        rm -fr .git/rebase-apply &&
 339        git checkout -f lorem2 &&
 340        git reset master2 --hard &&
 341        sed -n -e "3,\$p" msg >file &&
 342        head -n 9 msg >>file &&
 343        git add file &&
 344        test_tick &&
 345        git commit -m "copied stuff" &&
 346        git am -3 -q lorem-move.patch >output.out 2>&1 &&
 347        ! test -s output.out
 348'
 349
 350test_expect_success 'am pauses on conflict' '
 351        rm -fr .git/rebase-apply &&
 352        git reset --hard &&
 353        git checkout lorem2^^ &&
 354        test_must_fail git am lorem-move.patch &&
 355        test -d .git/rebase-apply
 356'
 357
 358test_expect_success 'am --skip works' '
 359        echo goodbye >expected &&
 360        git am --skip &&
 361        test_path_is_missing .git/rebase-apply &&
 362        git diff --exit-code lorem2^^ -- file &&
 363        test_cmp expected another
 364'
 365
 366test_expect_success 'am --abort removes a stray directory' '
 367        mkdir .git/rebase-apply &&
 368        git am --abort &&
 369        test_path_is_missing .git/rebase-apply
 370'
 371
 372test_expect_success 'am --resolved works' '
 373        echo goodbye >expected &&
 374        rm -fr .git/rebase-apply &&
 375        git reset --hard &&
 376        git checkout lorem2^^ &&
 377        test_must_fail git am lorem-move.patch &&
 378        test -d .git/rebase-apply &&
 379        echo resolved >>file &&
 380        git add file &&
 381        git am --resolved &&
 382        test_path_is_missing .git/rebase-apply &&
 383        test_cmp expected another
 384'
 385
 386test_expect_success 'am takes patches from a Pine mailbox' '
 387        rm -fr .git/rebase-apply &&
 388        git reset --hard &&
 389        git checkout first &&
 390        cat pine patch1 | git am &&
 391        test_path_is_missing .git/rebase-apply &&
 392        git diff --exit-code master^..HEAD
 393'
 394
 395test_expect_success 'am fails on mail without patch' '
 396        rm -fr .git/rebase-apply &&
 397        git reset --hard &&
 398        test_must_fail git am <failmail &&
 399        git am --abort &&
 400        test_path_is_missing .git/rebase-apply
 401'
 402
 403test_expect_success 'am fails on empty patch' '
 404        rm -fr .git/rebase-apply &&
 405        git reset --hard &&
 406        echo "---" >>failmail &&
 407        test_must_fail git am <failmail &&
 408        git am --skip &&
 409        test_path_is_missing .git/rebase-apply
 410'
 411
 412test_expect_success 'am works from stdin in subdirectory' '
 413        rm -fr subdir &&
 414        rm -fr .git/rebase-apply &&
 415        git reset --hard &&
 416        git checkout first &&
 417        (
 418                mkdir -p subdir &&
 419                cd subdir &&
 420                git am <../patch1
 421        ) &&
 422        git diff --exit-code second
 423'
 424
 425test_expect_success 'am works from file (relative path given) in subdirectory' '
 426        rm -fr subdir &&
 427        rm -fr .git/rebase-apply &&
 428        git reset --hard &&
 429        git checkout first &&
 430        (
 431                mkdir -p subdir &&
 432                cd subdir &&
 433                git am ../patch1
 434        ) &&
 435        git diff --exit-code second
 436'
 437
 438test_expect_success 'am works from file (absolute path given) in subdirectory' '
 439        rm -fr subdir &&
 440        rm -fr .git/rebase-apply &&
 441        git reset --hard &&
 442        git checkout first &&
 443        P=$(pwd) &&
 444        (
 445                mkdir -p subdir &&
 446                cd subdir &&
 447                git am "$P/patch1"
 448        ) &&
 449        git diff --exit-code second
 450'
 451
 452test_expect_success 'am --committer-date-is-author-date' '
 453        rm -fr .git/rebase-apply &&
 454        git reset --hard &&
 455        git checkout first &&
 456        test_tick &&
 457        git am --committer-date-is-author-date patch1 &&
 458        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 459        sed -ne "/^author /s/.*> //p" head1 >at &&
 460        sed -ne "/^committer /s/.*> //p" head1 >ct &&
 461        test_cmp at ct
 462'
 463
 464test_expect_success 'am without --committer-date-is-author-date' '
 465        rm -fr .git/rebase-apply &&
 466        git reset --hard &&
 467        git checkout first &&
 468        test_tick &&
 469        git am patch1 &&
 470        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 471        sed -ne "/^author /s/.*> //p" head1 >at &&
 472        sed -ne "/^committer /s/.*> //p" head1 >ct &&
 473        ! test_cmp at ct
 474'
 475
 476# This checks for +0000 because TZ is set to UTC and that should
 477# show up when the current time is used. The date in message is set
 478# by test_tick that uses -0700 timezone; if this feature does not
 479# work, we will see that instead of +0000.
 480test_expect_success 'am --ignore-date' '
 481        rm -fr .git/rebase-apply &&
 482        git reset --hard &&
 483        git checkout first &&
 484        test_tick &&
 485        git am --ignore-date patch1 &&
 486        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 487        sed -ne "/^author /s/.*> //p" head1 >at &&
 488        grep "+0000" at
 489'
 490
 491test_expect_success 'am into an unborn branch' '
 492        git rev-parse first^{tree} >expected &&
 493        rm -fr .git/rebase-apply &&
 494        git reset --hard &&
 495        rm -fr subdir &&
 496        mkdir subdir &&
 497        git format-patch --numbered-files -o subdir -1 first &&
 498        (
 499                cd subdir &&
 500                git init &&
 501                git am 1
 502        ) &&
 503        (
 504                cd subdir &&
 505                git rev-parse HEAD^{tree} >../actual
 506        ) &&
 507        test_cmp expected actual
 508'
 509
 510test_expect_success 'am newline in subject' '
 511        rm -fr .git/rebase-apply &&
 512        git reset --hard &&
 513        git checkout first &&
 514        test_tick &&
 515        sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
 516        git am <patchnl >output.out 2>&1 &&
 517        test_i18ngrep "^Applying: second \\\n foo$" output.out
 518'
 519
 520test_expect_success 'am -q is quiet' '
 521        rm -fr .git/rebase-apply &&
 522        git reset --hard &&
 523        git checkout first &&
 524        test_tick &&
 525        git am -q <patch1 >output.out 2>&1 &&
 526        ! test -s output.out
 527'
 528
 529test_expect_success 'am empty-file does not infloop' '
 530        rm -fr .git/rebase-apply &&
 531        git reset --hard &&
 532        touch empty-file &&
 533        test_tick &&
 534        test_must_fail git am empty-file 2>actual &&
 535        echo Patch format detection failed. >expected &&
 536        test_i18ncmp expected actual
 537'
 538
 539test_done