t / t4014-format-patch.shon commit Merge branch 'jk/gpg-interface-cleanup' (ed0f7bd)
   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 --ignore-if-in-upstream handles tags" '
  61        git tag -a v1 -m tag side &&
  62        git tag -a v2 -m tag master &&
  63        git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
  64        cnt=$(grep "^From " patch1 | wc -l) &&
  65        test $cnt = 2
  66'
  67
  68test_expect_success "format-patch doesn't consider merge commits" '
  69
  70        git checkout -b slave master &&
  71        echo "Another line" >>file &&
  72        test_tick &&
  73        git commit -am "Slave change #1" &&
  74        echo "Yet another line" >>file &&
  75        test_tick &&
  76        git commit -am "Slave change #2" &&
  77        git checkout -b merger master &&
  78        test_tick &&
  79        git merge --no-ff slave &&
  80        cnt=$(git format-patch -3 --stdout | grep "^From " | wc -l) &&
  81        test $cnt = 3
  82'
  83
  84test_expect_success "format-patch result applies" '
  85
  86        git checkout -b rebuild-0 master &&
  87        git am -3 patch0 &&
  88        cnt=$(git rev-list master.. | wc -l) &&
  89        test $cnt = 2
  90'
  91
  92test_expect_success "format-patch --ignore-if-in-upstream result applies" '
  93
  94        git checkout -b rebuild-1 master &&
  95        git am -3 patch1 &&
  96        cnt=$(git rev-list master.. | wc -l) &&
  97        test $cnt = 2
  98'
  99
 100test_expect_success 'commit did not screw up the log message' '
 101
 102        git cat-file commit side | grep "^Side .* with .* backslash-n"
 103
 104'
 105
 106test_expect_success 'format-patch did not screw up the log message' '
 107
 108        grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
 109        grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
 110
 111'
 112
 113test_expect_success 'replay did not screw up the log message' '
 114
 115        git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
 116
 117'
 118
 119test_expect_success 'extra headers' '
 120
 121        git config format.headers "To: R E Cipient <rcipient@example.com>
 122" &&
 123        git config --add format.headers "Cc: S E Cipient <scipient@example.com>
 124" &&
 125        git format-patch --stdout master..side > patch2 &&
 126        sed -e "/^\$/q" patch2 > hdrs2 &&
 127        grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
 128        grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
 129
 130'
 131
 132test_expect_success 'extra headers without newlines' '
 133
 134        git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
 135        git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
 136        git format-patch --stdout master..side >patch3 &&
 137        sed -e "/^\$/q" patch3 > hdrs3 &&
 138        grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
 139        grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
 140
 141'
 142
 143test_expect_success 'extra headers with multiple To:s' '
 144
 145        git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
 146        git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
 147        git format-patch --stdout master..side > patch4 &&
 148        sed -e "/^\$/q" patch4 > hdrs4 &&
 149        grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
 150        grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
 151'
 152
 153test_expect_success 'additional command line cc (ascii)' '
 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_failure 'additional command line cc (rfc822)' '
 162
 163        git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
 164        git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
 165        grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
 166        grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" patch5
 167'
 168
 169test_expect_success 'command line headers' '
 170
 171        git config --unset-all format.headers &&
 172        git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
 173        grep "^Cc: R E Cipient <rcipient@example.com>\$" patch6
 174'
 175
 176test_expect_success 'configuration headers and command line headers' '
 177
 178        git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
 179        git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
 180        grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch7 &&
 181        grep "^ *S E Cipient <scipient@example.com>\$" patch7
 182'
 183
 184test_expect_success 'command line To: header (ascii)' '
 185
 186        git config --unset-all format.headers &&
 187        git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
 188        grep "^To: R E Cipient <rcipient@example.com>\$" patch8
 189'
 190
 191test_expect_failure 'command line To: header (rfc822)' '
 192
 193        git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
 194        grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch8
 195'
 196
 197test_expect_failure 'command line To: header (rfc2047)' '
 198
 199        git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
 200        grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch8
 201'
 202
 203test_expect_success 'configuration To: header (ascii)' '
 204
 205        git config format.to "R E Cipient <rcipient@example.com>" &&
 206        git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
 207        grep "^To: R E Cipient <rcipient@example.com>\$" patch9
 208'
 209
 210test_expect_failure 'configuration To: header (rfc822)' '
 211
 212        git config format.to "R. E. Cipient <rcipient@example.com>" &&
 213        git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
 214        grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch9
 215'
 216
 217test_expect_failure 'configuration To: header (rfc2047)' '
 218
 219        git config format.to "R Ä Cipient <rcipient@example.com>" &&
 220        git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
 221        grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch9
 222'
 223
 224# check_patch <patch>: Verify that <patch> looks like a half-sane
 225# patch email to avoid a false positive with !grep
 226check_patch () {
 227        grep -e "^From:" "$1" &&
 228        grep -e "^Date:" "$1" &&
 229        grep -e "^Subject:" "$1"
 230}
 231
 232test_expect_success '--no-to overrides config.to' '
 233
 234        git config --replace-all format.to \
 235                "R E Cipient <rcipient@example.com>" &&
 236        git format-patch --no-to --stdout master..side |
 237        sed -e "/^\$/q" >patch10 &&
 238        check_patch patch10 &&
 239        ! grep "^To: R E Cipient <rcipient@example.com>\$" patch10
 240'
 241
 242test_expect_success '--no-to and --to replaces config.to' '
 243
 244        git config --replace-all format.to \
 245                "Someone <someone@out.there>" &&
 246        git format-patch --no-to --to="Someone Else <else@out.there>" \
 247                --stdout master..side |
 248        sed -e "/^\$/q" >patch11 &&
 249        check_patch patch11 &&
 250        ! grep "^To: Someone <someone@out.there>\$" patch11 &&
 251        grep "^To: Someone Else <else@out.there>\$" patch11
 252'
 253
 254test_expect_success '--no-cc overrides config.cc' '
 255
 256        git config --replace-all format.cc \
 257                "C E Cipient <rcipient@example.com>" &&
 258        git format-patch --no-cc --stdout master..side |
 259        sed -e "/^\$/q" >patch12 &&
 260        check_patch patch12 &&
 261        ! grep "^Cc: C E Cipient <rcipient@example.com>\$" patch12
 262'
 263
 264test_expect_success '--no-add-header overrides config.headers' '
 265
 266        git config --replace-all format.headers \
 267                "Header1: B E Cipient <rcipient@example.com>" &&
 268        git format-patch --no-add-header --stdout master..side |
 269        sed -e "/^\$/q" >patch13 &&
 270        check_patch patch13 &&
 271        ! grep "^Header1: B E Cipient <rcipient@example.com>\$" patch13
 272'
 273
 274test_expect_success 'multiple files' '
 275
 276        rm -rf patches/ &&
 277        git checkout side &&
 278        git format-patch -o patches/ master &&
 279        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
 280'
 281
 282test_expect_success 'reroll count' '
 283        rm -fr patches &&
 284        git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
 285        ! grep -v "^patches/v4-000[0-3]-" list &&
 286        sed -n -e "/^Subject: /p" $(cat list) >subjects &&
 287        ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
 288'
 289
 290test_expect_success 'reroll count (-v)' '
 291        rm -fr patches &&
 292        git format-patch -o patches --cover-letter -v4 master..side >list &&
 293        ! grep -v "^patches/v4-000[0-3]-" list &&
 294        sed -n -e "/^Subject: /p" $(cat list) >subjects &&
 295        ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
 296'
 297
 298check_threading () {
 299        expect="$1" &&
 300        shift &&
 301        (git format-patch --stdout "$@"; echo $? > status.out) |
 302        # Prints everything between the Message-ID and In-Reply-To,
 303        # and replaces all Message-ID-lookalikes by a sequence number
 304        perl -ne '
 305                if (/^(message-id|references|in-reply-to)/i) {
 306                        $printing = 1;
 307                } elsif (/^\S/) {
 308                        $printing = 0;
 309                }
 310                if ($printing) {
 311                        $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
 312                        for $k (keys %h) {s/$k/$h{$k}/};
 313                        print;
 314                }
 315                print "---\n" if /^From /i;
 316        ' > actual &&
 317        test 0 = "$(cat status.out)" &&
 318        test_cmp "$expect" actual
 319}
 320
 321cat >> expect.no-threading <<EOF
 322---
 323---
 324---
 325EOF
 326
 327test_expect_success 'no threading' '
 328        git checkout side &&
 329        check_threading expect.no-threading master
 330'
 331
 332cat > expect.thread <<EOF
 333---
 334Message-Id: <0>
 335---
 336Message-Id: <1>
 337In-Reply-To: <0>
 338References: <0>
 339---
 340Message-Id: <2>
 341In-Reply-To: <0>
 342References: <0>
 343EOF
 344
 345test_expect_success 'thread' '
 346        check_threading expect.thread --thread master
 347'
 348
 349cat > expect.in-reply-to <<EOF
 350---
 351Message-Id: <0>
 352In-Reply-To: <1>
 353References: <1>
 354---
 355Message-Id: <2>
 356In-Reply-To: <1>
 357References: <1>
 358---
 359Message-Id: <3>
 360In-Reply-To: <1>
 361References: <1>
 362EOF
 363
 364test_expect_success 'thread in-reply-to' '
 365        check_threading expect.in-reply-to --in-reply-to="<test.message>" \
 366                --thread master
 367'
 368
 369cat > expect.cover-letter <<EOF
 370---
 371Message-Id: <0>
 372---
 373Message-Id: <1>
 374In-Reply-To: <0>
 375References: <0>
 376---
 377Message-Id: <2>
 378In-Reply-To: <0>
 379References: <0>
 380---
 381Message-Id: <3>
 382In-Reply-To: <0>
 383References: <0>
 384EOF
 385
 386test_expect_success 'thread cover-letter' '
 387        check_threading expect.cover-letter --cover-letter --thread master
 388'
 389
 390cat > expect.cl-irt <<EOF
 391---
 392Message-Id: <0>
 393In-Reply-To: <1>
 394References: <1>
 395---
 396Message-Id: <2>
 397In-Reply-To: <0>
 398References: <1>
 399        <0>
 400---
 401Message-Id: <3>
 402In-Reply-To: <0>
 403References: <1>
 404        <0>
 405---
 406Message-Id: <4>
 407In-Reply-To: <0>
 408References: <1>
 409        <0>
 410EOF
 411
 412test_expect_success 'thread cover-letter in-reply-to' '
 413        check_threading expect.cl-irt --cover-letter \
 414                --in-reply-to="<test.message>" --thread master
 415'
 416
 417test_expect_success 'thread explicit shallow' '
 418        check_threading expect.cl-irt --cover-letter \
 419                --in-reply-to="<test.message>" --thread=shallow master
 420'
 421
 422cat > expect.deep <<EOF
 423---
 424Message-Id: <0>
 425---
 426Message-Id: <1>
 427In-Reply-To: <0>
 428References: <0>
 429---
 430Message-Id: <2>
 431In-Reply-To: <1>
 432References: <0>
 433        <1>
 434EOF
 435
 436test_expect_success 'thread deep' '
 437        check_threading expect.deep --thread=deep master
 438'
 439
 440cat > expect.deep-irt <<EOF
 441---
 442Message-Id: <0>
 443In-Reply-To: <1>
 444References: <1>
 445---
 446Message-Id: <2>
 447In-Reply-To: <0>
 448References: <1>
 449        <0>
 450---
 451Message-Id: <3>
 452In-Reply-To: <2>
 453References: <1>
 454        <0>
 455        <2>
 456EOF
 457
 458test_expect_success 'thread deep in-reply-to' '
 459        check_threading expect.deep-irt  --thread=deep \
 460                --in-reply-to="<test.message>" master
 461'
 462
 463cat > expect.deep-cl <<EOF
 464---
 465Message-Id: <0>
 466---
 467Message-Id: <1>
 468In-Reply-To: <0>
 469References: <0>
 470---
 471Message-Id: <2>
 472In-Reply-To: <1>
 473References: <0>
 474        <1>
 475---
 476Message-Id: <3>
 477In-Reply-To: <2>
 478References: <0>
 479        <1>
 480        <2>
 481EOF
 482
 483test_expect_success 'thread deep cover-letter' '
 484        check_threading expect.deep-cl --cover-letter --thread=deep master
 485'
 486
 487cat > expect.deep-cl-irt <<EOF
 488---
 489Message-Id: <0>
 490In-Reply-To: <1>
 491References: <1>
 492---
 493Message-Id: <2>
 494In-Reply-To: <0>
 495References: <1>
 496        <0>
 497---
 498Message-Id: <3>
 499In-Reply-To: <2>
 500References: <1>
 501        <0>
 502        <2>
 503---
 504Message-Id: <4>
 505In-Reply-To: <3>
 506References: <1>
 507        <0>
 508        <2>
 509        <3>
 510EOF
 511
 512test_expect_success 'thread deep cover-letter in-reply-to' '
 513        check_threading expect.deep-cl-irt --cover-letter \
 514                --in-reply-to="<test.message>" --thread=deep master
 515'
 516
 517test_expect_success 'thread via config' '
 518        test_config format.thread true &&
 519        check_threading expect.thread master
 520'
 521
 522test_expect_success 'thread deep via config' '
 523        test_config format.thread deep &&
 524        check_threading expect.deep master
 525'
 526
 527test_expect_success 'thread config + override' '
 528        test_config format.thread deep &&
 529        check_threading expect.thread --thread master
 530'
 531
 532test_expect_success 'thread config + --no-thread' '
 533        test_config format.thread deep &&
 534        check_threading expect.no-threading --no-thread master
 535'
 536
 537test_expect_success 'excessive subject' '
 538
 539        rm -rf patches/ &&
 540        git checkout side &&
 541        for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
 542        git update-index file &&
 543        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." &&
 544        git format-patch -o patches/ master..side &&
 545        ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
 546'
 547
 548test_expect_success 'cover-letter inherits diff options' '
 549
 550        git mv file foo &&
 551        git commit -m foo &&
 552        git format-patch --no-renames --cover-letter -1 &&
 553        check_patch 0000-cover-letter.patch &&
 554        ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
 555        git format-patch --cover-letter -1 -M &&
 556        grep "file => foo .* 0 *\$" 0000-cover-letter.patch
 557
 558'
 559
 560cat > expect << EOF
 561  This is an excessively long subject line for a message due to the
 562    habit some projects have of not having a short, one-line subject at
 563    the start of the commit message, but rather sticking a whole
 564    paragraph right at the start as the only thing in the commit
 565    message. It had better not become the filename for the patch.
 566  foo
 567
 568EOF
 569
 570test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
 571
 572        git format-patch --cover-letter -2 &&
 573        sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
 574        test_cmp expect output
 575
 576'
 577
 578cat > expect << EOF
 579index 40f36c6..2dc5c23 100644
 580--- a/file
 581+++ b/file
 582@@ -13,4 +13,20 @@ C
 583 10
 584 D
 585 E
 586 F
 587+5
 588EOF
 589
 590test_expect_success 'format-patch respects -U' '
 591
 592        git format-patch -U4 -2 &&
 593        sed -e "1,/^diff/d" -e "/^+5/q" \
 594                <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
 595                >output &&
 596        test_cmp expect output
 597
 598'
 599
 600cat > expect << EOF
 601
 602diff --git a/file b/file
 603index 40f36c6..2dc5c23 100644
 604--- a/file
 605+++ b/file
 606@@ -14,3 +14,19 @@ C
 607 D
 608 E
 609 F
 610+5
 611EOF
 612
 613test_expect_success 'format-patch -p suppresses stat' '
 614
 615        git format-patch -p -2 &&
 616        sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
 617        test_cmp expect output
 618
 619'
 620
 621test_expect_success 'format-patch from a subdirectory (1)' '
 622        filename=$(
 623                rm -rf sub &&
 624                mkdir -p sub/dir &&
 625                cd sub/dir &&
 626                git format-patch -1
 627        ) &&
 628        case "$filename" in
 629        0*)
 630                ;; # ok
 631        *)
 632                echo "Oops? $filename"
 633                false
 634                ;;
 635        esac &&
 636        test -f "$filename"
 637'
 638
 639test_expect_success 'format-patch from a subdirectory (2)' '
 640        filename=$(
 641                rm -rf sub &&
 642                mkdir -p sub/dir &&
 643                cd sub/dir &&
 644                git format-patch -1 -o ..
 645        ) &&
 646        case "$filename" in
 647        ../0*)
 648                ;; # ok
 649        *)
 650                echo "Oops? $filename"
 651                false
 652                ;;
 653        esac &&
 654        basename=$(expr "$filename" : ".*/\(.*\)") &&
 655        test -f "sub/$basename"
 656'
 657
 658test_expect_success 'format-patch from a subdirectory (3)' '
 659        rm -f 0* &&
 660        filename=$(
 661                rm -rf sub &&
 662                mkdir -p sub/dir &&
 663                cd sub/dir &&
 664                git format-patch -1 -o "$TRASH_DIRECTORY"
 665        ) &&
 666        basename=$(expr "$filename" : ".*/\(.*\)") &&
 667        test -f "$basename"
 668'
 669
 670test_expect_success 'format-patch --in-reply-to' '
 671        git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
 672        grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
 673        grep "^References: <baz@foo.bar>" patch8
 674'
 675
 676test_expect_success 'format-patch --signoff' '
 677        git format-patch -1 --signoff --stdout >out &&
 678        grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
 679'
 680
 681test_expect_success 'format-patch --notes --signoff' '
 682        git notes --ref test add -m "test message" HEAD &&
 683        git format-patch -1 --signoff --stdout --notes=test >out &&
 684        # Three dashes must come after S-o-b
 685        ! sed "/^Signed-off-by: /q" out | grep "test message" &&
 686        sed "1,/^Signed-off-by: /d" out | grep "test message" &&
 687        # Notes message must come after three dashes
 688        ! sed "/^---$/q" out | grep "test message" &&
 689        sed "1,/^---$/d" out | grep "test message"
 690'
 691
 692echo "fatal: --name-only does not make sense" > expect.name-only
 693echo "fatal: --name-status does not make sense" > expect.name-status
 694echo "fatal: --check does not make sense" > expect.check
 695
 696test_expect_success 'options no longer allowed for format-patch' '
 697        test_must_fail git format-patch --name-only 2> output &&
 698        test_i18ncmp expect.name-only output &&
 699        test_must_fail git format-patch --name-status 2> output &&
 700        test_i18ncmp expect.name-status output &&
 701        test_must_fail git format-patch --check 2> output &&
 702        test_i18ncmp expect.check output'
 703
 704test_expect_success 'format-patch --numstat should produce a patch' '
 705        git format-patch --numstat --stdout master..side > output &&
 706        test 5 = $(grep "^diff --git a/" output | wc -l)'
 707
 708test_expect_success 'format-patch -- <path>' '
 709        git format-patch master..side -- file 2>error &&
 710        ! grep "Use .--" error
 711'
 712
 713test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
 714        git format-patch --ignore-if-in-upstream HEAD
 715'
 716
 717test_expect_success 'format-patch --signature' '
 718        git format-patch --stdout --signature="my sig" -1 >output &&
 719        grep "my sig" output
 720'
 721
 722test_expect_success 'format-patch with format.signature config' '
 723        git config format.signature "config sig" &&
 724        git format-patch --stdout -1 >output &&
 725        grep "config sig" output
 726'
 727
 728test_expect_success 'format-patch --signature overrides format.signature' '
 729        git config format.signature "config sig" &&
 730        git format-patch --stdout --signature="overrides" -1 >output &&
 731        ! grep "config sig" output &&
 732        grep "overrides" output
 733'
 734
 735test_expect_success 'format-patch --no-signature ignores format.signature' '
 736        git config format.signature "config sig" &&
 737        git format-patch --stdout --signature="my sig" --no-signature \
 738                -1 >output &&
 739        check_patch output &&
 740        ! grep "config sig" output &&
 741        ! grep "my sig" output &&
 742        ! grep "^-- \$" output
 743'
 744
 745test_expect_success 'format-patch --signature --cover-letter' '
 746        git config --unset-all format.signature &&
 747        git format-patch --stdout --signature="my sig" --cover-letter \
 748                -1 >output &&
 749        grep "my sig" output &&
 750        test 2 = $(grep "my sig" output | wc -l)
 751'
 752
 753test_expect_success 'format.signature="" suppresses signatures' '
 754        git config format.signature "" &&
 755        git format-patch --stdout -1 >output &&
 756        check_patch output &&
 757        ! grep "^-- \$" output
 758'
 759
 760test_expect_success 'format-patch --no-signature suppresses signatures' '
 761        git config --unset-all format.signature &&
 762        git format-patch --stdout --no-signature -1 >output &&
 763        check_patch output &&
 764        ! grep "^-- \$" output
 765'
 766
 767test_expect_success 'format-patch --signature="" suppresses signatures' '
 768        git format-patch --stdout --signature="" -1 >output &&
 769        check_patch output &&
 770        ! grep "^-- \$" output
 771'
 772
 773test_expect_success 'prepare mail-signature input' '
 774        cat >mail-signature <<-\EOF
 775
 776        Test User <test.email@kernel.org>
 777        http://git.kernel.org/cgit/git/git.git
 778
 779        git.kernel.org/?p=git/git.git;a=summary
 780
 781        EOF
 782'
 783
 784test_expect_success '--signature-file=file works' '
 785        git format-patch --stdout --signature-file=mail-signature -1 >output &&
 786        check_patch output &&
 787        sed -e "1,/^-- \$/d" <output >actual &&
 788        {
 789                cat mail-signature && echo
 790        } >expect &&
 791        test_cmp expect actual
 792'
 793
 794test_expect_success 'format.signaturefile works' '
 795        test_config format.signaturefile mail-signature &&
 796        git format-patch --stdout -1 >output &&
 797        check_patch output &&
 798        sed -e "1,/^-- \$/d" <output >actual &&
 799        {
 800                cat mail-signature && echo
 801        } >expect &&
 802        test_cmp expect actual
 803'
 804
 805test_expect_success '--no-signature suppresses format.signaturefile ' '
 806        test_config format.signaturefile mail-signature &&
 807        git format-patch --stdout --no-signature -1 >output &&
 808        check_patch output &&
 809        ! grep "^-- \$" output
 810'
 811
 812test_expect_success '--signature-file overrides format.signaturefile' '
 813        cat >other-mail-signature <<-\EOF &&
 814        Use this other signature instead of mail-signature.
 815        EOF
 816        test_config format.signaturefile mail-signature &&
 817        git format-patch --stdout \
 818                        --signature-file=other-mail-signature -1 >output &&
 819        check_patch output &&
 820        sed -e "1,/^-- \$/d" <output >actual &&
 821        {
 822                cat other-mail-signature && echo
 823        } >expect &&
 824        test_cmp expect actual
 825'
 826
 827test_expect_success '--signature overrides format.signaturefile' '
 828        test_config format.signaturefile mail-signature &&
 829        git format-patch --stdout --signature="my sig" -1 >output &&
 830        check_patch output &&
 831        grep "my sig" output
 832'
 833
 834test_expect_success TTY 'format-patch --stdout paginates' '
 835        rm -f pager_used &&
 836        test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
 837        test_path_is_file pager_used
 838'
 839
 840 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
 841        rm -f pager_used &&
 842        test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
 843        test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
 844        test_path_is_missing pager_used &&
 845        test_path_is_missing .git/pager_used
 846'
 847
 848test_expect_success 'format-patch handles multi-line subjects' '
 849        rm -rf patches/ &&
 850        echo content >>file &&
 851        for i in one two three; do echo $i; done >msg &&
 852        git add file &&
 853        git commit -F msg &&
 854        git format-patch -o patches -1 &&
 855        grep ^Subject: patches/0001-one.patch >actual &&
 856        echo "Subject: [PATCH] one two three" >expect &&
 857        test_cmp expect actual
 858'
 859
 860test_expect_success 'format-patch handles multi-line encoded subjects' '
 861        rm -rf patches/ &&
 862        echo content >>file &&
 863        for i in en två tre; do echo $i; done >msg &&
 864        git add file &&
 865        git commit -F msg &&
 866        git format-patch -o patches -1 &&
 867        grep ^Subject: patches/0001-en.patch >actual &&
 868        echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
 869        test_cmp expect actual
 870'
 871
 872M8="foo bar "
 873M64=$M8$M8$M8$M8$M8$M8$M8$M8
 874M512=$M64$M64$M64$M64$M64$M64$M64$M64
 875cat >expect <<'EOF'
 876Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 877 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 878 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 879 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 880 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 881 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 882 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 883EOF
 884test_expect_success 'format-patch wraps extremely long subject (ascii)' '
 885        echo content >>file &&
 886        git add file &&
 887        git commit -m "$M512" &&
 888        git format-patch --stdout -1 >patch &&
 889        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 890        test_cmp expect subject
 891'
 892
 893M8="föö bar "
 894M64=$M8$M8$M8$M8$M8$M8$M8$M8
 895M512=$M64$M64$M64$M64$M64$M64$M64$M64
 896cat >expect <<'EOF'
 897Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 898 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 899 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 900 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 901 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 902 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 903 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 904 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 905 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 906 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 907 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 908 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 909 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 910 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 911 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 912 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 913 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 914 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 915 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 916 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 917 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 918 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 919 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 920 =?UTF-8?q?bar?=
 921EOF
 922test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
 923        rm -rf patches/ &&
 924        echo content >>file &&
 925        git add file &&
 926        git commit -m "$M512" &&
 927        git format-patch --stdout -1 >patch &&
 928        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 929        test_cmp expect subject
 930'
 931
 932check_author() {
 933        echo content >>file &&
 934        git add file &&
 935        GIT_AUTHOR_NAME=$1 git commit -m author-check &&
 936        git format-patch --stdout -1 >patch &&
 937        sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
 938        test_cmp expect actual
 939}
 940
 941cat >expect <<'EOF'
 942From: "Foo B. Bar" <author@example.com>
 943EOF
 944test_expect_success 'format-patch quotes dot in from-headers' '
 945        check_author "Foo B. Bar"
 946'
 947
 948cat >expect <<'EOF'
 949From: "Foo \"The Baz\" Bar" <author@example.com>
 950EOF
 951test_expect_success 'format-patch quotes double-quote in from-headers' '
 952        check_author "Foo \"The Baz\" Bar"
 953'
 954
 955cat >expect <<'EOF'
 956From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
 957EOF
 958test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
 959        check_author "Föo Bar"
 960'
 961
 962cat >expect <<'EOF'
 963From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
 964EOF
 965test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
 966        check_author "Föo B. Bar"
 967'
 968
 969cat >expect <<EOF
 970From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
 971 <author@example.com>
 972EOF
 973test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
 974        check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
 975'
 976
 977cat >expect <<'EOF'
 978From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
 979 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
 980 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
 981EOF
 982test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
 983        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"
 984'
 985
 986cat >expect <<'EOF'
 987From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
 988 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
 989 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
 990EOF
 991test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
 992        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"
 993'
 994
 995cat >expect <<'EOF'
 996From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
 997 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
 998 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
 999 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1000 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1001EOF
