t / t4014-format-patch.shon commit Merge branch 'jk/cvsimport-quoting' into maint-2.10 (6d6e2f8)
   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 'format.from=false' '
 233
 234        git -c format.from=false format-patch --stdout master..side |
 235        sed -e "/^\$/q" >patch &&
 236        check_patch patch &&
 237        ! grep "^From: C O Mitter <committer@example.com>\$" patch
 238'
 239
 240test_expect_success 'format.from=true' '
 241
 242        git -c format.from=true format-patch --stdout master..side |
 243        sed -e "/^\$/q" >patch &&
 244        check_patch patch &&
 245        grep "^From: C O Mitter <committer@example.com>\$" patch
 246'
 247
 248test_expect_success 'format.from with address' '
 249
 250        git -c format.from="F R Om <from@example.com>" format-patch --stdout master..side |
 251        sed -e "/^\$/q" >patch &&
 252        check_patch patch &&
 253        grep "^From: F R Om <from@example.com>\$" patch
 254'
 255
 256test_expect_success '--no-from overrides format.from' '
 257
 258        git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout master..side |
 259        sed -e "/^\$/q" >patch &&
 260        check_patch patch &&
 261        ! grep "^From: F R Om <from@example.com>\$" patch
 262'
 263
 264test_expect_success '--from overrides format.from' '
 265
 266        git -c format.from="F R Om <from@example.com>" format-patch --from --stdout master..side |
 267        sed -e "/^\$/q" >patch &&
 268        check_patch patch &&
 269        ! grep "^From: F R Om <from@example.com>\$" patch
 270'
 271
 272test_expect_success '--no-to overrides config.to' '
 273
 274        git config --replace-all format.to \
 275                "R E Cipient <rcipient@example.com>" &&
 276        git format-patch --no-to --stdout master..side |
 277        sed -e "/^\$/q" >patch10 &&
 278        check_patch patch10 &&
 279        ! grep "^To: R E Cipient <rcipient@example.com>\$" patch10
 280'
 281
 282test_expect_success '--no-to and --to replaces config.to' '
 283
 284        git config --replace-all format.to \
 285                "Someone <someone@out.there>" &&
 286        git format-patch --no-to --to="Someone Else <else@out.there>" \
 287                --stdout master..side |
 288        sed -e "/^\$/q" >patch11 &&
 289        check_patch patch11 &&
 290        ! grep "^To: Someone <someone@out.there>\$" patch11 &&
 291        grep "^To: Someone Else <else@out.there>\$" patch11
 292'
 293
 294test_expect_success '--no-cc overrides config.cc' '
 295
 296        git config --replace-all format.cc \
 297                "C E Cipient <rcipient@example.com>" &&
 298        git format-patch --no-cc --stdout master..side |
 299        sed -e "/^\$/q" >patch12 &&
 300        check_patch patch12 &&
 301        ! grep "^Cc: C E Cipient <rcipient@example.com>\$" patch12
 302'
 303
 304test_expect_success '--no-add-header overrides config.headers' '
 305
 306        git config --replace-all format.headers \
 307                "Header1: B E Cipient <rcipient@example.com>" &&
 308        git format-patch --no-add-header --stdout master..side |
 309        sed -e "/^\$/q" >patch13 &&
 310        check_patch patch13 &&
 311        ! grep "^Header1: B E Cipient <rcipient@example.com>\$" patch13
 312'
 313
 314test_expect_success 'multiple files' '
 315
 316        rm -rf patches/ &&
 317        git checkout side &&
 318        git format-patch -o patches/ master &&
 319        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
 320'
 321
 322test_expect_success 'reroll count' '
 323        rm -fr patches &&
 324        git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
 325        ! grep -v "^patches/v4-000[0-3]-" list &&
 326        sed -n -e "/^Subject: /p" $(cat list) >subjects &&
 327        ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
 328'
 329
 330test_expect_success 'reroll count (-v)' '
 331        rm -fr patches &&
 332        git format-patch -o patches --cover-letter -v4 master..side >list &&
 333        ! grep -v "^patches/v4-000[0-3]-" list &&
 334        sed -n -e "/^Subject: /p" $(cat list) >subjects &&
 335        ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
 336'
 337
 338check_threading () {
 339        expect="$1" &&
 340        shift &&
 341        (git format-patch --stdout "$@"; echo $? > status.out) |
 342        # Prints everything between the Message-ID and In-Reply-To,
 343        # and replaces all Message-ID-lookalikes by a sequence number
 344        perl -ne '
 345                if (/^(message-id|references|in-reply-to)/i) {
 346                        $printing = 1;
 347                } elsif (/^\S/) {
 348                        $printing = 0;
 349                }
 350                if ($printing) {
 351                        $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
 352                        for $k (keys %h) {s/$k/$h{$k}/};
 353                        print;
 354                }
 355                print "---\n" if /^From /i;
 356        ' > actual &&
 357        test 0 = "$(cat status.out)" &&
 358        test_cmp "$expect" actual
 359}
 360
 361cat >> expect.no-threading <<EOF
 362---
 363---
 364---
 365EOF
 366
 367test_expect_success 'no threading' '
 368        git checkout side &&
 369        check_threading expect.no-threading master
 370'
 371
 372cat > expect.thread <<EOF
 373---
 374Message-Id: <0>
 375---
 376Message-Id: <1>
 377In-Reply-To: <0>
 378References: <0>
 379---
 380Message-Id: <2>
 381In-Reply-To: <0>
 382References: <0>
 383EOF
 384
 385test_expect_success 'thread' '
 386        check_threading expect.thread --thread master
 387'
 388
 389cat > expect.in-reply-to <<EOF
 390---
 391Message-Id: <0>
 392In-Reply-To: <1>
 393References: <1>
 394---
 395Message-Id: <2>
 396In-Reply-To: <1>
 397References: <1>
 398---
 399Message-Id: <3>
 400In-Reply-To: <1>
 401References: <1>
 402EOF
 403
 404test_expect_success 'thread in-reply-to' '
 405        check_threading expect.in-reply-to --in-reply-to="<test.message>" \
 406                --thread master
 407'
 408
 409cat > expect.cover-letter <<EOF
 410---
 411Message-Id: <0>
 412---
 413Message-Id: <1>
 414In-Reply-To: <0>
 415References: <0>
 416---
 417Message-Id: <2>
 418In-Reply-To: <0>
 419References: <0>
 420---
 421Message-Id: <3>
 422In-Reply-To: <0>
 423References: <0>
 424EOF
 425
 426test_expect_success 'thread cover-letter' '
 427        check_threading expect.cover-letter --cover-letter --thread master
 428'
 429
 430cat > expect.cl-irt <<EOF
 431---
 432Message-Id: <0>
 433In-Reply-To: <1>
 434References: <1>
 435---
 436Message-Id: <2>
 437In-Reply-To: <0>
 438References: <1>
 439        <0>
 440---
 441Message-Id: <3>
 442In-Reply-To: <0>
 443References: <1>
 444        <0>
 445---
 446Message-Id: <4>
 447In-Reply-To: <0>
 448References: <1>
 449        <0>
 450EOF
 451
 452test_expect_success 'thread cover-letter in-reply-to' '
 453        check_threading expect.cl-irt --cover-letter \
 454                --in-reply-to="<test.message>" --thread master
 455'
 456
 457test_expect_success 'thread explicit shallow' '
 458        check_threading expect.cl-irt --cover-letter \
 459                --in-reply-to="<test.message>" --thread=shallow master
 460'
 461
 462cat > expect.deep <<EOF
 463---
 464Message-Id: <0>
 465---
 466Message-Id: <1>
 467In-Reply-To: <0>
 468References: <0>
 469---
 470Message-Id: <2>
 471In-Reply-To: <1>
 472References: <0>
 473        <1>
 474EOF
 475
 476test_expect_success 'thread deep' '
 477        check_threading expect.deep --thread=deep master
 478'
 479
 480cat > expect.deep-irt <<EOF
 481---
 482Message-Id: <0>
 483In-Reply-To: <1>
 484References: <1>
 485---
 486Message-Id: <2>
 487In-Reply-To: <0>
 488References: <1>
 489        <0>
 490---
 491Message-Id: <3>
 492In-Reply-To: <2>
 493References: <1>
 494        <0>
 495        <2>
 496EOF
 497
 498test_expect_success 'thread deep in-reply-to' '
 499        check_threading expect.deep-irt  --thread=deep \
 500                --in-reply-to="<test.message>" master
 501'
 502
 503cat > expect.deep-cl <<EOF
 504---
 505Message-Id: <0>
 506---
 507Message-Id: <1>
 508In-Reply-To: <0>
 509References: <0>
 510---
 511Message-Id: <2>
 512In-Reply-To: <1>
 513References: <0>
 514        <1>
 515---
 516Message-Id: <3>
 517In-Reply-To: <2>
 518References: <0>
 519        <1>
 520        <2>
 521EOF
 522
 523test_expect_success 'thread deep cover-letter' '
 524        check_threading expect.deep-cl --cover-letter --thread=deep master
 525'
 526
 527cat > expect.deep-cl-irt <<EOF
 528---
 529Message-Id: <0>
 530In-Reply-To: <1>
 531References: <1>
 532---
 533Message-Id: <2>
 534In-Reply-To: <0>
 535References: <1>
 536        <0>
 537---
 538Message-Id: <3>
 539In-Reply-To: <2>
 540References: <1>
 541        <0>
 542        <2>
 543---
 544Message-Id: <4>
 545In-Reply-To: <3>
 546References: <1>
 547        <0>
 548        <2>
 549        <3>
 550EOF
 551
 552test_expect_success 'thread deep cover-letter in-reply-to' '
 553        check_threading expect.deep-cl-irt --cover-letter \
 554                --in-reply-to="<test.message>" --thread=deep master
 555'
 556
 557test_expect_success 'thread via config' '
 558        test_config format.thread true &&
 559        check_threading expect.thread master
 560'
 561
 562test_expect_success 'thread deep via config' '
 563        test_config format.thread deep &&
 564        check_threading expect.deep master
 565'
 566
 567test_expect_success 'thread config + override' '
 568        test_config format.thread deep &&
 569        check_threading expect.thread --thread master
 570'
 571
 572test_expect_success 'thread config + --no-thread' '
 573        test_config format.thread deep &&
 574        check_threading expect.no-threading --no-thread master
 575'
 576
 577test_expect_success 'excessive subject' '
 578
 579        rm -rf patches/ &&
 580        git checkout side &&
 581        for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
 582        git update-index file &&
 583        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." &&
 584        git format-patch -o patches/ master..side &&
 585        ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
 586'
 587
 588test_expect_success 'cover-letter inherits diff options' '
 589
 590        git mv file foo &&
 591        git commit -m foo &&
 592        git format-patch --no-renames --cover-letter -1 &&
 593        check_patch 0000-cover-letter.patch &&
 594        ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
 595        git format-patch --cover-letter -1 -M &&
 596        grep "file => foo .* 0 *\$" 0000-cover-letter.patch
 597
 598'
 599
 600cat > expect << EOF
 601  This is an excessively long subject line for a message due to the
 602    habit some projects have of not having a short, one-line subject at
 603    the start of the commit message, but rather sticking a whole
 604    paragraph right at the start as the only thing in the commit
 605    message. It had better not become the filename for the patch.
 606  foo
 607
 608EOF
 609
 610test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
 611
 612        git format-patch --cover-letter -2 &&
 613        sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
 614        test_cmp expect output
 615
 616'
 617
 618cat > expect << EOF
 619index 40f36c6..2dc5c23 100644
 620--- a/file
 621+++ b/file
 622@@ -13,4 +13,20 @@ C
 623 10
 624 D
 625 E
 626 F
 627+5
 628EOF
 629
 630test_expect_success 'format-patch respects -U' '
 631
 632        git format-patch -U4 -2 &&
 633        sed -e "1,/^diff/d" -e "/^+5/q" \
 634                <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
 635                >output &&
 636        test_cmp expect output
 637
 638'
 639
 640cat > expect << EOF
 641
 642diff --git a/file b/file
 643index 40f36c6..2dc5c23 100644
 644--- a/file
 645+++ b/file
 646@@ -14,3 +14,19 @@ C
 647 D
 648 E
 649 F
 650+5
 651EOF
 652
 653test_expect_success 'format-patch -p suppresses stat' '
 654
 655        git format-patch -p -2 &&
 656        sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
 657        test_cmp expect output
 658
 659'
 660
 661test_expect_success 'format-patch from a subdirectory (1)' '
 662        filename=$(
 663                rm -rf sub &&
 664                mkdir -p sub/dir &&
 665                cd sub/dir &&
 666                git format-patch -1
 667        ) &&
 668        case "$filename" in
 669        0*)
 670                ;; # ok
 671        *)
 672                echo "Oops? $filename"
 673                false
 674                ;;
 675        esac &&
 676        test -f "$filename"
 677'
 678
 679test_expect_success 'format-patch from a subdirectory (2)' '
 680        filename=$(
 681                rm -rf sub &&
 682                mkdir -p sub/dir &&
 683                cd sub/dir &&
 684                git format-patch -1 -o ..
 685        ) &&
 686        case "$filename" in
 687        ../0*)
 688                ;; # ok
 689        *)
 690                echo "Oops? $filename"
 691                false
 692                ;;
 693        esac &&
 694        basename=$(expr "$filename" : ".*/\(.*\)") &&
 695        test -f "sub/$basename"
 696'
 697
 698test_expect_success 'format-patch from a subdirectory (3)' '
 699        rm -f 0* &&
 700        filename=$(
 701                rm -rf sub &&
 702                mkdir -p sub/dir &&
 703                cd sub/dir &&
 704                git format-patch -1 -o "$TRASH_DIRECTORY"
 705        ) &&
 706        basename=$(expr "$filename" : ".*/\(.*\)") &&
 707        test -f "$basename"
 708'
 709
 710test_expect_success 'format-patch --in-reply-to' '
 711        git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
 712        grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
 713        grep "^References: <baz@foo.bar>" patch8
 714'
 715
 716test_expect_success 'format-patch --signoff' '
 717        git format-patch -1 --signoff --stdout >out &&
 718        grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
 719'
 720
 721test_expect_success 'format-patch --notes --signoff' '
 722        git notes --ref test add -m "test message" HEAD &&
 723        git format-patch -1 --signoff --stdout --notes=test >out &&
 724        # Three dashes must come after S-o-b
 725        ! sed "/^Signed-off-by: /q" out | grep "test message" &&
 726        sed "1,/^Signed-off-by: /d" out | grep "test message" &&
 727        # Notes message must come after three dashes
 728        ! sed "/^---$/q" out | grep "test message" &&
 729        sed "1,/^---$/d" out | grep "test message"
 730'
 731
 732echo "fatal: --name-only does not make sense" > expect.name-only
 733echo "fatal: --name-status does not make sense" > expect.name-status
 734echo "fatal: --check does not make sense" > expect.check
 735
 736test_expect_success 'options no longer allowed for format-patch' '
 737        test_must_fail git format-patch --name-only 2> output &&
 738        test_i18ncmp expect.name-only output &&
 739        test_must_fail git format-patch --name-status 2> output &&
 740        test_i18ncmp expect.name-status output &&
 741        test_must_fail git format-patch --check 2> output &&
 742        test_i18ncmp expect.check output'
 743
 744test_expect_success 'format-patch --numstat should produce a patch' '
 745        git format-patch --numstat --stdout master..side > output &&
 746        test 5 = $(grep "^diff --git a/" output | wc -l)'
 747
 748test_expect_success 'format-patch -- <path>' '
 749        git format-patch master..side -- file 2>error &&
 750        ! grep "Use .--" error
 751'
 752
 753test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
 754        git format-patch --ignore-if-in-upstream HEAD
 755'
 756
 757git_version="$(git --version | sed "s/.* //")"
 758
 759signature() {
 760        printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
 761}
 762
 763test_expect_success 'format-patch default signature' '
 764        git format-patch --stdout -1 | tail -n 3 >output &&
 765        signature >expect &&
 766        test_cmp expect output
 767'
 768
 769test_expect_success 'format-patch --signature' '
 770        git format-patch --stdout --signature="my sig" -1 | tail -n 3 >output &&
 771        signature "my sig" >expect &&
 772        test_cmp expect output
 773'
 774
 775test_expect_success 'format-patch with format.signature config' '
 776        git config format.signature "config sig" &&
 777        git format-patch --stdout -1 >output &&
 778        grep "config sig" output
 779'
 780
 781test_expect_success 'format-patch --signature overrides format.signature' '
 782        git config format.signature "config sig" &&
 783        git format-patch --stdout --signature="overrides" -1 >output &&
 784        ! grep "config sig" output &&
 785        grep "overrides" output
 786'
 787
 788test_expect_success 'format-patch --no-signature ignores format.signature' '
 789        git config format.signature "config sig" &&
 790        git format-patch --stdout --signature="my sig" --no-signature \
 791                -1 >output &&
 792        check_patch output &&
 793        ! grep "config sig" output &&
 794        ! grep "my sig" output &&
 795        ! grep "^-- \$" output
 796'
 797
 798test_expect_success 'format-patch --signature --cover-letter' '
 799        git config --unset-all format.signature &&
 800        git format-patch --stdout --signature="my sig" --cover-letter \
 801                -1 >output &&
 802        grep "my sig" output &&
 803        test 2 = $(grep "my sig" output | wc -l)
 804'
 805
 806test_expect_success 'format.signature="" suppresses signatures' '
 807        git config format.signature "" &&
 808        git format-patch --stdout -1 >output &&
 809        check_patch output &&
 810        ! grep "^-- \$" output
 811'
 812
 813test_expect_success 'format-patch --no-signature suppresses signatures' '
 814        git config --unset-all format.signature &&
 815        git format-patch --stdout --no-signature -1 >output &&
 816        check_patch output &&
 817        ! grep "^-- \$" output
 818'
 819
 820test_expect_success 'format-patch --signature="" suppresses signatures' '
 821        git format-patch --stdout --signature="" -1 >output &&
 822        check_patch output &&
 823        ! grep "^-- \$" output
 824'
 825
 826test_expect_success 'prepare mail-signature input' '
 827        cat >mail-signature <<-\EOF
 828
 829        Test User <test.email@kernel.org>
 830        http://git.kernel.org/cgit/git/git.git
 831
 832        git.kernel.org/?p=git/git.git;a=summary
 833
 834        EOF
 835'
 836
 837test_expect_success '--signature-file=file works' '
 838        git format-patch --stdout --signature-file=mail-signature -1 >output &&
 839        check_patch output &&
 840        sed -e "1,/^-- \$/d" <output >actual &&
 841        {
 842                cat mail-signature && echo
 843        } >expect &&
 844        test_cmp expect actual
 845'
 846
 847test_expect_success 'format.signaturefile works' '
 848        test_config format.signaturefile mail-signature &&
 849        git format-patch --stdout -1 >output &&
 850        check_patch output &&
 851        sed -e "1,/^-- \$/d" <output >actual &&
 852        {
 853                cat mail-signature && echo
 854        } >expect &&
 855        test_cmp expect actual
 856'
 857
 858test_expect_success '--no-signature suppresses format.signaturefile ' '
 859        test_config format.signaturefile mail-signature &&
 860        git format-patch --stdout --no-signature -1 >output &&
 861        check_patch output &&
 862        ! grep "^-- \$" output
 863'
 864
 865test_expect_success '--signature-file overrides format.signaturefile' '
 866        cat >other-mail-signature <<-\EOF &&
 867        Use this other signature instead of mail-signature.
 868        EOF
 869        test_config format.signaturefile mail-signature &&
 870        git format-patch --stdout \
 871                        --signature-file=other-mail-signature -1 >output &&
 872        check_patch output &&
 873        sed -e "1,/^-- \$/d" <output >actual &&
 874        {
 875                cat other-mail-signature && echo
 876        } >expect &&
 877        test_cmp expect actual
 878'
 879
 880test_expect_success '--signature overrides format.signaturefile' '
 881        test_config format.signaturefile mail-signature &&
 882        git format-patch --stdout --signature="my sig" -1 >output &&
 883        check_patch output &&
 884        grep "my sig" output
 885'
 886
 887test_expect_success TTY 'format-patch --stdout paginates' '
 888        rm -f pager_used &&
 889        test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
 890        test_path_is_file pager_used
 891'
 892
 893 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
 894        rm -f pager_used &&
 895        test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
 896        test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
 897        test_path_is_missing pager_used &&
 898        test_path_is_missing .git/pager_used
 899'
 900
 901test_expect_success 'format-patch handles multi-line subjects' '
 902        rm -rf patches/ &&
 903        echo content >>file &&
 904        for i in one two three; do echo $i; done >msg &&
 905        git add file &&
 906        git commit -F msg &&
 907        git format-patch -o patches -1 &&
 908        grep ^Subject: patches/0001-one.patch >actual &&
 909        echo "Subject: [PATCH] one two three" >expect &&
 910        test_cmp expect actual
 911'
 912
 913test_expect_success 'format-patch handles multi-line encoded subjects' '
 914        rm -rf patches/ &&
 915        echo content >>file &&
 916        for i in en två tre; do echo $i; done >msg &&
 917        git add file &&
 918        git commit -F msg &&
 919        git format-patch -o patches -1 &&
 920        grep ^Subject: patches/0001-en.patch >actual &&
 921        echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
 922        test_cmp expect actual
 923'
 924
 925M8="foo bar "
 926M64=$M8$M8$M8$M8$M8$M8$M8$M8
 927M512=$M64$M64$M64$M64$M64$M64$M64$M64
 928cat >expect <<'EOF'
 929Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 930 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 931 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 932 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 933 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 934 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 935 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 936EOF
 937test_expect_success 'format-patch wraps extremely long subject (ascii)' '
 938        echo content >>file &&
 939        git add file &&
 940        git commit -m "$M512" &&
 941        git format-patch --stdout -1 >patch &&
 942        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 943        test_cmp expect subject
 944'
 945
 946M8="föö bar "
 947M64=$M8$M8$M8$M8$M8$M8$M8$M8
 948M512=$M64$M64$M64$M64$M64$M64$M64$M64
 949cat >expect <<'EOF'
 950Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 951 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 952 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 953 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 954 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 955 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 956 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 957 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 958 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 959 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 960 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 961 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 962 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 963 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 964 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 965 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 966 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 967 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 968 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 969 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 970 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 971 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 972 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 973 =?UTF-8?q?bar?=
 974EOF
 975test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
 976        rm -rf patches/ &&
 977        echo content >>file &&
 978        git add file &&
 979        git commit -m "$M512" &&
 980        git format-patch --stdout -1 >patch &&
 981        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 982        test_cmp expect subject
 983'
 984
 985check_author() {
 986        echo content >>file &&
 987        git add file &&
 988        GIT_AUTHOR_NAME=$1 git commit -m author-check &&
 989        git format-patch --stdout -1 >patch &&
 990        sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
 991        test_cmp expect actual
 992}
 993
 994cat >expect <<'EOF'
 995From: "Foo B. Bar" <author@example.com>
 996EOF
 997test_expect_success 'format-patch quotes dot in from-headers' '
 998        check_author "Foo B. Bar"
 999'
