t / t4014-format-patch.shon commit Merge branch 'jc/merge-blobs' into maint (686b895)
   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 >out &&
 654        grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
 655'
 656
 657test_expect_success 'format-patch --notes --signoff' '
 658        git notes --ref test add -m "test message" HEAD &&
 659        git format-patch -1 --signoff --stdout --notes=test >out &&
 660        # Three dashes must come after S-o-b
 661        ! sed "/^Signed-off-by: /q" out | grep "test message" &&
 662        sed "1,/^Signed-off-by: /d" out | grep "test message" &&
 663        # Notes message must come after three dashes
 664        ! sed "/^---$/q" out | grep "test message" &&
 665        sed "1,/^---$/d" out | grep "test message"
 666'
 667
 668echo "fatal: --name-only does not make sense" > expect.name-only
 669echo "fatal: --name-status does not make sense" > expect.name-status
 670echo "fatal: --check does not make sense" > expect.check
 671
 672test_expect_success 'options no longer allowed for format-patch' '
 673        test_must_fail git format-patch --name-only 2> output &&
 674        test_i18ncmp expect.name-only output &&
 675        test_must_fail git format-patch --name-status 2> output &&
 676        test_i18ncmp expect.name-status output &&
 677        test_must_fail git format-patch --check 2> output &&
 678        test_i18ncmp expect.check output'
 679
 680test_expect_success 'format-patch --numstat should produce a patch' '
 681        git format-patch --numstat --stdout master..side > output &&
 682        test 6 = $(grep "^diff --git a/" output | wc -l)'
 683
 684test_expect_success 'format-patch -- <path>' '
 685        git format-patch master..side -- file 2>error &&
 686        ! grep "Use .--" error
 687'
 688
 689test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
 690        git format-patch --ignore-if-in-upstream HEAD
 691'
 692
 693test_expect_success 'format-patch --signature' '
 694        git format-patch --stdout --signature="my sig" -1 >output &&
 695        grep "my sig" output
 696'
 697
 698test_expect_success 'format-patch with format.signature config' '
 699        git config format.signature "config sig" &&
 700        git format-patch --stdout -1 >output &&
 701        grep "config sig" output
 702'
 703
 704test_expect_success 'format-patch --signature overrides format.signature' '
 705        git config format.signature "config sig" &&
 706        git format-patch --stdout --signature="overrides" -1 >output &&
 707        ! grep "config sig" output &&
 708        grep "overrides" output
 709'
 710
 711test_expect_success 'format-patch --no-signature ignores format.signature' '
 712        git config format.signature "config sig" &&
 713        git format-patch --stdout --signature="my sig" --no-signature \
 714                -1 >output &&
 715        check_patch output &&
 716        ! grep "config sig" output &&
 717        ! grep "my sig" output &&
 718        ! grep "^-- \$" output
 719'
 720
 721test_expect_success 'format-patch --signature --cover-letter' '
 722        git config --unset-all format.signature &&
 723        git format-patch --stdout --signature="my sig" --cover-letter \
 724                -1 >output &&
 725        grep "my sig" output &&
 726        test 2 = $(grep "my sig" output | wc -l)
 727'
 728
 729test_expect_success 'format.signature="" supresses signatures' '
 730        git config format.signature "" &&
 731        git format-patch --stdout -1 >output &&
 732        check_patch output &&
 733        ! grep "^-- \$" output
 734'
 735
 736test_expect_success 'format-patch --no-signature supresses signatures' '
 737        git config --unset-all format.signature &&
 738        git format-patch --stdout --no-signature -1 >output &&
 739        check_patch output &&
 740        ! grep "^-- \$" output
 741'
 742
 743test_expect_success 'format-patch --signature="" supresses signatures' '
 744        git format-patch --stdout --signature="" -1 >output &&
 745        check_patch output &&
 746        ! grep "^-- \$" output
 747'
 748
 749test_expect_success TTY 'format-patch --stdout paginates' '
 750        rm -f pager_used &&
 751        (
 752                GIT_PAGER="wc >pager_used" &&
 753                export GIT_PAGER &&
 754                test_terminal git format-patch --stdout --all
 755        ) &&
 756        test_path_is_file pager_used
 757'
 758
 759 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
 760        rm -f pager_used &&
 761        (
 762                GIT_PAGER="wc >pager_used" &&
 763                export GIT_PAGER &&
 764                test_terminal git --no-pager format-patch --stdout --all &&
 765                test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
 766        ) &&
 767        test_path_is_missing pager_used &&
 768        test_path_is_missing .git/pager_used
 769'
 770
 771test_expect_success 'format-patch handles multi-line subjects' '
 772        rm -rf patches/ &&
 773        echo content >>file &&
 774        for i in one two three; do echo $i; done >msg &&
 775        git add file &&
 776        git commit -F msg &&
 777        git format-patch -o patches -1 &&
 778        grep ^Subject: patches/0001-one.patch >actual &&
 779        echo "Subject: [PATCH] one two three" >expect &&
 780        test_cmp expect actual
 781'
 782
 783test_expect_success 'format-patch handles multi-line encoded subjects' '
 784        rm -rf patches/ &&
 785        echo content >>file &&
 786        for i in en två tre; do echo $i; done >msg &&
 787        git add file &&
 788        git commit -F msg &&
 789        git format-patch -o patches -1 &&
 790        grep ^Subject: patches/0001-en.patch >actual &&
 791        echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
 792        test_cmp expect actual
 793'
 794
 795M8="foo bar "
 796M64=$M8$M8$M8$M8$M8$M8$M8$M8
 797M512=$M64$M64$M64$M64$M64$M64$M64$M64
 798cat >expect <<'EOF'
 799Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 800 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 801 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 802 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 803 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 804 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 805 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 806EOF
 807test_expect_success 'format-patch wraps extremely long subject (ascii)' '
 808        echo content >>file &&
 809        git add file &&
 810        git commit -m "$M512" &&
 811        git format-patch --stdout -1 >patch &&
 812        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 813        test_cmp expect subject
 814'
 815
 816M8="föö bar "
 817M64=$M8$M8$M8$M8$M8$M8$M8$M8
 818M512=$M64$M64$M64$M64$M64$M64$M64$M64
 819cat >expect <<'EOF'
 820Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 821 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 822 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 823 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 824 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3?=
 825 =?UTF-8?q?=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 826 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3?=
 827 =?UTF-8?q?=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 828 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 829 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 830 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 831 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3?=
 832 =?UTF-8?q?=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 833 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3?=
 834 =?UTF-8?q?=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 835 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 836 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 837 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 838 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3?=
 839 =?UTF-8?q?=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 840 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3?=
 841 =?UTF-8?q?=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 842 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 843EOF
 844test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
 845        rm -rf patches/ &&
 846        echo content >>file &&
 847        git add file &&
 848        git commit -m "$M512" &&
 849        git format-patch --stdout -1 >patch &&
 850        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 851        test_cmp expect subject
 852'
 853
 854check_author() {
 855        echo content >>file &&
 856        git add file &&
 857        GIT_AUTHOR_NAME=$1 git commit -m author-check &&
 858        git format-patch --stdout -1 >patch &&
 859        sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
 860        test_cmp expect actual
 861}
 862
 863cat >expect <<'EOF'
 864From: "Foo B. Bar" <author@example.com>
 865EOF
 866test_expect_success 'format-patch quotes dot in from-headers' '
 867        check_author "Foo B. Bar"
 868'
 869
 870cat >expect <<'EOF'
 871From: "Foo \"The Baz\" Bar" <author@example.com>
 872EOF
 873test_expect_success 'format-patch quotes double-quote in from-headers' '
 874        check_author "Foo \"The Baz\" Bar"
 875'
 876
 877cat >expect <<'EOF'
 878From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
 879EOF
 880test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
 881        check_author "Föo Bar"
 882'
 883
 884cat >expect <<'EOF'
 885From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
 886EOF
 887test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
 888        check_author "Föo B. Bar"
 889'
 890
 891cat >expect <<EOF
 892From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
 893 <author@example.com>
 894EOF
 895test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
 896        check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
 897'
 898
 899cat >expect <<'EOF'
 900From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
 901 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
 902 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
 903EOF
 904test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
 905        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"
 906'
 907
 908cat >expect <<'EOF'
 909From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
 910 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
 911 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
 912EOF
 913test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
 914        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"
 915'
 916
 917cat >expect <<'EOF'
 918From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
 919 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
 920 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
 921 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
 922 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
 923EOF
 924test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
 925        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"
 926'
 927
 928cat >expect <<'EOF'
 929Subject: header with . in it
 930EOF
 931test_expect_success 'subject lines do not have 822 atom-quoting' '
 932        echo content >>file &&
 933        git add file &&
 934        git commit -m "header with . in it" &&
 935        git format-patch -k -1 --stdout >patch &&
 936        grep ^Subject: patch >actual &&
 937        test_cmp expect actual
 938'
 939
 940cat >expect <<'EOF'
 941Subject: [PREFIX 1/1] header with . in it
 942EOF
 943test_expect_success 'subject prefixes have space prepended' '
 944        git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
 945        grep ^Subject: patch >actual &&
 946        test_cmp expect actual
 947'
 948
 949cat >expect <<'EOF'
 950Subject: [1/1] header with . in it
 951EOF
 952test_expect_success 'empty subject prefix does not have extra space' '
 953        git format-patch -n -1 --stdout --subject-prefix= >patch &&
 954        grep ^Subject: patch >actual &&
 955        test_cmp expect actual
 956'
 957
 958test_expect_success 'format patch ignores color.ui' '
 959        test_unconfig color.ui &&
 960        git format-patch --stdout -1 >expect &&
 961        test_config color.ui always &&
 962        git format-patch --stdout -1 >actual &&
 963        test_cmp expect actual
 964'
 965
 966test_done