t / t4014-format-patch.shon commit symbolic-ref --short: abbreviate the output unambiguously (42b0059)
   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 -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
 521---
 522 file |   16 ++++++++++++++++
 523 1 file changed, 16 insertions(+)
 524
 525diff --git a/file b/file
 526index 40f36c6..2dc5c23 100644
 527--- a/file
 528+++ b/file
 529@@ -13,4 +13,20 @@ C
 530 10
 531 D
 532 E
 533 F
 534+5
 535EOF
 536
 537test_expect_success 'format-patch respects -U' '
 538
 539        git format-patch -U4 -2 &&
 540        sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
 541        test_cmp expect output
 542
 543'
 544
 545cat > expect << EOF
 546
 547diff --git a/file b/file
 548index 40f36c6..2dc5c23 100644
 549--- a/file
 550+++ b/file
 551@@ -14,3 +14,19 @@ C
 552 D
 553 E
 554 F
 555+5
 556EOF
 557
 558test_expect_success 'format-patch -p suppresses stat' '
 559
 560        git format-patch -p -2 &&
 561        sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
 562        test_cmp expect output
 563
 564'
 565
 566test_expect_success 'format-patch from a subdirectory (1)' '
 567        filename=$(
 568                rm -rf sub &&
 569                mkdir -p sub/dir &&
 570                cd sub/dir &&
 571                git format-patch -1
 572        ) &&
 573        case "$filename" in
 574        0*)
 575                ;; # ok
 576        *)
 577                echo "Oops? $filename"
 578                false
 579                ;;
 580        esac &&
 581        test -f "$filename"
 582'
 583
 584test_expect_success 'format-patch from a subdirectory (2)' '
 585        filename=$(
 586                rm -rf sub &&
 587                mkdir -p sub/dir &&
 588                cd sub/dir &&
 589                git format-patch -1 -o ..
 590        ) &&
 591        case "$filename" in
 592        ../0*)
 593                ;; # ok
 594        *)
 595                echo "Oops? $filename"
 596                false
 597                ;;
 598        esac &&
 599        basename=$(expr "$filename" : ".*/\(.*\)") &&
 600        test -f "sub/$basename"
 601'
 602
 603test_expect_success 'format-patch from a subdirectory (3)' '
 604        rm -f 0* &&
 605        filename=$(
 606                rm -rf sub &&
 607                mkdir -p sub/dir &&
 608                cd sub/dir &&
 609                git format-patch -1 -o "$TRASH_DIRECTORY"
 610        ) &&
 611        basename=$(expr "$filename" : ".*/\(.*\)") &&
 612        test -f "$basename"
 613'
 614
 615test_expect_success 'format-patch --in-reply-to' '
 616        git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
 617        grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
 618        grep "^References: <baz@foo.bar>" patch8
 619'
 620
 621test_expect_success 'format-patch --signoff' '
 622        git format-patch -1 --signoff --stdout |
 623        grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
 624'
 625
 626echo "fatal: --name-only does not make sense" > expect.name-only
 627echo "fatal: --name-status does not make sense" > expect.name-status
 628echo "fatal: --check does not make sense" > expect.check
 629
 630test_expect_success 'options no longer allowed for format-patch' '
 631        test_must_fail git format-patch --name-only 2> output &&
 632        test_i18ncmp expect.name-only output &&
 633        test_must_fail git format-patch --name-status 2> output &&
 634        test_i18ncmp expect.name-status output &&
 635        test_must_fail git format-patch --check 2> output &&
 636        test_i18ncmp expect.check output'
 637
 638test_expect_success 'format-patch --numstat should produce a patch' '
 639        git format-patch --numstat --stdout master..side > output &&
 640        test 6 = $(grep "^diff --git a/" output | wc -l)'
 641
 642test_expect_success 'format-patch -- <path>' '
 643        git format-patch master..side -- file 2>error &&
 644        ! grep "Use .--" error
 645'
 646
 647test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
 648        git format-patch --ignore-if-in-upstream HEAD
 649'
 650
 651test_expect_success 'format-patch --signature' '
 652        git format-patch --stdout --signature="my sig" -1 >output &&
 653        grep "my sig" output
 654'
 655
 656test_expect_success 'format-patch with format.signature config' '
 657        git config format.signature "config sig" &&
 658        git format-patch --stdout -1 >output &&
 659        grep "config sig" output
 660'
 661
 662test_expect_success 'format-patch --signature overrides format.signature' '
 663        git config format.signature "config sig" &&
 664        git format-patch --stdout --signature="overrides" -1 >output &&
 665        ! grep "config sig" output &&
 666        grep "overrides" output
 667'
 668
 669test_expect_success 'format-patch --no-signature ignores format.signature' '
 670        git config format.signature "config sig" &&
 671        git format-patch --stdout --signature="my sig" --no-signature \
 672                -1 >output &&
 673        check_patch output &&
 674        ! grep "config sig" output &&
 675        ! grep "my sig" output &&
 676        ! grep "^-- \$" output
 677'
 678
 679test_expect_success 'format-patch --signature --cover-letter' '
 680        git config --unset-all format.signature &&
 681        git format-patch --stdout --signature="my sig" --cover-letter \
 682                -1 >output &&
 683        grep "my sig" output &&
 684        test 2 = $(grep "my sig" output | wc -l)
 685'
 686
 687test_expect_success 'format.signature="" supresses signatures' '
 688        git config format.signature "" &&
 689        git format-patch --stdout -1 >output &&
 690        check_patch output &&
 691        ! grep "^-- \$" output
 692'
 693
 694test_expect_success 'format-patch --no-signature supresses signatures' '
 695        git config --unset-all format.signature &&
 696        git format-patch --stdout --no-signature -1 >output &&
 697        check_patch output &&
 698        ! grep "^-- \$" output
 699'
 700
 701test_expect_success 'format-patch --signature="" supresses signatures' '
 702        git format-patch --stdout --signature="" -1 >output &&
 703        check_patch output &&
 704        ! grep "^-- \$" output
 705'
 706
 707test_expect_success TTY 'format-patch --stdout paginates' '
 708        rm -f pager_used &&
 709        (
 710                GIT_PAGER="wc >pager_used" &&
 711                export GIT_PAGER &&
 712                test_terminal git format-patch --stdout --all
 713        ) &&
 714        test_path_is_file pager_used
 715'
 716
 717 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
 718        rm -f pager_used &&
 719        (
 720                GIT_PAGER="wc >pager_used" &&
 721                export GIT_PAGER &&
 722                test_terminal git --no-pager format-patch --stdout --all &&
 723                test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
 724        ) &&
 725        test_path_is_missing pager_used &&
 726        test_path_is_missing .git/pager_used
 727'
 728
 729test_expect_success 'format-patch handles multi-line subjects' '
 730        rm -rf patches/ &&
 731        echo content >>file &&
 732        for i in one two three; do echo $i; done >msg &&
 733        git add file &&
 734        git commit -F msg &&
 735        git format-patch -o patches -1 &&
 736        grep ^Subject: patches/0001-one.patch >actual &&
 737        echo "Subject: [PATCH] one two three" >expect &&
 738        test_cmp expect actual
 739'
 740
 741test_expect_success 'format-patch handles multi-line encoded subjects' '
 742        rm -rf patches/ &&
 743        echo content >>file &&
 744        for i in en två tre; do echo $i; done >msg &&
 745        git add file &&
 746        git commit -F msg &&
 747        git format-patch -o patches -1 &&
 748        grep ^Subject: patches/0001-en.patch >actual &&
 749        echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
 750        test_cmp expect actual
 751'
 752
 753M8="foo bar "
 754M64=$M8$M8$M8$M8$M8$M8$M8$M8
 755M512=$M64$M64$M64$M64$M64$M64$M64$M64
 756cat >expect <<'EOF'
 757Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 758 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 759 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 760 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 761 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 762 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 763 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 764 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 765 foo bar foo bar foo bar foo bar
 766EOF
 767test_expect_success 'format-patch wraps extremely long headers (ascii)' '
 768        echo content >>file &&
 769        git add file &&
 770        git commit -m "$M512" &&
 771        git format-patch --stdout -1 >patch &&
 772        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 773        test_cmp expect subject
 774'
 775
 776M8="föö bar "
 777M64=$M8$M8$M8$M8$M8$M8$M8$M8
 778M512=$M64$M64$M64$M64$M64$M64$M64$M64
 779cat >expect <<'EOF'
 780Subject: [PATCH] =?UTF-8?q?f=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=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 799 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 800 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 801 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 802EOF
 803test_expect_success 'format-patch wraps extremely long headers (rfc2047)' '
 804        rm -rf patches/ &&
 805        echo content >>file &&
 806        git add file &&
 807        git commit -m "$M512" &&
 808        git format-patch --stdout -1 >patch &&
 809        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 810        test_cmp expect subject
 811'
 812
 813M8="foo_bar_"
 814M64=$M8$M8$M8$M8$M8$M8$M8$M8
 815cat >expect <<EOF
 816From: $M64
 817 <foobar@foo.bar>
 818EOF
 819test_expect_success 'format-patch wraps non-quotable headers' '
 820        rm -rf patches/ &&
 821        echo content >>file &&
 822        git add file &&
 823        git commit -mfoo --author "$M64 <foobar@foo.bar>" &&
 824        git format-patch --stdout -1 >patch &&
 825        sed -n "/^From: /p; /^ /p; /^$/q" <patch >from &&
 826        test_cmp expect from
 827'
 828
 829check_author() {
 830        echo content >>file &&
 831        git add file &&
 832        GIT_AUTHOR_NAME=$1 git commit -m author-check &&
 833        git format-patch --stdout -1 >patch &&
 834        grep ^From: patch >actual &&
 835        test_cmp expect actual
 836}
 837
 838cat >expect <<'EOF'
 839From: "Foo B. Bar" <author@example.com>
 840EOF
 841test_expect_success 'format-patch quotes dot in headers' '
 842        check_author "Foo B. Bar"
 843'
 844
 845cat >expect <<'EOF'
 846From: "Foo \"The Baz\" Bar" <author@example.com>
 847EOF
 848test_expect_success 'format-patch quotes double-quote in headers' '
 849        check_author "Foo \"The Baz\" Bar"
 850'
 851
 852cat >expect <<'EOF'
 853From: =?UTF-8?q?"F=C3=B6o=20B.=20Bar"?= <author@example.com>
 854EOF
 855test_expect_success 'rfc2047-encoded headers also double-quote 822 specials' '
 856        check_author "Föo B. Bar"
 857'
 858
 859cat >expect <<'EOF'
 860Subject: header with . in it
 861EOF
 862test_expect_success 'subject lines do not have 822 atom-quoting' '
 863        echo content >>file &&
 864        git add file &&
 865        git commit -m "header with . in it" &&
 866        git format-patch -k -1 --stdout >patch &&
 867        grep ^Subject: patch >actual &&
 868        test_cmp expect actual
 869'
 870
 871cat >expect <<'EOF'
 872Subject: [PREFIX 1/1] header with . in it
 873EOF
 874test_expect_success 'subject prefixes have space prepended' '
 875        git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
 876        grep ^Subject: patch >actual &&
 877        test_cmp expect actual
 878'
 879
 880cat >expect <<'EOF'
 881Subject: [1/1] header with . in it
 882EOF
 883test_expect_success 'empty subject prefix does not have extra space' '
 884        git format-patch -n -1 --stdout --subject-prefix= >patch &&
 885        grep ^Subject: patch >actual &&
 886        test_cmp expect actual
 887'
 888
 889test_expect_success 'format patch ignores color.ui' '
 890        test_unconfig color.ui &&
 891        git format-patch --stdout -1 >expect &&
 892        test_config color.ui always &&
 893        git format-patch --stdout -1 >actual &&
 894        test_cmp expect actual
 895'
 896
 897test_done