1002test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1003        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"
1004'
1005
1006cat >expect <<'EOF'
1007Subject: header with . in it
1008EOF
1009test_expect_success 'subject lines do not have 822 atom-quoting' '
1010        echo content >>file &&
1011        git add file &&
1012        git commit -m "header with . in it" &&
1013        git format-patch -k -1 --stdout >patch &&
1014        grep ^Subject: patch >actual &&
1015        test_cmp expect actual
1016'
1017
1018cat >expect <<'EOF'
1019Subject: [PREFIX 1/1] header with . in it
1020EOF
1021test_expect_success 'subject prefixes have space prepended' '
1022        git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1023        grep ^Subject: patch >actual &&
1024        test_cmp expect actual
1025'
1026
1027cat >expect <<'EOF'
1028Subject: [1/1] header with . in it
1029EOF
1030test_expect_success 'empty subject prefix does not have extra space' '
1031        git format-patch -n -1 --stdout --subject-prefix= >patch &&
1032        grep ^Subject: patch >actual &&
1033        test_cmp expect actual
1034'
1035
1036test_expect_success '--from=ident notices bogus ident' '
1037        test_must_fail git format-patch -1 --stdout --from=foo >patch
1038'
1039
1040test_expect_success '--from=ident replaces author' '
1041        git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1042        cat >expect <<-\EOF &&
1043        From: Me <me@example.com>
1044
1045        From: A U Thor <author@example.com>
1046
1047        EOF
1048        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1049        test_cmp expect patch.head
1050'
1051
1052test_expect_success '--from uses committer ident' '
1053        git format-patch -1 --stdout --from >patch &&
1054        cat >expect <<-\EOF &&
1055        From: C O Mitter <committer@example.com>
1056
1057        From: A U Thor <author@example.com>
1058
1059        EOF
1060        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1061        test_cmp expect patch.head
1062'
1063
1064test_expect_success '--from omits redundant in-body header' '
1065        git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1066        cat >expect <<-\EOF &&
1067        From: A U Thor <author@example.com>
1068
1069        EOF
1070        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1071        test_cmp expect patch.head
1072'
1073
1074test_expect_success 'in-body headers trigger content encoding' '
1075        test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1076        test_when_finished "git reset --hard HEAD^" &&
1077        git format-patch -1 --stdout --from >patch &&
1078        cat >expect <<-\EOF &&
1079        From: C O Mitter <committer@example.com>
1080        Content-Type: text/plain; charset=UTF-8
1081
1082        From: éxötìc <author@example.com>
1083
1084        EOF
1085        sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1086        test_cmp expect patch.head
1087'
1088
1089append_signoff()
1090{
1091        C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1092        git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1093        sed -n -e "1,/^---$/p" append_signoff.patch |
1094                egrep -n "^Subject|Sign|^$"
1095}
1096
1097test_expect_success 'signoff: commit with no body' '
1098        append_signoff </dev/null >actual &&
1099        cat <<\EOF | sed "s/EOL$//" >expected &&
11004:Subject: [PATCH] EOL
11018:
11029:Signed-off-by: C O Mitter <committer@example.com>
1103EOF
1104        test_cmp expected actual
1105'
1106
1107test_expect_success 'signoff: commit with only subject' '
1108        echo subject | append_signoff >actual &&
1109        cat >expected <<\EOF &&
11104:Subject: [PATCH] subject
11118:
11129:Signed-off-by: C O Mitter <committer@example.com>
1113EOF
1114        test_cmp expected actual
1115'
1116
1117test_expect_success 'signoff: commit with only subject that does not end with NL' '
1118        printf subject | append_signoff >actual &&
1119        cat >expected <<\EOF &&
11204:Subject: [PATCH] subject
11218:
11229:Signed-off-by: C O Mitter <committer@example.com>
1123EOF
1124        test_cmp expected actual
1125'
1126
1127test_expect_success 'signoff: no existing signoffs' '
1128        append_signoff <<\EOF >actual &&
1129subject
1130
1131body
1132EOF
1133        cat >expected <<\EOF &&
11344:Subject: [PATCH] subject
11358:
113610:
113711:Signed-off-by: C O Mitter <committer@example.com>
1138EOF
1139        test_cmp expected actual
1140'
1141
1142test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1143        printf "subject\n\nbody" | append_signoff >actual &&
1144        cat >expected <<\EOF &&
11454:Subject: [PATCH] subject
11468:
114710:
114811:Signed-off-by: C O Mitter <committer@example.com>
1149EOF
1150        test_cmp expected actual
1151'
1152
1153test_expect_success 'signoff: some random signoff' '
1154        append_signoff <<\EOF >actual &&
1155subject
1156
1157body
1158
1159Signed-off-by: my@house
1160EOF
1161        cat >expected <<\EOF &&
11624:Subject: [PATCH] subject
11638:
116410:
116511:Signed-off-by: my@house
116612:Signed-off-by: C O Mitter <committer@example.com>
1167EOF
1168        test_cmp expected actual
1169'
1170
1171test_expect_success 'signoff: misc conforming footer elements' '
1172        append_signoff <<\EOF >actual &&
1173subject
1174
1175body
1176
1177Signed-off-by: my@house
1178(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1179Tested-by: Some One <someone@example.com>
1180Bug: 1234
1181EOF
1182        cat >expected <<\EOF &&
11834:Subject: [PATCH] subject
11848:
118510:
118611:Signed-off-by: my@house
118715:Signed-off-by: C O Mitter <committer@example.com>
1188EOF
1189        test_cmp expected actual
1190'
1191
1192test_expect_success 'signoff: some random signoff-alike' '
1193        append_signoff <<\EOF >actual &&
1194subject
1195
1196body
1197Fooled-by-me: my@house
1198EOF
1199        cat >expected <<\EOF &&
12004:Subject: [PATCH] subject
12018:
120211:
120312:Signed-off-by: C O Mitter <committer@example.com>
1204EOF
1205        test_cmp expected actual
1206'
1207
1208test_expect_success 'signoff: not really a signoff' '
1209        append_signoff <<\EOF >actual &&
1210subject
1211
1212I want to mention about Signed-off-by: here.
1213EOF
1214        cat >expected <<\EOF &&
12154:Subject: [PATCH] subject
12168:
12179:I want to mention about Signed-off-by: here.
121810:
121911:Signed-off-by: C O Mitter <committer@example.com>
1220EOF
1221        test_cmp expected actual
1222'
1223
1224test_expect_success 'signoff: not really a signoff (2)' '
1225        append_signoff <<\EOF >actual &&
1226subject
1227
1228My unfortunate
1229Signed-off-by: example happens to be wrapped here.
1230EOF
1231        cat >expected <<\EOF &&
12324:Subject: [PATCH] subject
12338:
123410:Signed-off-by: example happens to be wrapped here.
123511:
123612:Signed-off-by: C O Mitter <committer@example.com>
1237EOF
1238        test_cmp expected actual
1239'
1240
1241test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1242        append_signoff <<\EOF >actual &&
1243subject
1244
1245Signed-off-by: my@house
1246Signed-off-by: your@house
1247
1248A lot of houses.
1249EOF
1250        cat >expected <<\EOF &&
12514:Subject: [PATCH] subject
12528:
12539:Signed-off-by: my@house
125410:Signed-off-by: your@house
125511:
125613:
125714:Signed-off-by: C O Mitter <committer@example.com>
1258EOF
1259        test_cmp expected actual
1260'
1261
1262test_expect_success 'signoff: the same signoff at the end' '
1263        append_signoff <<\EOF >actual &&
1264subject
1265
1266body
1267
1268Signed-off-by: C O Mitter <committer@example.com>
1269EOF
1270        cat >expected <<\EOF &&
12714:Subject: [PATCH] subject
12728:
127310:
127411:Signed-off-by: C O Mitter <committer@example.com>
1275EOF
1276        test_cmp expected actual
1277'
1278
1279test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1280        printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1281                append_signoff >actual &&
1282        cat >expected <<\EOF &&
12834:Subject: [PATCH] subject
12848:
12859:Signed-off-by: C O Mitter <committer@example.com>
1286EOF
1287        test_cmp expected actual
1288'
1289
1290test_expect_success 'signoff: the same signoff NOT at the end' '
1291        append_signoff <<\EOF >actual &&
1292subject
1293
1294body
1295
1296Signed-off-by: C O Mitter <committer@example.com>
1297Signed-off-by: my@house
1298EOF
1299        cat >expected <<\EOF &&
13004:Subject: [PATCH] subject
13018:
130210:
130311:Signed-off-by: C O Mitter <committer@example.com>
130412:Signed-off-by: my@house
1305EOF
1306        test_cmp expected actual
1307'
1308
1309test_expect_success 'signoff: detect garbage in non-conforming footer' '
1310        append_signoff <<\EOF >actual &&
1311subject
1312
1313body
1314
1315Tested-by: my@house
1316Some Trash
1317Signed-off-by: C O Mitter <committer@example.com>
1318EOF
1319        cat >expected <<\EOF &&
13204:Subject: [PATCH] subject
13218:
132210:
132313:Signed-off-by: C O Mitter <committer@example.com>
132414:
132515:Signed-off-by: C O Mitter <committer@example.com>
1326EOF
1327        test_cmp expected actual
1328'
1329
1330test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1331        append_signoff <<\EOF >actual &&
1332subject
1333
1334body
1335
1336Reviewed-id: Noone
1337Tested-by: my@house
1338Change-id: Ideadbeef
1339Signed-off-by: C O Mitter <committer@example.com>
1340Bug: 1234
1341EOF
1342        cat >expected <<\EOF &&
13434:Subject: [PATCH] subject
13448:
134510:
134614:Signed-off-by: C O Mitter <committer@example.com>
1347EOF
1348        test_cmp expected actual
1349'
1350
1351test_expect_success 'format patch ignores color.ui' '
1352        test_unconfig color.ui &&
1353        git format-patch --stdout -1 >expect &&
1354        test_config color.ui always &&
1355        git format-patch --stdout -1 >actual &&
1356        test_cmp expect actual
1357'
1358
1359test_expect_success 'cover letter using branch description (1)' '
1360        git checkout rebuild-1 &&
1361        test_config branch.rebuild-1.description hello &&
1362        git format-patch --stdout --cover-letter master >actual &&
1363        grep hello actual >/dev/null
1364'
1365
1366test_expect_success 'cover letter using branch description (2)' '
1367        git checkout rebuild-1 &&
1368        test_config branch.rebuild-1.description hello &&
1369        git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1370        grep hello actual >/dev/null
1371'
1372
1373test_expect_success 'cover letter using branch description (3)' '
1374        git checkout rebuild-1 &&
1375        test_config branch.rebuild-1.description hello &&
1376        git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1377        grep hello actual >/dev/null
1378'
1379
1380test_expect_success 'cover letter using branch description (4)' '
1381        git checkout rebuild-1 &&
1382        test_config branch.rebuild-1.description hello &&
1383        git format-patch --stdout --cover-letter master.. >actual &&
1384        grep hello actual >/dev/null
1385'
1386
1387test_expect_success 'cover letter using branch description (5)' '
1388        git checkout rebuild-1 &&
1389        test_config branch.rebuild-1.description hello &&
1390        git format-patch --stdout --cover-letter -2 HEAD >actual &&
1391        grep hello actual >/dev/null
1392'
1393
1394test_expect_success 'cover letter using branch description (6)' '
1395        git checkout rebuild-1 &&
1396        test_config branch.rebuild-1.description hello &&
1397        git format-patch --stdout --cover-letter -2 >actual &&
1398        grep hello actual >/dev/null
1399'
1400
1401test_expect_success 'cover letter with nothing' '
1402        git format-patch --stdout --cover-letter >actual &&
1403        test_line_count = 0 actual
1404'
1405
1406test_expect_success 'cover letter auto' '
1407        mkdir -p tmp &&
1408        test_when_finished "rm -rf tmp;
1409                git config --unset format.coverletter" &&
1410
1411        git config format.coverletter auto &&
1412        git format-patch -o tmp -1 >list &&
1413        test_line_count = 1 list &&
1414        git format-patch -o tmp -2 >list &&
1415        test_line_count = 3 list
1416'
1417
1418test_expect_success 'cover letter auto user override' '
1419        mkdir -p tmp &&
1420        test_when_finished "rm -rf tmp;
1421                git config --unset format.coverletter" &&
1422
1423        git config format.coverletter auto &&
1424        git format-patch -o tmp --cover-letter -1 >list &&
1425        test_line_count = 2 list &&
1426        git format-patch -o tmp --cover-letter -2 >list &&
1427        test_line_count = 3 list &&
1428        git format-patch -o tmp --no-cover-letter -1 >list &&
1429        test_line_count = 1 list &&
1430        git format-patch -o tmp --no-cover-letter -2 >list &&
1431        test_line_count = 2 list
1432'
1433
1434test_expect_success 'format-patch --zero-commit' '
1435        git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1436        grep "^From " patch2 | sort | uniq >actual &&
1437        echo "From $_z40 Mon Sep 17 00:00:00 2001" >expect &&
1438        test_cmp expect actual
1439'
1440
1441test_expect_success 'From line has expected format' '
1442        git format-patch --stdout v2..v1 >patch2 &&
1443        grep "^From " patch2 >from &&
1444        grep "^From $_x40 Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1445        test_cmp from filtered
1446'
1447
1448test_expect_success 'format-patch format.outputDirectory option' '
1449        test_config format.outputDirectory patches &&
1450        rm -fr patches &&
1451        git format-patch master..side &&
1452        test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
1453'
1454
1455test_expect_success 'format-patch -o overrides format.outputDirectory' '
1456        test_config format.outputDirectory patches &&
1457        rm -fr patches patchset &&
1458        git format-patch master..side -o patchset &&
1459        test_path_is_missing patches &&
1460        test_path_is_dir patchset
1461'
1462
1463test_expect_success 'format-patch --base' '
1464        git checkout side &&
1465        git format-patch --stdout --base=HEAD~3 -1 >patch &&
1466        grep "^base-commit:" patch >actual &&
1467        grep "^prerequisite-patch-id:" patch >>actual &&
1468        echo "base-commit: $(git rev-parse HEAD~3)" >expected &&
1469        echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1470        echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1471        test_cmp expected actual
1472'
1473
1474test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1475        test_must_fail git format-patch --base=HEAD -2 &&
1476        test_must_fail git format-patch --base=HEAD~1 -2 &&
1477        git format-patch --stdout --base=HEAD~2 -2 >patch &&
1478        grep "^base-commit:" patch >actual &&
1479        echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
1480        test_cmp expected actual
1481'
1482
1483test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1484        # For history as below:
1485        #
1486        #    ---Q---P---Z---Y---*---X
1487        #        \             /
1488        #         ------------W
1489        #
1490        # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1491        git checkout -b topic1 master &&
1492        git rev-parse HEAD >commit-id-base &&
1493        test_commit P &&
1494        git rev-parse HEAD >commit-id-P &&
1495        test_commit Z &&
1496        git rev-parse HEAD >commit-id-Z &&
1497        test_commit Y &&
1498        git checkout -b topic2 master &&
1499        test_commit W &&
1500        git merge topic1 &&
1501        test_commit X &&
1502        test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1503        test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1504        git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1505        grep "^base-commit:" patch >actual &&
1506        echo "base-commit: $(cat commit-id-base)" >expected &&
1507        test_cmp expected actual
1508'
1509
1510test_expect_success 'format-patch --base=auto' '
1511        git checkout -b upstream master &&
1512        git checkout -b local upstream &&
1513        git branch --set-upstream-to=upstream &&
1514        test_commit N1 &&
1515        test_commit N2 &&
1516        git format-patch --stdout --base=auto -2 >patch &&
1517        grep "^base-commit:" patch >actual &&
1518        echo "base-commit: $(git rev-parse upstream)" >expected &&
1519        test_cmp expected actual
1520'
1521
1522test_expect_success 'format-patch errors out when history involves criss-cross' '
1523        # setup criss-cross history
1524        #
1525        #   B---M1---D
1526        #  / \ /
1527        # A   X
1528        #  \ / \
1529        #   C---M2---E
1530        #
1531        git checkout master &&
1532        test_commit A &&
1533        git checkout -b xb master &&
1534        test_commit B &&
1535        git checkout -b xc master &&
1536        test_commit C &&
1537        git checkout -b xbc xb -- &&
1538        git merge xc &&
1539        git checkout -b xcb xc -- &&
1540        git branch --set-upstream-to=xbc &&
1541        git merge xb &&
1542        git checkout xbc &&
1543        test_commit D &&
1544        git checkout xcb &&
1545        test_commit E &&
1546        test_must_fail  git format-patch --base=auto -1
1547'
1548
1549test_expect_success 'format-patch format.useAutoBaseoption' '
1550        test_when_finished "git config --unset format.useAutoBase" &&
1551        git checkout local &&
1552        git config format.useAutoBase true &&
1553        git format-patch --stdout -1 >patch &&
1554        grep "^base-commit:" patch >actual &&
1555        echo "base-commit: $(git rev-parse upstream)" >expected &&
1556        test_cmp expected actual
1557'
1558
1559test_expect_success 'format-patch --base overrides format.useAutoBase' '
1560        test_when_finished "git config --unset format.useAutoBase" &&
1561        git config format.useAutoBase true &&
1562        git format-patch --stdout --base=HEAD~1 -1 >patch &&
1563        grep "^base-commit:" patch >actual &&
1564        echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
1565        test_cmp expected actual
1566'
1567
1568test_expect_success 'format-patch --pretty=mboxrd' '
1569        sp=" " &&
1570        cat >msg <<-INPUT_END &&
1571        mboxrd should escape the body
1572
1573        From could trip up a loose mbox parser
1574        >From extra escape for reversibility
1575        >>From extra escape for reversibility 2
1576        from lower case not escaped
1577        Fromm bad speling not escaped
1578         From with leading space not escaped
1579
1580        F
1581        From
1582        From$sp
1583        From    $sp
1584        From    $sp
1585        INPUT_END
1586
1587        cat >expect <<-INPUT_END &&
1588        >From could trip up a loose mbox parser
1589        >>From extra escape for reversibility
1590        >>>From extra escape for reversibility 2
1591        from lower case not escaped
1592        Fromm bad speling not escaped
1593         From with leading space not escaped
1594
1595        F
1596        From
1597        From
1598        From
1599        From
1600        INPUT_END
1601
1602        C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
1603        git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
1604        git grep -h --no-index -A11 \
1605                "^>From could trip up a loose mbox parser" patch >actual &&
1606        test_cmp expect actual
1607'
1608
1609test_done