t / t4014-format-patch.shon commit Sync with maint (9ffdd46)
   1#!/bin/sh
   2#
   3# Copyright (c) 2006 Junio C Hamano
   4#
   5
   6test_description='various format-patch tests'
   7
   8. ./test-lib.sh
   9. "$TEST_DIRECTORY"/lib-terminal.sh
  10
  11test_expect_success setup '
  12
  13        for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
  14        cat file >elif &&
  15        git add file elif &&
  16        test_tick &&
  17        git commit -m Initial &&
  18        git checkout -b side &&
  19
  20        for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
  21        test_chmod +x elif &&
  22        test_tick &&
  23        git commit -m "Side changes #1" &&
  24
  25        for i in D E F; do echo "$i"; done >>file &&
  26        git update-index file &&
  27        test_tick &&
  28        git commit -m "Side changes #2" &&
  29        git tag C2 &&
  30
  31        for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
  32        git update-index file &&
  33        test_tick &&
  34        git commit -m "Side changes #3 with \\n backslash-n in it." &&
  35
  36        git checkout master &&
  37        git diff-tree -p C2 | git apply --index &&
  38        test_tick &&
  39        git commit -m "Master accepts moral equivalent of #2"
  40
  41'
  42
  43test_expect_success "format-patch --ignore-if-in-upstream" '
  44
  45        git format-patch --stdout master..side >patch0 &&
  46        cnt=`grep "^From " patch0 | wc -l` &&
  47        test $cnt = 3
  48
  49'
  50
  51test_expect_success "format-patch --ignore-if-in-upstream" '
  52
  53        git format-patch --stdout \
  54                --ignore-if-in-upstream master..side >patch1 &&
  55        cnt=`grep "^From " patch1 | wc -l` &&
  56        test $cnt = 2
  57
  58'
  59
  60test_expect_success "format-patch doesn't consider merge commits" '
  61
  62        git checkout -b slave master &&
  63        echo "Another line" >>file &&
  64        test_tick &&
  65        git commit -am "Slave change #1" &&
  66        echo "Yet another line" >>file &&
  67        test_tick &&
  68        git commit -am "Slave change #2" &&
  69        git checkout -b merger master &&
  70        test_tick &&
  71        git merge --no-ff slave &&
  72        cnt=`git format-patch -3 --stdout | grep "^From " | wc -l` &&
  73        test $cnt = 3
  74'
  75
  76test_expect_success "format-patch result applies" '
  77
  78        git checkout -b rebuild-0 master &&
  79        git am -3 patch0 &&
  80        cnt=`git rev-list master.. | wc -l` &&
  81        test $cnt = 2
  82'
  83
  84test_expect_success "format-patch --ignore-if-in-upstream result applies" '
  85
  86        git checkout -b rebuild-1 master &&
  87        git am -3 patch1 &&
  88        cnt=`git rev-list master.. | wc -l` &&
  89        test $cnt = 2
  90'
  91
  92test_expect_success 'commit did not screw up the log message' '
  93
  94        git cat-file commit side | grep "^Side .* with .* backslash-n"
  95
  96'
  97
  98test_expect_success 'format-patch did not screw up the log message' '
  99
 100        grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
 101        grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
 102
 103'
 104
 105test_expect_success 'replay did not screw up the log message' '
 106
 107        git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
 108
 109'
 110
 111test_expect_success 'extra headers' '
 112
 113        git config format.headers "To: R. E. Cipient <rcipient@example.com>
 114" &&
 115        git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>
 116" &&
 117        git format-patch --stdout master..side > patch2 &&
 118        sed -e "/^\$/q" patch2 > hdrs2 &&
 119        grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs2 &&
 120        grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs2
 121
 122'
 123
 124test_expect_success 'extra headers without newlines' '
 125
 126        git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
 127        git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>" &&
 128        git format-patch --stdout master..side >patch3 &&
 129        sed -e "/^\$/q" patch3 > hdrs3 &&
 130        grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs3 &&
 131        grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs3
 132
 133'
 134
 135test_expect_success 'extra headers with multiple To:s' '
 136
 137        git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
 138        git config --add format.headers "To: S. E. Cipient <scipient@example.com>" &&
 139        git format-patch --stdout master..side > patch4 &&
 140        sed -e "/^\$/q" patch4 > hdrs4 &&
 141        grep "^To: R. E. Cipient <rcipient@example.com>,\$" hdrs4 &&
 142        grep "^ *S. E. Cipient <scipient@example.com>\$" hdrs4
 143'
 144
 145test_expect_success 'additional command line cc' '
 146
 147        git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
 148        git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
 149        grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch5 &&
 150        grep "^ *S. E. Cipient <scipient@example.com>\$" patch5
 151'
 152
 153test_expect_success 'command line headers' '
 154
 155        git config --unset-all format.headers &&
 156        git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
 157        grep "^Cc: R. E. Cipient <rcipient@example.com>\$" patch6
 158'
 159
 160test_expect_success 'configuration headers and command line headers' '
 161
 162        git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
 163        git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
 164        grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch7 &&
 165        grep "^ *S. E. Cipient <scipient@example.com>\$" patch7
 166'
 167
 168test_expect_success 'command line To: header' '
 169
 170        git config --unset-all format.headers &&
 171        git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
 172        grep "^To: R. E. Cipient <rcipient@example.com>\$" patch8
 173'
 174
 175test_expect_success 'configuration To: header' '
 176
 177        git config format.to "R. E. Cipient <rcipient@example.com>" &&
 178        git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
 179        grep "^To: R. E. Cipient <rcipient@example.com>\$" patch9
 180'
 181
 182# check_patch <patch>: Verify that <patch> looks like a half-sane
 183# patch email to avoid a false positive with !grep
 184check_patch () {
 185        grep -e "^From:" "$1" &&
 186        grep -e "^Date:" "$1" &&
 187        grep -e "^Subject:" "$1"
 188}
 189
 190test_expect_success '--no-to overrides config.to' '
 191
 192        git config --replace-all format.to \
 193                "R. E. Cipient <rcipient@example.com>" &&
 194        git format-patch --no-to --stdout master..side |
 195        sed -e "/^\$/q" >patch10 &&
 196        check_patch patch10 &&
 197        ! grep "^To: R. E. Cipient <rcipient@example.com>\$" patch10
 198'
 199
 200test_expect_success '--no-to and --to replaces config.to' '
 201
 202        git config --replace-all format.to \
 203                "Someone <someone@out.there>" &&
 204        git format-patch --no-to --to="Someone Else <else@out.there>" \
 205                --stdout master..side |
 206        sed -e "/^\$/q" >patch11 &&
 207        check_patch patch11 &&
 208        ! grep "^To: Someone <someone@out.there>\$" patch11 &&
 209        grep "^To: Someone Else <else@out.there>\$" patch11
 210'
 211
 212test_expect_success '--no-cc overrides config.cc' '
 213
 214        git config --replace-all format.cc \
 215                "C. E. Cipient <rcipient@example.com>" &&
 216        git format-patch --no-cc --stdout master..side |
 217        sed -e "/^\$/q" >patch12 &&
 218        check_patch patch12 &&
 219        ! grep "^Cc: C. E. Cipient <rcipient@example.com>\$" patch12
 220'
 221
 222test_expect_success '--no-add-header overrides config.headers' '
 223
 224        git config --replace-all format.headers \
 225                "Header1: B. E. Cipient <rcipient@example.com>" &&
 226        git format-patch --no-add-header --stdout master..side |
 227        sed -e "/^\$/q" >patch13 &&
 228        check_patch patch13 &&
 229        ! grep "^Header1: B. E. Cipient <rcipient@example.com>\$" patch13
 230'
 231
 232test_expect_success 'multiple files' '
 233
 234        rm -rf patches/ &&
 235        git checkout side &&
 236        git format-patch -o patches/ master &&
 237        ls patches/0001-Side-changes-1.patch patches/0002-Side-changes-2.patch patches/0003-Side-changes-3-with-n-backslash-n-in-it.patch
 238'
 239
 240check_threading () {
 241        expect="$1" &&
 242        shift &&
 243        (git format-patch --stdout "$@"; echo $? > status.out) |
 244        # Prints everything between the Message-ID and In-Reply-To,
 245        # and replaces all Message-ID-lookalikes by a sequence number
 246        "$PERL_PATH" -ne '
 247                if (/^(message-id|references|in-reply-to)/i) {
 248                        $printing = 1;
 249                } elsif (/^\S/) {
 250                        $printing = 0;
 251                }
 252                if ($printing) {
 253                        $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
 254                        for $k (keys %h) {s/$k/$h{$k}/};
 255                        print;
 256                }
 257                print "---\n" if /^From /i;
 258        ' > actual &&
 259        test 0 = "$(cat status.out)" &&
 260        test_cmp "$expect" actual
 261}
 262
 263cat >> expect.no-threading <<EOF
 264---
 265---
 266---
 267EOF
 268
 269test_expect_success 'no threading' '
 270        git checkout side &&
 271        check_threading expect.no-threading master
 272'
 273
 274cat > expect.thread <<EOF
 275---
 276Message-Id: <0>
 277---
 278Message-Id: <1>
 279In-Reply-To: <0>
 280References: <0>
 281---
 282Message-Id: <2>
 283In-Reply-To: <0>
 284References: <0>
 285EOF
 286
 287test_expect_success 'thread' '
 288        check_threading expect.thread --thread master
 289'
 290
 291cat > expect.in-reply-to <<EOF
 292---
 293Message-Id: <0>
 294In-Reply-To: <1>
 295References: <1>
 296---
 297Message-Id: <2>
 298In-Reply-To: <1>
 299References: <1>
 300---
 301Message-Id: <3>
 302In-Reply-To: <1>
 303References: <1>
 304EOF
 305
 306test_expect_success 'thread in-reply-to' '
 307        check_threading expect.in-reply-to --in-reply-to="<test.message>" \
 308                --thread master
 309'
 310
 311cat > expect.cover-letter <<EOF
 312---
 313Message-Id: <0>
 314---
 315Message-Id: <1>
 316In-Reply-To: <0>
 317References: <0>
 318---
 319Message-Id: <2>
 320In-Reply-To: <0>
 321References: <0>
 322---
 323Message-Id: <3>
 324In-Reply-To: <0>
 325References: <0>
 326EOF
 327
 328test_expect_success 'thread cover-letter' '
 329        check_threading expect.cover-letter --cover-letter --thread master
 330'
 331
 332cat > expect.cl-irt <<EOF
 333---
 334Message-Id: <0>
 335In-Reply-To: <1>
 336References: <1>
 337---
 338Message-Id: <2>
 339In-Reply-To: <0>
 340References: <1>
 341        <0>
 342---
 343Message-Id: <3>
 344In-Reply-To: <0>
 345References: <1>
 346        <0>
 347---
 348Message-Id: <4>
 349In-Reply-To: <0>
 350References: <1>
 351        <0>
 352EOF
 353
 354test_expect_success 'thread cover-letter in-reply-to' '
 355        check_threading expect.cl-irt --cover-letter \
 356                --in-reply-to="<test.message>" --thread master
 357'
 358
 359test_expect_success 'thread explicit shallow' '
 360        check_threading expect.cl-irt --cover-letter \
 361                --in-reply-to="<test.message>" --thread=shallow master
 362'
 363
 364cat > expect.deep <<EOF
 365---
 366Message-Id: <0>
 367---
 368Message-Id: <1>
 369In-Reply-To: <0>
 370References: <0>
 371---
 372Message-Id: <2>
 373In-Reply-To: <1>
 374References: <0>
 375        <1>
 376EOF
 377
 378test_expect_success 'thread deep' '
 379        check_threading expect.deep --thread=deep master
 380'
 381
 382cat > expect.deep-irt <<EOF
 383---
 384Message-Id: <0>
 385In-Reply-To: <1>
 386References: <1>
 387---
 388Message-Id: <2>
 389In-Reply-To: <0>
 390References: <1>
 391        <0>
 392---
 393Message-Id: <3>
 394In-Reply-To: <2>
 395References: <1>
 396        <0>
 397        <2>
 398EOF
 399
 400test_expect_success 'thread deep in-reply-to' '
 401        check_threading expect.deep-irt  --thread=deep \
 402                --in-reply-to="<test.message>" master
 403'
 404
 405cat > expect.deep-cl <<EOF
 406---
 407Message-Id: <0>
 408---
 409Message-Id: <1>
 410In-Reply-To: <0>
 411References: <0>
 412---
 413Message-Id: <2>
 414In-Reply-To: <1>
 415References: <0>
 416        <1>
 417---
 418Message-Id: <3>
 419In-Reply-To: <2>
 420References: <0>
 421        <1>
 422        <2>
 423EOF
 424
 425test_expect_success 'thread deep cover-letter' '
 426        check_threading expect.deep-cl --cover-letter --thread=deep master
 427'
 428
 429cat > expect.deep-cl-irt <<EOF
 430---
 431Message-Id: <0>
 432In-Reply-To: <1>
 433References: <1>
 434---
 435Message-Id: <2>
 436In-Reply-To: <0>
 437References: <1>
 438        <0>
 439---
 440Message-Id: <3>
 441In-Reply-To: <2>
 442References: <1>
 443        <0>
 444        <2>
 445---
 446Message-Id: <4>
 447In-Reply-To: <3>
 448References: <1>
 449        <0>
 450        <2>
 451        <3>
 452EOF
 453
 454test_expect_success 'thread deep cover-letter in-reply-to' '
 455        check_threading expect.deep-cl-irt --cover-letter \
 456                --in-reply-to="<test.message>" --thread=deep master
 457'
 458
 459test_expect_success 'thread via config' '
 460        test_config format.thread true &&
 461        check_threading expect.thread master
 462'
 463
 464test_expect_success 'thread deep via config' '
 465        test_config format.thread deep &&
 466        check_threading expect.deep master
 467'
 468
 469test_expect_success 'thread config + override' '
 470        test_config format.thread deep &&
 471        check_threading expect.thread --thread master
 472'
 473
 474test_expect_success 'thread config + --no-thread' '
 475        test_config format.thread deep &&
 476        check_threading expect.no-threading --no-thread master
 477'
 478
 479test_expect_success 'excessive subject' '
 480
 481        rm -rf patches/ &&
 482        git checkout side &&
 483        for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
 484        git update-index file &&
 485        git commit -m "This is an excessively long subject line for a message due to the habit some projects have of not having a short, one-line subject at the start of the commit message, but rather sticking a whole paragraph right at the start as the only thing in the commit message. It had better not become the filename for the patch." &&
 486        git format-patch -o patches/ master..side &&
 487        ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
 488'
 489
 490test_expect_success 'cover-letter inherits diff options' '
 491
 492        git mv file foo &&
 493        git commit -m foo &&
 494        git format-patch --cover-letter -1 &&
 495        check_patch 0000-cover-letter.patch &&
 496        ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
 497        git format-patch --cover-letter -1 -M &&
 498        grep "file => foo .* 0 *\$" 0000-cover-letter.patch
 499
 500'
 501
 502cat > expect << EOF
 503  This is an excessively long subject line for a message due to the
 504    habit some projects have of not having a short, one-line subject at
 505    the start of the commit message, but rather sticking a whole
 506    paragraph right at the start as the only thing in the commit
 507    message. It had better not become the filename for the patch.
 508  foo
 509
 510EOF
 511
 512test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
 513
 514        git format-patch --cover-letter -2 &&
 515        sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
 516        test_cmp expect output
 517
 518'
 519
 520cat > expect << EOF
 521index 40f36c6..2dc5c23 100644
 522--- a/file
 523+++ b/file
 524@@ -13,4 +13,20 @@ C
 525 10
 526 D
 527 E
 528 F
 529+5
 530EOF
 531
 532test_expect_success 'format-patch respects -U' '
 533
 534        git format-patch -U4 -2 &&
 535        sed -e "1,/^diff/d" -e "/^+5/q" \
 536                <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
 537                >output &&
 538        test_cmp expect output
 539
 540'
 541
 542cat > expect << EOF
 543
 544diff --git a/file b/file
 545index 40f36c6..2dc5c23 100644
 546--- a/file
 547+++ b/file
 548@@ -14,3 +14,19 @@ C
 549 D
 550 E
 551 F
 552+5
 553EOF
 554
 555test_expect_success 'format-patch -p suppresses stat' '
 556
 557        git format-patch -p -2 &&
 558        sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
 559        test_cmp expect output
 560
 561'
 562
 563test_expect_success 'format-patch from a subdirectory (1)' '
 564        filename=$(
 565                rm -rf sub &&
 566                mkdir -p sub/dir &&
 567                cd sub/dir &&
 568                git format-patch -1
 569        ) &&
 570        case "$filename" in
 571        0*)
 572                ;; # ok
 573        *)
 574                echo "Oops? $filename"
 575                false
 576                ;;
 577        esac &&
 578        test -f "$filename"
 579'
 580
 581test_expect_success 'format-patch from a subdirectory (2)' '
 582        filename=$(
 583                rm -rf sub &&
 584                mkdir -p sub/dir &&
 585                cd sub/dir &&
 586                git format-patch -1 -o ..
 587        ) &&
 588        case "$filename" in
 589        ../0*)
 590                ;; # ok
 591        *)
 592                echo "Oops? $filename"
 593                false
 594                ;;
 595        esac &&
 596        basename=$(expr "$filename" : ".*/\(.*\)") &&
 597        test -f "sub/$basename"
 598'
 599
 600test_expect_success 'format-patch from a subdirectory (3)' '
 601        rm -f 0* &&
 602        filename=$(
 603                rm -rf sub &&
 604                mkdir -p sub/dir &&
 605                cd sub/dir &&
 606                git format-patch -1 -o "$TRASH_DIRECTORY"
 607        ) &&
 608        basename=$(expr "$filename" : ".*/\(.*\)") &&
 609        test -f "$basename"
 610'
 611
 612test_expect_success 'format-patch --in-reply-to' '
 613        git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
 614        grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
 615        grep "^References: <baz@foo.bar>" patch8
 616'
 617
 618test_expect_success 'format-patch --signoff' '
 619        git format-patch -1 --signoff --stdout |
 620        grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
 621'
 622
 623echo "fatal: --name-only does not make sense" > expect.name-only
 624echo "fatal: --name-status does not make sense" > expect.name-status
 625echo "fatal: --check does not make sense" > expect.check
 626
 627test_expect_success 'options no longer allowed for format-patch' '
 628        test_must_fail git format-patch --name-only 2> output &&
 629        test_i18ncmp expect.name-only output &&
 630        test_must_fail git format-patch --name-status 2> output &&
 631        test_i18ncmp expect.name-status output &&
 632        test_must_fail git format-patch --check 2> output &&
 633        test_i18ncmp expect.check output'
 634
 635test_expect_success 'format-patch --numstat should produce a patch' '
 636        git format-patch --numstat --stdout master..side > output &&
 637        test 6 = $(grep "^diff --git a/" output | wc -l)'
 638
 639test_expect_success 'format-patch -- <path>' '
 640        git format-patch master..side -- file 2>error &&
 641        ! grep "Use .--" error
 642'
 643
 644test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
 645        git format-patch --ignore-if-in-upstream HEAD
 646'
 647
 648test_expect_success 'format-patch --signature' '
 649        git format-patch --stdout --signature="my sig" -1 >output &&
 650        grep "my sig" output
 651'
 652
 653test_expect_success 'format-patch with format.signature config' '
 654        git config format.signature "config sig" &&
 655        git format-patch --stdout -1 >output &&
 656        grep "config sig" output
 657'
 658
 659test_expect_success 'format-patch --signature overrides format.signature' '
 660        git config format.signature "config sig" &&
 661        git format-patch --stdout --signature="overrides" -1 >output &&
 662        ! grep "config sig" output &&
 663        grep "overrides" output
 664'
 665
 666test_expect_success 'format-patch --no-signature ignores format.signature' '
 667        git config format.signature "config sig" &&
 668        git format-patch --stdout --signature="my sig" --no-signature \
 669                -1 >output &&
 670        check_patch output &&
 671        ! grep "config sig" output &&
 672        ! grep "my sig" output &&
 673        ! grep "^-- \$" output
 674'
 675
 676test_expect_success 'format-patch --signature --cover-letter' '
 677        git config --unset-all format.signature &&
 678        git format-patch --stdout --signature="my sig" --cover-letter \
 679                -1 >output &&
 680        grep "my sig" output &&
 681        test 2 = $(grep "my sig" output | wc -l)
 682'
 683
 684test_expect_success 'format.signature="" supresses signatures' '
 685        git config format.signature "" &&
 686        git format-patch --stdout -1 >output &&
 687        check_patch output &&
 688        ! grep "^-- \$" output
 689'
 690
 691test_expect_success 'format-patch --no-signature supresses signatures' '
 692        git config --unset-all format.signature &&
 693        git format-patch --stdout --no-signature -1 >output &&
 694        check_patch output &&
 695        ! grep "^-- \$" output
 696'
 697
 698test_expect_success 'format-patch --signature="" supresses signatures' '
 699        git format-patch --stdout --signature="" -1 >output &&
 700        check_patch output &&
 701        ! grep "^-- \$" output
 702'
 703
 704test_expect_success TTY 'format-patch --stdout paginates' '
 705        rm -f pager_used &&
 706        (
 707                GIT_PAGER="wc >pager_used" &&
 708                export GIT_PAGER &&
 709                test_terminal git format-patch --stdout --all
 710        ) &&
 711        test_path_is_file pager_used
 712'
 713
 714 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
 715        rm -f pager_used &&
 716        (
 717                GIT_PAGER="wc >pager_used" &&
 718                export GIT_PAGER &&
 719                test_terminal git --no-pager format-patch --stdout --all &&
 720                test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
 721        ) &&
 722        test_path_is_missing pager_used &&
 723        test_path_is_missing .git/pager_used
 724'
 725
 726test_expect_success 'format-patch handles multi-line subjects' '
 727        rm -rf patches/ &&
 728        echo content >>file &&
 729        for i in one two three; do echo $i; done >msg &&
 730        git add file &&
 731        git commit -F msg &&
 732        git format-patch -o patches -1 &&
 733        grep ^Subject: patches/0001-one.patch >actual &&
 734        echo "Subject: [PATCH] one two three" >expect &&
 735        test_cmp expect actual
 736'
 737
 738test_expect_success 'format-patch handles multi-line encoded subjects' '
 739        rm -rf patches/ &&
 740        echo content >>file &&
 741        for i in en två tre; do echo $i; done >msg &&
 742        git add file &&
 743        git commit -F msg &&
 744        git format-patch -o patches -1 &&
 745        grep ^Subject: patches/0001-en.patch >actual &&
 746        echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
 747        test_cmp expect actual
 748'
 749
 750M8="foo bar "
 751M64=$M8$M8$M8$M8$M8$M8$M8$M8
 752M512=$M64$M64$M64$M64$M64$M64$M64$M64
 753cat >expect <<'EOF'
 754Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 755 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 756 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 757 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 758 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 759 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 760 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 761 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 762 foo bar foo bar foo bar foo bar
 763EOF
 764test_expect_success 'format-patch wraps extremely long headers (ascii)' '
 765        echo content >>file &&
 766        git add file &&
 767        git commit -m "$M512" &&
 768        git format-patch --stdout -1 >patch &&
 769        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 770        test_cmp expect subject
 771'
 772
 773M8="föö bar "
 774M64=$M8$M8$M8$M8$M8$M8$M8$M8
 775M512=$M64$M64$M64$M64$M64$M64$M64$M64
 776cat >expect <<'EOF'
 777Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 778 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 779 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 780 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 781 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 782 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 783 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 784 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 785 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 786 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 787 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 788 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 789 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 790 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 791 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 792 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 793 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 794 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 795 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 796 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 797 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 798 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 799EOF
 800test_expect_success 'format-patch wraps extremely long headers (rfc2047)' '
 801        rm -rf patches/ &&
 802        echo content >>file &&
 803        git add file &&
 804        git commit -m "$M512" &&
 805        git format-patch --stdout -1 >patch &&
 806        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 807        test_cmp expect subject
 808'
 809
 810M8="foo_bar_"
 811M64=$M8$M8$M8$M8$M8$M8$M8$M8
 812cat >expect <<EOF
 813From: $M64
 814 <foobar@foo.bar>
 815EOF
 816test_expect_success 'format-patch wraps non-quotable headers' '
 817        rm -rf patches/ &&
 818        echo content >>file &&
 819        git add file &&
 820        git commit -mfoo --author "$M64 <foobar@foo.bar>" &&
 821        git format-patch --stdout -1 >patch &&
 822        sed -n "/^From: /p; /^ /p; /^$/q" <patch >from &&
 823        test_cmp expect from
 824'
 825
 826check_author() {
 827        echo content >>file &&
 828        git add file &&
 829        GIT_AUTHOR_NAME=$1 git commit -m author-check &&
 830        git format-patch --stdout -1 >patch &&
 831        grep ^From: patch >actual &&
 832        test_cmp expect actual
 833}
 834
 835cat >expect <<'EOF'
 836From: "Foo B. Bar" <author@example.com>
 837EOF
 838test_expect_success 'format-patch quotes dot in headers' '
 839        check_author "Foo B. Bar"
 840'
 841
 842cat >expect <<'EOF'
 843From: "Foo \"The Baz\" Bar" <author@example.com>
 844EOF
 845test_expect_success 'format-patch quotes double-quote in headers' '
 846        check_author "Foo \"The Baz\" Bar"
 847'
 848
 849cat >expect <<'EOF'
 850From: =?UTF-8?q?"F=C3=B6o=20B.=20Bar"?= <author@example.com>
 851EOF
 852test_expect_success 'rfc2047-encoded headers also double-quote 822 specials' '
 853        check_author "Föo B. Bar"
 854'
 855
 856cat >expect <<'EOF'
 857Subject: header with . in it
 858EOF
 859test_expect_success 'subject lines do not have 822 atom-quoting' '
 860        echo content >>file &&
 861        git add file &&
 862        git commit -m "header with . in it" &&
 863        git format-patch -k -1 --stdout >patch &&
 864        grep ^Subject: patch >actual &&
 865        test_cmp expect actual
 866'
 867
 868cat >expect <<'EOF'
 869Subject: [PREFIX 1/1] header with . in it
 870EOF
 871test_expect_success 'subject prefixes have space prepended' '
 872        git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
 873        grep ^Subject: patch >actual &&
 874        test_cmp expect actual
 875'
 876
 877cat >expect <<'EOF'
 878Subject: [1/1] header with . in it
 879EOF
 880test_expect_success 'empty subject prefix does not have extra space' '
 881        git format-patch -n -1 --stdout --subject-prefix= >patch &&
 882        grep ^Subject: patch >actual &&
 883        test_cmp expect actual
 884'
 885
 886test_expect_success 'format patch ignores color.ui' '
 887        test_unconfig color.ui &&
 888        git format-patch --stdout -1 >expect &&
 889        test_config color.ui always &&
 890        git format-patch --stdout -1 >actual &&
 891        test_cmp expect actual
 892'
 893
 894test_done