1000
1001cat >expect <<'EOF'
1002From: "Foo \"The Baz\" Bar" <author@example.com>
1003EOF
1004test_expect_success 'format-patch quotes double-quote in from-headers' '
1005        check_author "Foo \"The Baz\" Bar"
1006'
1007
1008cat >expect <<'EOF'
1009From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1010EOF
1011test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1012        check_author "Föo Bar"
1013'
1014
1015cat >expect <<'EOF'
1016From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1017EOF
1018test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1019        check_author "Föo B. Bar"
1020'
1021
1022cat >expect <<EOF
1023From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1024 <author@example.com>
1025EOF
1026test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1027        check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1028'
1029
1030cat >expect <<'EOF'
1031From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1032 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1033 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1034EOF
1035test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1036        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"
1037'
1038
1039cat >expect <<'EOF'
1040From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1041 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1042 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1043EOF
1044test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1045        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"
1046'
1047
1048cat >expect <<'EOF'
1049From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1050 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1051 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1052 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1053 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1054EOF
1055test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1056        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"
1057'
1058
1059cat >expect <<'EOF'
1060Subject: header with . in it
1061EOF
1062test_expect_success 'subject lines do not have 822 atom-quoting' '
1063        echo content >>file &&
1064        git add file &&
1065        git commit -m "header with . in it" &&
1066        git format-patch -k -1 --stdout >patch &&
1067        grep ^Subject: patch >actual &&
1068        test_cmp expect actual
1069'
1070
1071cat >expect <<'EOF'
1072Subject: [PREFIX 1/1] header with . in it
1073EOF
1074test_expect_success 'subject prefixes have space prepended' '
1075        git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1076        grep ^Subject: patch >actual &&
1077        test_cmp expect actual
1078'
1079
1080cat >expect <<'EOF'
1081Subject: [1/1] header with . in it
1082EOF
1083test_expect_success 'empty subject prefix does not have extra space' '
1084        git format-patch -n -1 --stdout --subject-prefix= >patch &&
1085        grep ^Subject: patch >actual &&
1086        test_cmp expect actual
1087'
1088
1089test_expect_success '--from=ident notices bogus ident' '
1090        test_must_fail git format-patch -1 --stdout --from=foo >patch
1091'
1092
1093test_expect_success '--from=ident replaces author' '
1094        git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1095        cat >expect <<-\EOF &&
1096        From: Me <me@example.com>
1097
1098        From: A U Thor <author@example.com>
1099
1100        EOF
1101        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1102        test_cmp expect patch.head
1103'
1104
1105test_expect_success '--from uses committer ident' '
1106        git format-patch -1 --stdout --from >patch &&
1107        cat >expect <<-\EOF &&
1108        From: C O Mitter <committer@example.com>
1109
1110        From: A U Thor <author@example.com>
1111
1112        EOF
1113        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1114        test_cmp expect patch.head
1115'
1116
1117test_expect_success '--from omits redundant in-body header' '
1118        git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1119        cat >expect <<-\EOF &&
1120        From: A U Thor <author@example.com>
1121
1122        EOF
1123        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1124        test_cmp expect patch.head
1125'
1126
1127test_expect_success 'in-body headers trigger content encoding' '
1128        test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1129        test_when_finished "git reset --hard HEAD^" &&
1130        git format-patch -1 --stdout --from >patch &&
1131        cat >expect <<-\EOF &&
1132        From: C O Mitter <committer@example.com>
1133        Content-Type: text/plain; charset=UTF-8
1134
1135        From: éxötìc <author@example.com>
1136
1137        EOF
1138        sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1139        test_cmp expect patch.head
1140'
1141
1142append_signoff()
1143{
1144        C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1145        git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1146        sed -n -e "1,/^---$/p" append_signoff.patch |
1147                egrep -n "^Subject|Sign|^$"
1148}
1149
1150test_expect_success 'signoff: commit with no body' '
1151        append_signoff </dev/null >actual &&
1152        cat <<\EOF | sed "s/EOL$//" >expected &&
11534:Subject: [PATCH] EOL
11548:
11559:Signed-off-by: C O Mitter <committer@example.com>
1156EOF
1157        test_cmp expected actual
1158'
1159
1160test_expect_success 'signoff: commit with only subject' '
1161        echo subject | append_signoff >actual &&
1162        cat >expected <<\EOF &&
11634:Subject: [PATCH] subject
11648:
11659:Signed-off-by: C O Mitter <committer@example.com>
1166EOF
1167        test_cmp expected actual
1168'
1169
1170test_expect_success 'signoff: commit with only subject that does not end with NL' '
1171        printf subject | append_signoff >actual &&
1172        cat >expected <<\EOF &&
11734:Subject: [PATCH] subject
11748:
11759:Signed-off-by: C O Mitter <committer@example.com>
1176EOF
1177        test_cmp expected actual
1178'
1179
1180test_expect_success 'signoff: no existing signoffs' '
1181        append_signoff <<\EOF >actual &&
1182subject
1183
1184body
1185EOF
1186        cat >expected <<\EOF &&
11874:Subject: [PATCH] subject
11888:
118910:
119011:Signed-off-by: C O Mitter <committer@example.com>
1191EOF
1192        test_cmp expected actual
1193'
1194
1195test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1196        printf "subject\n\nbody" | append_signoff >actual &&
1197        cat >expected <<\EOF &&
11984:Subject: [PATCH] subject
11998:
120010:
120111:Signed-off-by: C O Mitter <committer@example.com>
1202EOF
1203        test_cmp expected actual
1204'
1205
1206test_expect_success 'signoff: some random signoff' '
1207        append_signoff <<\EOF >actual &&
1208subject
1209
1210body
1211
1212Signed-off-by: my@house
1213EOF
1214        cat >expected <<\EOF &&
12154:Subject: [PATCH] subject
12168:
121710:
121811:Signed-off-by: my@house
121912:Signed-off-by: C O Mitter <committer@example.com>
1220EOF
1221        test_cmp expected actual
1222'
1223
1224test_expect_success 'signoff: misc conforming footer elements' '
1225        append_signoff <<\EOF >actual &&
1226subject
1227
1228body
1229
1230Signed-off-by: my@house
1231(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1232Tested-by: Some One <someone@example.com>
1233Bug: 1234
1234EOF
1235        cat >expected <<\EOF &&
12364:Subject: [PATCH] subject
12378:
123810:
123911:Signed-off-by: my@house
124015:Signed-off-by: C O Mitter <committer@example.com>
1241EOF
1242        test_cmp expected actual
1243'
1244
1245test_expect_success 'signoff: some random signoff-alike' '
1246        append_signoff <<\EOF >actual &&
1247subject
1248
1249body
1250Fooled-by-me: my@house
1251EOF
1252        cat >expected <<\EOF &&
12534:Subject: [PATCH] subject
12548:
125511:
125612:Signed-off-by: C O Mitter <committer@example.com>
1257EOF
1258        test_cmp expected actual
1259'
1260
1261test_expect_success 'signoff: not really a signoff' '
1262        append_signoff <<\EOF >actual &&
1263subject
1264
1265I want to mention about Signed-off-by: here.
1266EOF
1267        cat >expected <<\EOF &&
12684:Subject: [PATCH] subject
12698:
12709:I want to mention about Signed-off-by: here.
127110:
127211:Signed-off-by: C O Mitter <committer@example.com>
1273EOF
1274        test_cmp expected actual
1275'
1276
1277test_expect_success 'signoff: not really a signoff (2)' '
1278        append_signoff <<\EOF >actual &&
1279subject
1280
1281My unfortunate
1282Signed-off-by: example happens to be wrapped here.
1283EOF
1284        cat >expected <<\EOF &&
12854:Subject: [PATCH] subject
12868:
128710:Signed-off-by: example happens to be wrapped here.
128811:
128912:Signed-off-by: C O Mitter <committer@example.com>
1290EOF
1291        test_cmp expected actual
1292'
1293
1294test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1295        append_signoff <<\EOF >actual &&
1296subject
1297
1298Signed-off-by: my@house
1299Signed-off-by: your@house
1300
1301A lot of houses.
1302EOF
1303        cat >expected <<\EOF &&
13044:Subject: [PATCH] subject
13058:
13069:Signed-off-by: my@house
130710:Signed-off-by: your@house
130811:
130913:
131014:Signed-off-by: C O Mitter <committer@example.com>
1311EOF
1312        test_cmp expected actual
1313'
1314
1315test_expect_success 'signoff: the same signoff at the end' '
1316        append_signoff <<\EOF >actual &&
1317subject
1318
1319body
1320
1321Signed-off-by: C O Mitter <committer@example.com>
1322EOF
1323        cat >expected <<\EOF &&
13244:Subject: [PATCH] subject
13258:
132610:
132711:Signed-off-by: C O Mitter <committer@example.com>
1328EOF
1329        test_cmp expected actual
1330'
1331
1332test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1333        printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1334                append_signoff >actual &&
1335        cat >expected <<\EOF &&
13364:Subject: [PATCH] subject
13378:
13389:Signed-off-by: C O Mitter <committer@example.com>
1339EOF
1340        test_cmp expected actual
1341'
1342
1343test_expect_success 'signoff: the same signoff NOT at the end' '
1344        append_signoff <<\EOF >actual &&
1345subject
1346
1347body
1348
1349Signed-off-by: C O Mitter <committer@example.com>
1350Signed-off-by: my@house
1351EOF
1352        cat >expected <<\EOF &&
13534:Subject: [PATCH] subject
13548:
135510:
135611:Signed-off-by: C O Mitter <committer@example.com>
135712:Signed-off-by: my@house
1358EOF
1359        test_cmp expected actual
1360'
1361
1362test_expect_success 'signoff: detect garbage in non-conforming footer' '
1363        append_signoff <<\EOF >actual &&
1364subject
1365
1366body
1367
1368Tested-by: my@house
1369Some Trash
1370Signed-off-by: C O Mitter <committer@example.com>
1371EOF
1372        cat >expected <<\EOF &&
13734:Subject: [PATCH] subject
13748:
137510:
137613:Signed-off-by: C O Mitter <committer@example.com>
137714:
137815:Signed-off-by: C O Mitter <committer@example.com>
1379EOF
1380        test_cmp expected actual
1381'
1382
1383test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1384        append_signoff <<\EOF >actual &&
1385subject
1386
1387body
1388
1389Reviewed-id: Noone
1390Tested-by: my@house
1391Change-id: Ideadbeef
1392Signed-off-by: C O Mitter <committer@example.com>
1393Bug: 1234
1394EOF
1395        cat >expected <<\EOF &&
13964:Subject: [PATCH] subject
13978:
139810:
139914:Signed-off-by: C O Mitter <committer@example.com>
1400EOF
1401        test_cmp expected actual
1402'
1403
1404test_expect_success 'format patch ignores color.ui' '
1405        test_unconfig color.ui &&
1406        git format-patch --stdout -1 >expect &&
1407        test_config color.ui always &&
1408        git format-patch --stdout -1 >actual &&
1409        test_cmp expect actual
1410'
1411
1412test_expect_success 'cover letter using branch description (1)' '
1413        git checkout rebuild-1 &&
1414        test_config branch.rebuild-1.description hello &&
1415        git format-patch --stdout --cover-letter master >actual &&
1416        grep hello actual >/dev/null
1417'
1418
1419test_expect_success 'cover letter using branch description (2)' '
1420        git checkout rebuild-1 &&
1421        test_config branch.rebuild-1.description hello &&
1422        git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1423        grep hello actual >/dev/null
1424'
1425
1426test_expect_success 'cover letter using branch description (3)' '
1427        git checkout rebuild-1 &&
1428        test_config branch.rebuild-1.description hello &&
1429        git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1430        grep hello actual >/dev/null
1431'
1432
1433test_expect_success 'cover letter using branch description (4)' '
1434        git checkout rebuild-1 &&
1435        test_config branch.rebuild-1.description hello &&
1436        git format-patch --stdout --cover-letter master.. >actual &&
1437        grep hello actual >/dev/null
1438'
1439
1440test_expect_success 'cover letter using branch description (5)' '
1441        git checkout rebuild-1 &&
1442        test_config branch.rebuild-1.description hello &&
1443        git format-patch --stdout --cover-letter -2 HEAD >actual &&
1444        grep hello actual >/dev/null
1445'
1446
1447test_expect_success 'cover letter using branch description (6)' '
1448        git checkout rebuild-1 &&
1449        test_config branch.rebuild-1.description hello &&
1450        git format-patch --stdout --cover-letter -2 >actual &&
1451        grep hello actual >/dev/null
1452'
1453
1454test_expect_success 'cover letter with nothing' '
1455        git format-patch --stdout --cover-letter >actual &&
1456        test_line_count = 0 actual
1457'
1458
1459test_expect_success 'cover letter auto' '
1460        mkdir -p tmp &&
1461        test_when_finished "rm -rf tmp;
1462                git config --unset format.coverletter" &&
1463
1464        git config format.coverletter auto &&
1465        git format-patch -o tmp -1 >list &&
1466        test_line_count = 1 list &&
1467        git format-patch -o tmp -2 >list &&
1468        test_line_count = 3 list
1469'
1470
1471test_expect_success 'cover letter auto user override' '
1472        mkdir -p tmp &&
1473        test_when_finished "rm -rf tmp;
1474                git config --unset format.coverletter" &&
1475
1476        git config format.coverletter auto &&
1477        git format-patch -o tmp --cover-letter -1 >list &&
1478        test_line_count = 2 list &&
1479        git format-patch -o tmp --cover-letter -2 >list &&
1480        test_line_count = 3 list &&
1481        git format-patch -o tmp --no-cover-letter -1 >list &&
1482        test_line_count = 1 list &&
1483        git format-patch -o tmp --no-cover-letter -2 >list &&
1484        test_line_count = 2 list
1485'
1486
1487test_expect_success 'format-patch --zero-commit' '
1488        git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1489        grep "^From " patch2 | sort | uniq >actual &&
1490        echo "From $_z40 Mon Sep 17 00:00:00 2001" >expect &&
1491        test_cmp expect actual
1492'
1493
1494test_expect_success 'From line has expected format' '
1495        git format-patch --stdout v2..v1 >patch2 &&
1496        grep "^From " patch2 >from &&
1497        grep "^From $_x40 Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1498        test_cmp from filtered
1499'
1500
1501test_expect_success 'format-patch format.outputDirectory option' '
1502        test_config format.outputDirectory patches &&
1503        rm -fr patches &&
1504        git format-patch master..side &&
1505        test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
1506'
1507
1508test_expect_success 'format-patch -o overrides format.outputDirectory' '
1509        test_config format.outputDirectory patches &&
1510        rm -fr patches patchset &&
1511        git format-patch master..side -o patchset &&
1512        test_path_is_missing patches &&
1513        test_path_is_dir patchset
1514'
1515
1516test_expect_success 'format-patch --base' '
1517        git checkout side &&
1518        git format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual &&
1519        echo >expected &&
1520        echo "base-commit: $(git rev-parse HEAD~3)" >>expected &&
1521        echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1522        echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1523        signature >> expected &&
1524        test_cmp expected actual
1525'
1526
1527test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1528        test_must_fail git format-patch --base=HEAD -2 &&
1529        test_must_fail git format-patch --base=HEAD~1 -2 &&
1530        git format-patch --stdout --base=HEAD~2 -2 >patch &&
1531        grep "^base-commit:" patch >actual &&
1532        echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
1533        test_cmp expected actual
1534'
1535
1536test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1537        # For history as below:
1538        #
1539        #    ---Q---P---Z---Y---*---X
1540        #        \             /
1541        #         ------------W
1542        #
1543        # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1544        git checkout -b topic1 master &&
1545        git rev-parse HEAD >commit-id-base &&
1546        test_commit P &&
1547        git rev-parse HEAD >commit-id-P &&
1548        test_commit Z &&
1549        git rev-parse HEAD >commit-id-Z &&
1550        test_commit Y &&
1551        git checkout -b topic2 master &&
1552        test_commit W &&
1553        git merge topic1 &&
1554        test_commit X &&
1555        test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1556        test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1557        git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1558        grep "^base-commit:" patch >actual &&
1559        echo "base-commit: $(cat commit-id-base)" >expected &&
1560        test_cmp expected actual
1561'
1562
1563test_expect_success 'format-patch --base=auto' '
1564        git checkout -b upstream master &&
1565        git checkout -b local upstream &&
1566        git branch --set-upstream-to=upstream &&
1567        test_commit N1 &&
1568        test_commit N2 &&
1569        git format-patch --stdout --base=auto -2 >patch &&
1570        grep "^base-commit:" patch >actual &&
1571        echo "base-commit: $(git rev-parse upstream)" >expected &&
1572        test_cmp expected actual
1573'
1574
1575test_expect_success 'format-patch errors out when history involves criss-cross' '
1576        # setup criss-cross history
1577        #
1578        #   B---M1---D
1579        #  / \ /
1580        # A   X
1581        #  \ / \
1582        #   C---M2---E
1583        #
1584        git checkout master &&
1585        test_commit A &&
1586        git checkout -b xb master &&
1587        test_commit B &&
1588        git checkout -b xc master &&
1589        test_commit C &&
1590        git checkout -b xbc xb -- &&
1591        git merge xc &&
1592        git checkout -b xcb xc -- &&
1593        git branch --set-upstream-to=xbc &&
1594        git merge xb &&
1595        git checkout xbc &&
1596        test_commit D &&
1597        git checkout xcb &&
1598        test_commit E &&
1599        test_must_fail  git format-patch --base=auto -1
1600'
1601
1602test_expect_success 'format-patch format.useAutoBaseoption' '
1603        test_when_finished "git config --unset format.useAutoBase" &&
1604        git checkout local &&
1605        git config format.useAutoBase true &&
1606        git format-patch --stdout -1 >patch &&
1607        grep "^base-commit:" patch >actual &&
1608        echo "base-commit: $(git rev-parse upstream)" >expected &&
1609        test_cmp expected actual
1610'
1611
1612test_expect_success 'format-patch --base overrides format.useAutoBase' '
1613        test_when_finished "git config --unset format.useAutoBase" &&
1614        git config format.useAutoBase true &&
1615        git format-patch --stdout --base=HEAD~1 -1 >patch &&
1616        grep "^base-commit:" patch >actual &&
1617        echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
1618        test_cmp expected actual
1619'
1620
1621test_expect_success 'format-patch --base with --attach' '
1622        git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
1623        sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
1624                patch >actual &&
1625        test_write_lines 1 2 >expect &&
1626        test_cmp expect actual
1627'
1628
1629test_expect_success 'format-patch --pretty=mboxrd' '
1630        sp=" " &&
1631        cat >msg <<-INPUT_END &&
1632        mboxrd should escape the body
1633
1634        From could trip up a loose mbox parser
1635        >From extra escape for reversibility
1636        >>From extra escape for reversibility 2
1637        from lower case not escaped
1638        Fromm bad speling not escaped
1639         From with leading space not escaped
1640
1641        F
1642        From
1643        From$sp
1644        From    $sp
1645        From    $sp
1646        INPUT_END
1647
1648        cat >expect <<-INPUT_END &&
1649        >From could trip up a loose mbox parser
1650        >>From extra escape for reversibility
1651        >>>From extra escape for reversibility 2
1652        from lower case not escaped
1653        Fromm bad speling not escaped
1654         From with leading space not escaped
1655
1656        F
1657        From
1658        From
1659        From
1660        From
1661        INPUT_END
1662
1663        C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
1664        git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
1665        git grep -h --no-index -A11 \
1666                "^>From could trip up a loose mbox parser" patch >actual &&
1667        test_cmp expect actual
1668'
1669
1670test_done