t / t4150-am.shon commit avoid segfault when reading header of malformed commits (a9c7a8a)
   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        q_to_tab <<-\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 -d .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 -d .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 -d .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 -d .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 -d .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," 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 -d .git/rebase-apply &&
 262        git cat-file commit HEAD >actual &&
 263        grep "Re: Re: Re: \[PATCH 1/5 v2\] third" actual
 264'
 265
 266test_expect_success 'am -3 falls back to 3-way merge' '
 267        rm -fr .git/rebase-apply &&
 268        git reset --hard &&
 269        git checkout -b lorem2 master2 &&
 270        sed -n -e "3,\$p" msg >file &&
 271        head -n 9 msg >>file &&
 272        git add file &&
 273        test_tick &&
 274        git commit -m "copied stuff" &&
 275        git am -3 lorem-move.patch &&
 276        ! test -d .git/rebase-apply &&
 277        git diff --exit-code lorem
 278'
 279
 280test_expect_success 'am -3 -p0 can read --no-prefix patch' '
 281        rm -fr .git/rebase-apply &&
 282        git reset --hard &&
 283        git checkout -b lorem3 master2 &&
 284        sed -n -e "3,\$p" msg >file &&
 285        head -n 9 msg >>file &&
 286        git add file &&
 287        test_tick &&
 288        git commit -m "copied stuff" &&
 289        git am -3 -p0 lorem-zero.patch &&
 290        ! test -d .git/rebase-apply &&
 291        git diff --exit-code lorem
 292'
 293
 294test_expect_success 'am can rename a file' '
 295        grep "^rename from" rename.patch &&
 296        rm -fr .git/rebase-apply &&
 297        git reset --hard &&
 298        git checkout lorem^0 &&
 299        git am rename.patch &&
 300        ! test -d .git/rebase-apply &&
 301        git update-index --refresh &&
 302        git diff --exit-code rename
 303'
 304
 305test_expect_success 'am -3 can rename a file' '
 306        grep "^rename from" rename.patch &&
 307        rm -fr .git/rebase-apply &&
 308        git reset --hard &&
 309        git checkout lorem^0 &&
 310        git am -3 rename.patch &&
 311        ! test -d .git/rebase-apply &&
 312        git update-index --refresh &&
 313        git diff --exit-code rename
 314'
 315
 316test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
 317        grep "^rename from" rename-add.patch &&
 318        rm -fr .git/rebase-apply &&
 319        git reset --hard &&
 320        git checkout lorem^0 &&
 321        git am -3 rename-add.patch &&
 322        ! test -d .git/rebase-apply &&
 323        git update-index --refresh &&
 324        git diff --exit-code rename
 325'
 326
 327test_expect_success 'am -3 -q is quiet' '
 328        rm -fr .git/rebase-apply &&
 329        git checkout -f lorem2 &&
 330        git reset master2 --hard &&
 331        sed -n -e "3,\$p" msg >file &&
 332        head -n 9 msg >>file &&
 333        git add file &&
 334        test_tick &&
 335        git commit -m "copied stuff" &&
 336        git am -3 -q lorem-move.patch >output.out 2>&1 &&
 337        ! test -s output.out
 338'
 339
 340test_expect_success 'am pauses on conflict' '
 341        rm -fr .git/rebase-apply &&
 342        git reset --hard &&
 343        git checkout lorem2^^ &&
 344        test_must_fail git am lorem-move.patch &&
 345        test -d .git/rebase-apply
 346'
 347
 348test_expect_success 'am --skip works' '
 349        echo goodbye >expected &&
 350        git am --skip &&
 351        ! test -d .git/rebase-apply &&
 352        git diff --exit-code lorem2^^ -- file &&
 353        test_cmp expected another
 354'
 355
 356test_expect_success 'am --resolved works' '
 357        echo goodbye >expected &&
 358        rm -fr .git/rebase-apply &&
 359        git reset --hard &&
 360        git checkout lorem2^^ &&
 361        test_must_fail git am lorem-move.patch &&
 362        test -d .git/rebase-apply &&
 363        echo resolved >>file &&
 364        git add file &&
 365        git am --resolved &&
 366        ! test -d .git/rebase-apply &&
 367        test_cmp expected another
 368'
 369
 370test_expect_success 'am takes patches from a Pine mailbox' '
 371        rm -fr .git/rebase-apply &&
 372        git reset --hard &&
 373        git checkout first &&
 374        cat pine patch1 | git am &&
 375        ! test -d .git/rebase-apply &&
 376        git diff --exit-code master^..HEAD
 377'
 378
 379test_expect_success 'am fails on mail without patch' '
 380        rm -fr .git/rebase-apply &&
 381        git reset --hard &&
 382        test_must_fail git am <failmail &&
 383        git am --abort &&
 384        ! test -d .git/rebase-apply
 385'
 386
 387test_expect_success 'am fails on empty patch' '
 388        rm -fr .git/rebase-apply &&
 389        git reset --hard &&
 390        echo "---" >>failmail &&
 391        test_must_fail git am <failmail &&
 392        git am --skip &&
 393        ! test -d .git/rebase-apply
 394'
 395
 396test_expect_success 'am works from stdin in subdirectory' '
 397        rm -fr subdir &&
 398        rm -fr .git/rebase-apply &&
 399        git reset --hard &&
 400        git checkout first &&
 401        (
 402                mkdir -p subdir &&
 403                cd subdir &&
 404                git am <../patch1
 405        ) &&
 406        git diff --exit-code second
 407'
 408
 409test_expect_success 'am works from file (relative path given) in subdirectory' '
 410        rm -fr subdir &&
 411        rm -fr .git/rebase-apply &&
 412        git reset --hard &&
 413        git checkout first &&
 414        (
 415                mkdir -p subdir &&
 416                cd subdir &&
 417                git am ../patch1
 418        ) &&
 419        git diff --exit-code second
 420'
 421
 422test_expect_success 'am works from file (absolute path given) in subdirectory' '
 423        rm -fr subdir &&
 424        rm -fr .git/rebase-apply &&
 425        git reset --hard &&
 426        git checkout first &&
 427        P=$(pwd) &&
 428        (
 429                mkdir -p subdir &&
 430                cd subdir &&
 431                git am "$P/patch1"
 432        ) &&
 433        git diff --exit-code second
 434'
 435
 436test_expect_success 'am --committer-date-is-author-date' '
 437        rm -fr .git/rebase-apply &&
 438        git reset --hard &&
 439        git checkout first &&
 440        test_tick &&
 441        git am --committer-date-is-author-date patch1 &&
 442        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 443        sed -ne "/^author /s/.*> //p" head1 >at &&
 444        sed -ne "/^committer /s/.*> //p" head1 >ct &&
 445        test_cmp at ct
 446'
 447
 448test_expect_success 'am without --committer-date-is-author-date' '
 449        rm -fr .git/rebase-apply &&
 450        git reset --hard &&
 451        git checkout first &&
 452        test_tick &&
 453        git am patch1 &&
 454        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 455        sed -ne "/^author /s/.*> //p" head1 >at &&
 456        sed -ne "/^committer /s/.*> //p" head1 >ct &&
 457        ! test_cmp at ct
 458'
 459
 460# This checks for +0000 because TZ is set to UTC and that should
 461# show up when the current time is used. The date in message is set
 462# by test_tick that uses -0700 timezone; if this feature does not
 463# work, we will see that instead of +0000.
 464test_expect_success 'am --ignore-date' '
 465        rm -fr .git/rebase-apply &&
 466        git reset --hard &&
 467        git checkout first &&
 468        test_tick &&
 469        git am --ignore-date patch1 &&
 470        git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
 471        sed -ne "/^author /s/.*> //p" head1 >at &&
 472        grep "+0000" at
 473'
 474
 475test_expect_success 'am into an unborn branch' '
 476        git rev-parse first^{tree} >expected &&
 477        rm -fr .git/rebase-apply &&
 478        git reset --hard &&
 479        rm -fr subdir &&
 480        mkdir subdir &&
 481        git format-patch --numbered-files -o subdir -1 first &&
 482        (
 483                cd subdir &&
 484                git init &&
 485                git am 1
 486        ) &&
 487        (
 488                cd subdir &&
 489                git rev-parse HEAD^{tree} >../actual
 490        ) &&
 491        test_cmp expected actual
 492'
 493
 494test_expect_success 'am newline in subject' '
 495        rm -fr .git/rebase-apply &&
 496        git reset --hard &&
 497        git checkout first &&
 498        test_tick &&
 499        sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
 500        git am <patchnl >output.out 2>&1 &&
 501        test_i18ngrep "^Applying: second \\\n foo$" output.out
 502'
 503
 504test_expect_success 'am -q is quiet' '
 505        rm -fr .git/rebase-apply &&
 506        git reset --hard &&
 507        git checkout first &&
 508        test_tick &&
 509        git am -q <patch1 >output.out 2>&1 &&
 510        ! test -s output.out
 511'
 512
 513test_expect_success 'am empty-file does not infloop' '
 514        rm -fr .git/rebase-apply &&
 515        git reset --hard &&
 516        touch empty-file &&
 517        test_tick &&
 518        { git am empty-file > actual 2>&1 && false || :; } &&
 519        echo Patch format detection failed. >expected &&
 520        test_cmp expected actual
 521'
 522
 523test_done