t / t4014-format-patch.shon commit Merge branch 'km/send-email-compose-encoding' (05eda51)
   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 (ascii)' '
 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_failure 'additional command line cc (rfc822)' '
 154
 155        git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
 156        git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
 157        grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
 158        grep "^ *"S. E. Cipient" <scipient@example.com>\$" patch5
 159'
 160
 161test_expect_success 'command line headers' '
 162
 163        git config --unset-all format.headers &&
 164        git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
 165        grep "^Cc: R E Cipient <rcipient@example.com>\$" patch6
 166'
 167
 168test_expect_success 'configuration headers and command line headers' '
 169
 170        git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
 171        git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
 172        grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch7 &&
 173        grep "^ *S E Cipient <scipient@example.com>\$" patch7
 174'
 175
 176test_expect_success 'command line To: header (ascii)' '
 177
 178        git config --unset-all format.headers &&
 179        git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
 180        grep "^To: R E Cipient <rcipient@example.com>\$" patch8
 181'
 182
 183test_expect_failure 'command line To: header (rfc822)' '
 184
 185        git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
 186        grep "^To: "R. E. Cipient" <rcipient@example.com>\$" patch8
 187'
 188
 189test_expect_failure 'command line To: header (rfc2047)' '
 190
 191        git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
 192        grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch8
 193'
 194
 195test_expect_success 'configuration To: header (ascii)' '
 196
 197        git config format.to "R E Cipient <rcipient@example.com>" &&
 198        git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
 199        grep "^To: R E Cipient <rcipient@example.com>\$" patch9
 200'
 201
 202test_expect_failure 'configuration To: header (rfc822)' '
 203
 204        git config format.to "R. E. Cipient <rcipient@example.com>" &&
 205        git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
 206        grep "^To: "R. E. Cipient" <rcipient@example.com>\$" patch9
 207'
 208
 209test_expect_failure 'configuration To: header (rfc2047)' '
 210
 211        git config format.to "R Ä Cipient <rcipient@example.com>" &&
 212        git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
 213        grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch9
 214'
 215
 216# check_patch <patch>: Verify that <patch> looks like a half-sane
 217# patch email to avoid a false positive with !grep
 218check_patch () {
 219        grep -e "^From:" "$1" &&
 220        grep -e "^Date:" "$1" &&
 221        grep -e "^Subject:" "$1"
 222}
 223
 224test_expect_success '--no-to overrides config.to' '
 225
 226        git config --replace-all format.to \
 227                "R E Cipient <rcipient@example.com>" &&
 228        git format-patch --no-to --stdout master..side |
 229        sed -e "/^\$/q" >patch10 &&
 230        check_patch patch10 &&
 231        ! grep "^To: R E Cipient <rcipient@example.com>\$" patch10
 232'
 233
 234test_expect_success '--no-to and --to replaces config.to' '
 235
 236        git config --replace-all format.to \
 237                "Someone <someone@out.there>" &&
 238        git format-patch --no-to --to="Someone Else <else@out.there>" \
 239                --stdout master..side |
 240        sed -e "/^\$/q" >patch11 &&
 241        check_patch patch11 &&
 242        ! grep "^To: Someone <someone@out.there>\$" patch11 &&
 243        grep "^To: Someone Else <else@out.there>\$" patch11
 244'
 245
 246test_expect_success '--no-cc overrides config.cc' '
 247
 248        git config --replace-all format.cc \
 249                "C E Cipient <rcipient@example.com>" &&
 250        git format-patch --no-cc --stdout master..side |
 251        sed -e "/^\$/q" >patch12 &&
 252        check_patch patch12 &&
 253        ! grep "^Cc: C E Cipient <rcipient@example.com>\$" patch12
 254'
 255
 256test_expect_success '--no-add-header overrides config.headers' '
 257
 258        git config --replace-all format.headers \
 259                "Header1: B E Cipient <rcipient@example.com>" &&
 260        git format-patch --no-add-header --stdout master..side |
 261        sed -e "/^\$/q" >patch13 &&
 262        check_patch patch13 &&
 263        ! grep "^Header1: B E Cipient <rcipient@example.com>\$" patch13
 264'
 265
 266test_expect_success 'multiple files' '
 267
 268        rm -rf patches/ &&
 269        git checkout side &&
 270        git format-patch -o patches/ master &&
 271        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
 272'
 273
 274check_threading () {
 275        expect="$1" &&
 276        shift &&
 277        (git format-patch --stdout "$@"; echo $? > status.out) |
 278        # Prints everything between the Message-ID and In-Reply-To,
 279        # and replaces all Message-ID-lookalikes by a sequence number
 280        "$PERL_PATH" -ne '
 281                if (/^(message-id|references|in-reply-to)/i) {
 282                        $printing = 1;
 283                } elsif (/^\S/) {
 284                        $printing = 0;
 285                }
 286                if ($printing) {
 287                        $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
 288                        for $k (keys %h) {s/$k/$h{$k}/};
 289                        print;
 290                }
 291                print "---\n" if /^From /i;
 292        ' > actual &&
 293        test 0 = "$(cat status.out)" &&
 294        test_cmp "$expect" actual
 295}
 296
 297cat >> expect.no-threading <<EOF
 298---
 299---
 300---
 301EOF
 302
 303test_expect_success 'no threading' '
 304        git checkout side &&
 305        check_threading expect.no-threading master
 306'
 307
 308cat > expect.thread <<EOF
 309---
 310Message-Id: <0>
 311---
 312Message-Id: <1>
 313In-Reply-To: <0>
 314References: <0>
 315---
 316Message-Id: <2>
 317In-Reply-To: <0>
 318References: <0>
 319EOF
 320
 321test_expect_success 'thread' '
 322        check_threading expect.thread --thread master
 323'
 324
 325cat > expect.in-reply-to <<EOF
 326---
 327Message-Id: <0>
 328In-Reply-To: <1>
 329References: <1>
 330---
 331Message-Id: <2>
 332In-Reply-To: <1>
 333References: <1>
 334---
 335Message-Id: <3>
 336In-Reply-To: <1>
 337References: <1>
 338EOF
 339
 340test_expect_success 'thread in-reply-to' '
 341        check_threading expect.in-reply-to --in-reply-to="<test.message>" \
 342                --thread master
 343'
 344
 345cat > expect.cover-letter <<EOF
 346---
 347Message-Id: <0>
 348---
 349Message-Id: <1>
 350In-Reply-To: <0>
 351References: <0>
 352---
 353Message-Id: <2>
 354In-Reply-To: <0>
 355References: <0>
 356---
 357Message-Id: <3>
 358In-Reply-To: <0>
 359References: <0>
 360EOF
 361
 362test_expect_success 'thread cover-letter' '
 363        check_threading expect.cover-letter --cover-letter --thread master
 364'
 365
 366cat > expect.cl-irt <<EOF
 367---
 368Message-Id: <0>
 369In-Reply-To: <1>
 370References: <1>
 371---
 372Message-Id: <2>
 373In-Reply-To: <0>
 374References: <1>
 375        <0>
 376---
 377Message-Id: <3>
 378In-Reply-To: <0>
 379References: <1>
 380        <0>
 381---
 382Message-Id: <4>
 383In-Reply-To: <0>
 384References: <1>
 385        <0>
 386EOF
 387
 388test_expect_success 'thread cover-letter in-reply-to' '
 389        check_threading expect.cl-irt --cover-letter \
 390                --in-reply-to="<test.message>" --thread master
 391'
 392
 393test_expect_success 'thread explicit shallow' '
 394        check_threading expect.cl-irt --cover-letter \
 395                --in-reply-to="<test.message>" --thread=shallow master
 396'
 397
 398cat > expect.deep <<EOF
 399---
 400Message-Id: <0>
 401---
 402Message-Id: <1>
 403In-Reply-To: <0>
 404References: <0>
 405---
 406Message-Id: <2>
 407In-Reply-To: <1>
 408References: <0>
 409        <1>
 410EOF
 411
 412test_expect_success 'thread deep' '
 413        check_threading expect.deep --thread=deep master
 414'
 415
 416cat > expect.deep-irt <<EOF
 417---
 418Message-Id: <0>
 419In-Reply-To: <1>
 420References: <1>
 421---
 422Message-Id: <2>
 423In-Reply-To: <0>
 424References: <1>
 425        <0>
 426---
 427Message-Id: <3>
 428In-Reply-To: <2>
 429References: <1>
 430        <0>
 431        <2>
 432EOF
 433
 434test_expect_success 'thread deep in-reply-to' '
 435        check_threading expect.deep-irt  --thread=deep \
 436                --in-reply-to="<test.message>" master
 437'
 438
 439cat > expect.deep-cl <<EOF
 440---
 441Message-Id: <0>
 442---
 443Message-Id: <1>
 444In-Reply-To: <0>
 445References: <0>
 446---
 447Message-Id: <2>
 448In-Reply-To: <1>
 449References: <0>
 450        <1>
 451---
 452Message-Id: <3>
 453In-Reply-To: <2>
 454References: <0>
 455        <1>
 456        <2>
 457EOF
 458
 459test_expect_success 'thread deep cover-letter' '
 460        check_threading expect.deep-cl --cover-letter --thread=deep master
 461'
 462
 463cat > expect.deep-cl-irt <<EOF
 464---
 465Message-Id: <0>
 466In-Reply-To: <1>
 467References: <1>
 468---
 469Message-Id: <2>
 470In-Reply-To: <0>
 471References: <1>
 472        <0>
 473---
 474Message-Id: <3>
 475In-Reply-To: <2>
 476References: <1>
 477        <0>
 478        <2>
 479---
 480Message-Id: <4>
 481In-Reply-To: <3>
 482References: <1>
 483        <0>
 484        <2>
 485        <3>
 486EOF
 487
 488test_expect_success 'thread deep cover-letter in-reply-to' '
 489        check_threading expect.deep-cl-irt --cover-letter \
 490                --in-reply-to="<test.message>" --thread=deep master
 491'
 492
 493test_expect_success 'thread via config' '
 494        test_config format.thread true &&
 495        check_threading expect.thread master
 496'
 497
 498test_expect_success 'thread deep via config' '
 499        test_config format.thread deep &&
 500        check_threading expect.deep master
 501'
 502
 503test_expect_success 'thread config + override' '
 504        test_config format.thread deep &&
 505        check_threading expect.thread --thread master
 506'
 507
 508test_expect_success 'thread config + --no-thread' '
 509        test_config format.thread deep &&
 510        check_threading expect.no-threading --no-thread master
 511'
 512
 513test_expect_success 'excessive subject' '
 514
 515        rm -rf patches/ &&
 516        git checkout side &&
 517        for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
 518        git update-index file &&
 519        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." &&
 520        git format-patch -o patches/ master..side &&
 521        ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
 522'
 523
 524test_expect_success 'cover-letter inherits diff options' '
 525
 526        git mv file foo &&
 527        git commit -m foo &&
 528        git format-patch --cover-letter -1 &&
 529        check_patch 0000-cover-letter.patch &&
 530        ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
 531        git format-patch --cover-letter -1 -M &&
 532        grep "file => foo .* 0 *\$" 0000-cover-letter.patch
 533
 534'
 535
 536cat > expect << EOF
 537  This is an excessively long subject line for a message due to the
 538    habit some projects have of not having a short, one-line subject at
 539    the start of the commit message, but rather sticking a whole
 540    paragraph right at the start as the only thing in the commit
 541    message. It had better not become the filename for the patch.
 542  foo
 543
 544EOF
 545
 546test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
 547
 548        git format-patch --cover-letter -2 &&
 549        sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
 550        test_cmp expect output
 551
 552'
 553
 554cat > expect << EOF
 555index 40f36c6..2dc5c23 100644
 556--- a/file
 557+++ b/file
 558@@ -13,4 +13,20 @@ C
 559 10
 560 D
 561 E
 562 F
 563+5
 564EOF
 565
 566test_expect_success 'format-patch respects -U' '
 567
 568        git format-patch -U4 -2 &&
 569        sed -e "1,/^diff/d" -e "/^+5/q" \
 570                <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
 571                >output &&
 572        test_cmp expect output
 573
 574'
 575
 576cat > expect << EOF
 577
 578diff --git a/file b/file
 579index 40f36c6..2dc5c23 100644
 580--- a/file
 581+++ b/file
 582@@ -14,3 +14,19 @@ C
 583 D
 584 E
 585 F
 586+5
 587EOF
 588
 589test_expect_success 'format-patch -p suppresses stat' '
 590
 591        git format-patch -p -2 &&
 592        sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
 593        test_cmp expect output
 594
 595'
 596
 597test_expect_success 'format-patch from a subdirectory (1)' '
 598        filename=$(
 599                rm -rf sub &&
 600                mkdir -p sub/dir &&
 601                cd sub/dir &&
 602                git format-patch -1
 603        ) &&
 604        case "$filename" in
 605        0*)
 606                ;; # ok
 607        *)
 608                echo "Oops? $filename"
 609                false
 610                ;;
 611        esac &&
 612        test -f "$filename"
 613'
 614
 615test_expect_success 'format-patch from a subdirectory (2)' '
 616        filename=$(
 617                rm -rf sub &&
 618                mkdir -p sub/dir &&
 619                cd sub/dir &&
 620                git format-patch -1 -o ..
 621        ) &&
 622        case "$filename" in
 623        ../0*)
 624                ;; # ok
 625        *)
 626                echo "Oops? $filename"
 627                false
 628                ;;
 629        esac &&
 630        basename=$(expr "$filename" : ".*/\(.*\)") &&
 631        test -f "sub/$basename"
 632'
 633
 634test_expect_success 'format-patch from a subdirectory (3)' '
 635        rm -f 0* &&
 636        filename=$(
 637                rm -rf sub &&
 638                mkdir -p sub/dir &&
 639                cd sub/dir &&
 640                git format-patch -1 -o "$TRASH_DIRECTORY"
 641        ) &&
 642        basename=$(expr "$filename" : ".*/\(.*\)") &&
 643        test -f "$basename"
 644'
 645
 646test_expect_success 'format-patch --in-reply-to' '
 647        git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
 648        grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
 649        grep "^References: <baz@foo.bar>" patch8
 650'
 651
 652test_expect_success 'format-patch --signoff' '
 653        git format-patch -1 --signoff --stdout |
 654        grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
 655'
 656
 657echo "fatal: --name-only does not make sense" > expect.name-only
 658echo "fatal: --name-status does not make sense" > expect.name-status
 659echo "fatal: --check does not make sense" > expect.check
 660
 661test_expect_success 'options no longer allowed for format-patch' '
 662        test_must_fail git format-patch --name-only 2> output &&
 663        test_i18ncmp expect.name-only output &&
 664        test_must_fail git format-patch --name-status 2> output &&
 665        test_i18ncmp expect.name-status output &&
 666        test_must_fail git format-patch --check 2> output &&
 667        test_i18ncmp expect.check output'
 668
 669test_expect_success 'format-patch --numstat should produce a patch' '
 670        git format-patch --numstat --stdout master..side > output &&
 671        test 6 = $(grep "^diff --git a/" output | wc -l)'
 672
 673test_expect_success 'format-patch -- <path>' '
 674        git format-patch master..side -- file 2>error &&
 675        ! grep "Use .--" error
 676'
 677
 678test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
 679        git format-patch --ignore-if-in-upstream HEAD
 680'
 681
 682test_expect_success 'format-patch --signature' '
 683        git format-patch --stdout --signature="my sig" -1 >output &&
 684        grep "my sig" output
 685'
 686
 687test_expect_success 'format-patch with format.signature config' '
 688        git config format.signature "config sig" &&
 689        git format-patch --stdout -1 >output &&
 690        grep "config sig" output
 691'
 692
 693test_expect_success 'format-patch --signature overrides format.signature' '
 694        git config format.signature "config sig" &&
 695        git format-patch --stdout --signature="overrides" -1 >output &&
 696        ! grep "config sig" output &&
 697        grep "overrides" output
 698'
 699
 700test_expect_success 'format-patch --no-signature ignores format.signature' '
 701        git config format.signature "config sig" &&
 702        git format-patch --stdout --signature="my sig" --no-signature \
 703                -1 >output &&
 704        check_patch output &&
 705        ! grep "config sig" output &&
 706        ! grep "my sig" output &&
 707        ! grep "^-- \$" output
 708'
 709
 710test_expect_success 'format-patch --signature --cover-letter' '
 711        git config --unset-all format.signature &&
 712        git format-patch --stdout --signature="my sig" --cover-letter \
 713                -1 >output &&
 714        grep "my sig" output &&
 715        test 2 = $(grep "my sig" output | wc -l)
 716'
 717
 718test_expect_success 'format.signature="" supresses signatures' '
 719        git config format.signature "" &&
 720        git format-patch --stdout -1 >output &&
 721        check_patch output &&
 722        ! grep "^-- \$" output
 723'
 724
 725test_expect_success 'format-patch --no-signature supresses signatures' '
 726        git config --unset-all format.signature &&
 727        git format-patch --stdout --no-signature -1 >output &&
 728        check_patch output &&
 729        ! grep "^-- \$" output
 730'
 731
 732test_expect_success 'format-patch --signature="" supresses signatures' '
 733        git format-patch --stdout --signature="" -1 >output &&
 734        check_patch output &&
 735        ! grep "^-- \$" output
 736'
 737
 738test_expect_success TTY 'format-patch --stdout paginates' '
 739        rm -f pager_used &&
 740        (
 741                GIT_PAGER="wc >pager_used" &&
 742                export GIT_PAGER &&
 743                test_terminal git format-patch --stdout --all
 744        ) &&
 745        test_path_is_file pager_used
 746'
 747
 748 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
 749        rm -f pager_used &&
 750        (
 751                GIT_PAGER="wc >pager_used" &&
 752                export GIT_PAGER &&
 753                test_terminal git --no-pager format-patch --stdout --all &&
 754                test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
 755        ) &&
 756        test_path_is_missing pager_used &&
 757        test_path_is_missing .git/pager_used
 758'
 759
 760test_expect_success 'format-patch handles multi-line subjects' '
 761        rm -rf patches/ &&
 762        echo content >>file &&
 763        for i in one two three; do echo $i; done >msg &&
 764        git add file &&
 765        git commit -F msg &&
 766        git format-patch -o patches -1 &&
 767        grep ^Subject: patches/0001-one.patch >actual &&
 768        echo "Subject: [PATCH] one two three" >expect &&
 769        test_cmp expect actual
 770'
 771
 772test_expect_success 'format-patch handles multi-line encoded subjects' '
 773        rm -rf patches/ &&
 774        echo content >>file &&
 775        for i in en två tre; do echo $i; done >msg &&
 776        git add file &&
 777        git commit -F msg &&
 778        git format-patch -o patches -1 &&
 779        grep ^Subject: patches/0001-en.patch >actual &&
 780        echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
 781        test_cmp expect actual
 782'
 783
 784M8="foo bar "
 785M64=$M8$M8$M8$M8$M8$M8$M8$M8
 786M512=$M64$M64$M64$M64$M64$M64$M64$M64
 787cat >expect <<'EOF'
 788Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 789 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 790 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 791 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 792 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 793 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 794 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 795EOF
 796test_expect_success 'format-patch wraps extremely long subject (ascii)' '
 797        echo content >>file &&
 798        git add file &&
 799        git commit -m "$M512" &&
 800        git format-patch --stdout -1 >patch &&
 801        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 802        test_cmp expect subject
 803'
 804
 805M8="föö bar "
 806M64=$M8$M8$M8$M8$M8$M8$M8$M8
 807M512=$M64$M64$M64$M64$M64$M64$M64$M64
 808cat >expect <<'EOF'
 809Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 810 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 811 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 812 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 813 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3?=
 814 =?UTF-8?q?=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 815 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3?=
 816 =?UTF-8?q?=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 817 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 818 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 819 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 820 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3?=
 821 =?UTF-8?q?=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 822 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3?=
 823 =?UTF-8?q?=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 824 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 825 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 826 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 827 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3?=
 828 =?UTF-8?q?=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 829 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3?=
 830 =?UTF-8?q?=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 831 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 832EOF
 833test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
 834        rm -rf patches/ &&
 835        echo content >>file &&
 836        git add file &&
 837        git commit -m "$M512" &&
 838        git format-patch --stdout -1 >patch &&
 839        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 840        test_cmp expect subject
 841'
 842
 843check_author() {
 844        echo content >>file &&
 845        git add file &&
 846        GIT_AUTHOR_NAME=$1 git commit -m author-check &&
 847        git format-patch --stdout -1 >patch &&
 848        sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
 849        test_cmp expect actual
 850}
 851
 852cat >expect <<'EOF'
 853From: "Foo B. Bar" <author@example.com>
 854EOF
 855test_expect_success 'format-patch quotes dot in from-headers' '
 856        check_author "Foo B. Bar"
 857'
 858
 859cat >expect <<'EOF'
 860From: "Foo \"The Baz\" Bar" <author@example.com>
 861EOF
 862test_expect_success 'format-patch quotes double-quote in from-headers' '
 863        check_author "Foo \"The Baz\" Bar"
 864'
 865
 866cat >expect <<'EOF'
 867From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
 868EOF
 869test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
 870        check_author "Föo Bar"
 871'
 872
 873cat >expect <<'EOF'
 874From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
 875EOF
 876test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
 877        check_author "Föo B. Bar"
 878'
 879
 880cat >expect <<EOF
 881From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
 882 <author@example.com>
 883EOF
 884test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
 885        check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
 886'
 887
 888cat >expect <<'EOF'
 889From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
 890 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
 891 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
 892EOF
 893test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
 894        check_author "Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
 895'
 896
 897cat >expect <<'EOF'
 898From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
 899 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
 900 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
 901EOF
 902test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
 903        check_author "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
 904'
 905
 906cat >expect <<'EOF'
 907From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
 908 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
 909 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
 910 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
 911 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
 912EOF
 913test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
 914        check_author "Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
 915'
 916
 917cat >expect <<'EOF'
 918Subject: header with . in it
 919EOF
 920test_expect_success 'subject lines do not have 822 atom-quoting' '
 921        echo content >>file &&
 922        git add file &&
 923        git commit -m "header with . in it" &&
 924        git format-patch -k -1 --stdout >patch &&
 925        grep ^Subject: patch >actual &&
 926        test_cmp expect actual
 927'
 928
 929cat >expect <<'EOF'
 930Subject: [PREFIX 1/1] header with . in it
 931EOF
 932test_expect_success 'subject prefixes have space prepended' '
 933        git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
 934        grep ^Subject: patch >actual &&
 935        test_cmp expect actual
 936'
 937
 938cat >expect <<'EOF'
 939Subject: [1/1] header with . in it
 940EOF
 941test_expect_success 'empty subject prefix does not have extra space' '
 942        git format-patch -n -1 --stdout --subject-prefix= >patch &&
 943        grep ^Subject: patch >actual &&
 944        test_cmp expect actual
 945'
 946
 947test_expect_success 'format patch ignores color.ui' '
 948        test_unconfig color.ui &&
 949        git format-patch --stdout -1 >expect &&
 950        test_config color.ui always &&
 951        git format-patch --stdout -1 >actual &&
 952        test_cmp expect actual
 953'
 954
 955test_done