t / t4014-format-patch.shon commit Merge branch 'po/fix-doc-merge-base-illustration' (4abeeb6)
   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 '--rfc' '
1090        cat >expect <<-\EOF &&
1091        Subject: [RFC PATCH 1/1] header with . in it
1092        EOF
1093        git format-patch -n -1 --stdout --rfc >patch &&
1094        grep ^Subject: patch >actual &&
1095        test_cmp expect actual
1096'
1097
1098test_expect_success '--from=ident notices bogus ident' '
1099        test_must_fail git format-patch -1 --stdout --from=foo >patch
1100'
1101
1102test_expect_success '--from=ident replaces author' '
1103        git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1104        cat >expect <<-\EOF &&
1105        From: Me <me@example.com>
1106
1107        From: A U Thor <author@example.com>
1108
1109        EOF
1110        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1111        test_cmp expect patch.head
1112'
1113
1114test_expect_success '--from uses committer ident' '
1115        git format-patch -1 --stdout --from >patch &&
1116        cat >expect <<-\EOF &&
1117        From: C O Mitter <committer@example.com>
1118
1119        From: A U Thor <author@example.com>
1120
1121        EOF
1122        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1123        test_cmp expect patch.head
1124'
1125
1126test_expect_success '--from omits redundant in-body header' '
1127        git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1128        cat >expect <<-\EOF &&
1129        From: A U Thor <author@example.com>
1130
1131        EOF
1132        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1133        test_cmp expect patch.head
1134'
1135
1136test_expect_success 'in-body headers trigger content encoding' '
1137        test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1138        test_when_finished "git reset --hard HEAD^" &&
1139        git format-patch -1 --stdout --from >patch &&
1140        cat >expect <<-\EOF &&
1141        From: C O Mitter <committer@example.com>
1142        Content-Type: text/plain; charset=UTF-8
1143
1144        From: éxötìc <author@example.com>
1145
1146        EOF
1147        sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1148        test_cmp expect patch.head
1149'
1150
1151append_signoff()
1152{
1153        C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1154        git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1155        sed -n -e "1,/^---$/p" append_signoff.patch |
1156                egrep -n "^Subject|Sign|^$"
1157}
1158
1159test_expect_success 'signoff: commit with no body' '
1160        append_signoff </dev/null >actual &&
1161        cat <<\EOF | sed "s/EOL$//" >expected &&
11624:Subject: [PATCH] EOL
11638:
11649:Signed-off-by: C O Mitter <committer@example.com>
1165EOF
1166        test_cmp expected actual
1167'
1168
1169test_expect_success 'signoff: commit with only subject' '
1170        echo subject | append_signoff >actual &&
1171        cat >expected <<\EOF &&
11724:Subject: [PATCH] subject
11738:
11749:Signed-off-by: C O Mitter <committer@example.com>
1175EOF
1176        test_cmp expected actual
1177'
1178
1179test_expect_success 'signoff: commit with only subject that does not end with NL' '
1180        printf subject | append_signoff >actual &&
1181        cat >expected <<\EOF &&
11824:Subject: [PATCH] subject
11838:
11849:Signed-off-by: C O Mitter <committer@example.com>
1185EOF
1186        test_cmp expected actual
1187'
1188
1189test_expect_success 'signoff: no existing signoffs' '
1190        append_signoff <<\EOF >actual &&
1191subject
1192
1193body
1194EOF
1195        cat >expected <<\EOF &&
11964:Subject: [PATCH] subject
11978:
119810:
119911:Signed-off-by: C O Mitter <committer@example.com>
1200EOF
1201        test_cmp expected actual
1202'
1203
1204test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1205        printf "subject\n\nbody" | append_signoff >actual &&
1206        cat >expected <<\EOF &&
12074:Subject: [PATCH] subject
12088:
120910:
121011:Signed-off-by: C O Mitter <committer@example.com>
1211EOF
1212        test_cmp expected actual
1213'
1214
1215test_expect_success 'signoff: some random signoff' '
1216        append_signoff <<\EOF >actual &&
1217subject
1218
1219body
1220
1221Signed-off-by: my@house
1222EOF
1223        cat >expected <<\EOF &&
12244:Subject: [PATCH] subject
12258:
122610:
122711:Signed-off-by: my@house
122812:Signed-off-by: C O Mitter <committer@example.com>
1229EOF
1230        test_cmp expected actual
1231'
1232
1233test_expect_success 'signoff: misc conforming footer elements' '
1234        append_signoff <<\EOF >actual &&
1235subject
1236
1237body
1238
1239Signed-off-by: my@house
1240(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1241Tested-by: Some One <someone@example.com>
1242Bug: 1234
1243EOF
1244        cat >expected <<\EOF &&
12454:Subject: [PATCH] subject
12468:
124710:
124811:Signed-off-by: my@house
124915:Signed-off-by: C O Mitter <committer@example.com>
1250EOF
1251        test_cmp expected actual
1252'
1253
1254test_expect_success 'signoff: some random signoff-alike' '
1255        append_signoff <<\EOF >actual &&
1256subject
1257
1258body
1259Fooled-by-me: my@house
1260EOF
1261        cat >expected <<\EOF &&
12624:Subject: [PATCH] subject
12638:
126411:
126512:Signed-off-by: C O Mitter <committer@example.com>
1266EOF
1267        test_cmp expected actual
1268'
1269
1270test_expect_success 'signoff: not really a signoff' '
1271        append_signoff <<\EOF >actual &&
1272subject
1273
1274I want to mention about Signed-off-by: here.
1275EOF
1276        cat >expected <<\EOF &&
12774:Subject: [PATCH] subject
12788:
12799:I want to mention about Signed-off-by: here.
128010:
128111:Signed-off-by: C O Mitter <committer@example.com>
1282EOF
1283        test_cmp expected actual
1284'
1285
1286test_expect_success 'signoff: not really a signoff (2)' '
1287        append_signoff <<\EOF >actual &&
1288subject
1289
1290My unfortunate
1291Signed-off-by: example happens to be wrapped here.
1292EOF
1293        cat >expected <<\EOF &&
12944:Subject: [PATCH] subject
12958:
129610:Signed-off-by: example happens to be wrapped here.
129711:
129812:Signed-off-by: C O Mitter <committer@example.com>
1299EOF
1300        test_cmp expected actual
1301'
1302
1303test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1304        append_signoff <<\EOF >actual &&
1305subject
1306
1307Signed-off-by: my@house
1308Signed-off-by: your@house
1309
1310A lot of houses.
1311EOF
1312        cat >expected <<\EOF &&
13134:Subject: [PATCH] subject
13148:
13159:Signed-off-by: my@house
131610:Signed-off-by: your@house
131711:
131813:
131914:Signed-off-by: C O Mitter <committer@example.com>
1320EOF
1321        test_cmp expected actual
1322'
1323
1324test_expect_success 'signoff: the same signoff at the end' '
1325        append_signoff <<\EOF >actual &&
1326subject
1327
1328body
1329
1330Signed-off-by: C O Mitter <committer@example.com>
1331EOF
1332        cat >expected <<\EOF &&
13334:Subject: [PATCH] subject
13348:
133510:
133611:Signed-off-by: C O Mitter <committer@example.com>
1337EOF
1338        test_cmp expected actual
1339'
1340
1341test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1342        printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1343                append_signoff >actual &&
1344        cat >expected <<\EOF &&
13454:Subject: [PATCH] subject
13468:
13479:Signed-off-by: C O Mitter <committer@example.com>
1348EOF
1349        test_cmp expected actual
1350'
1351
1352test_expect_success 'signoff: the same signoff NOT at the end' '
1353        append_signoff <<\EOF >actual &&
1354subject
1355
1356body
1357
1358Signed-off-by: C O Mitter <committer@example.com>
1359Signed-off-by: my@house
1360EOF
1361        cat >expected <<\EOF &&
13624:Subject: [PATCH] subject
13638:
136410:
136511:Signed-off-by: C O Mitter <committer@example.com>
136612:Signed-off-by: my@house
1367EOF
1368        test_cmp expected actual
1369'
1370
1371test_expect_success 'signoff: detect garbage in non-conforming footer' '
1372        append_signoff <<\EOF >actual &&
1373subject
1374
1375body
1376
1377Tested-by: my@house
1378Some Trash
1379Signed-off-by: C O Mitter <committer@example.com>
1380EOF
1381        cat >expected <<\EOF &&
13824:Subject: [PATCH] subject
13838:
138410:
138513:Signed-off-by: C O Mitter <committer@example.com>
138614:
138715:Signed-off-by: C O Mitter <committer@example.com>
1388EOF
1389        test_cmp expected actual
1390'
1391
1392test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1393        append_signoff <<\EOF >actual &&
1394subject
1395
1396body
1397
1398Reviewed-id: Noone
1399Tested-by: my@house
1400Change-id: Ideadbeef
1401Signed-off-by: C O Mitter <committer@example.com>
1402Bug: 1234
1403EOF
1404        cat >expected <<\EOF &&
14054:Subject: [PATCH] subject
14068:
140710:
140814:Signed-off-by: C O Mitter <committer@example.com>
1409EOF
1410        test_cmp expected actual
1411'
1412
1413test_expect_success 'format patch ignores color.ui' '
1414        test_unconfig color.ui &&
1415        git format-patch --stdout -1 >expect &&
1416        test_config color.ui always &&
1417        git format-patch --stdout -1 >actual &&
1418        test_cmp expect actual
1419'
1420
1421test_expect_success 'cover letter using branch description (1)' '
1422        git checkout rebuild-1 &&
1423        test_config branch.rebuild-1.description hello &&
1424        git format-patch --stdout --cover-letter master >actual &&
1425        grep hello actual >/dev/null
1426'
1427
1428test_expect_success 'cover letter using branch description (2)' '
1429        git checkout rebuild-1 &&
1430        test_config branch.rebuild-1.description hello &&
1431        git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1432        grep hello actual >/dev/null
1433'
1434
1435test_expect_success 'cover letter using branch description (3)' '
1436        git checkout rebuild-1 &&
1437        test_config branch.rebuild-1.description hello &&
1438        git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1439        grep hello actual >/dev/null
1440'
1441
1442test_expect_success 'cover letter using branch description (4)' '
1443        git checkout rebuild-1 &&
1444        test_config branch.rebuild-1.description hello &&
1445        git format-patch --stdout --cover-letter master.. >actual &&
1446        grep hello actual >/dev/null
1447'
1448
1449test_expect_success 'cover letter using branch description (5)' '
1450        git checkout rebuild-1 &&
1451        test_config branch.rebuild-1.description hello &&
1452        git format-patch --stdout --cover-letter -2 HEAD >actual &&
1453        grep hello actual >/dev/null
1454'
1455
1456test_expect_success 'cover letter using branch description (6)' '
1457        git checkout rebuild-1 &&
1458        test_config branch.rebuild-1.description hello &&
1459        git format-patch --stdout --cover-letter -2 >actual &&
1460        grep hello actual >/dev/null
1461'
1462
1463test_expect_success 'cover letter with nothing' '
1464        git format-patch --stdout --cover-letter >actual &&
1465        test_line_count = 0 actual
1466'
1467
1468test_expect_success 'cover letter auto' '
1469        mkdir -p tmp &&
1470        test_when_finished "rm -rf tmp;
1471                git config --unset format.coverletter" &&
1472
1473        git config format.coverletter auto &&
1474        git format-patch -o tmp -1 >list &&
1475        test_line_count = 1 list &&
1476        git format-patch -o tmp -2 >list &&
1477        test_line_count = 3 list
1478'
1479
1480test_expect_success 'cover letter auto user override' '
1481        mkdir -p tmp &&
1482        test_when_finished "rm -rf tmp;
1483                git config --unset format.coverletter" &&
1484
1485        git config format.coverletter auto &&
1486        git format-patch -o tmp --cover-letter -1 >list &&
1487        test_line_count = 2 list &&
1488        git format-patch -o tmp --cover-letter -2 >list &&
1489        test_line_count = 3 list &&
1490        git format-patch -o tmp --no-cover-letter -1 >list &&
1491        test_line_count = 1 list &&
1492        git format-patch -o tmp --no-cover-letter -2 >list &&
1493        test_line_count = 2 list
1494'
1495
1496test_expect_success 'format-patch --zero-commit' '
1497        git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1498        grep "^From " patch2 | sort | uniq >actual &&
1499        echo "From $_z40 Mon Sep 17 00:00:00 2001" >expect &&
1500        test_cmp expect actual
1501'
1502
1503test_expect_success 'From line has expected format' '
1504        git format-patch --stdout v2..v1 >patch2 &&
1505        grep "^From " patch2 >from &&
1506        grep "^From $_x40 Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1507        test_cmp from filtered
1508'
1509
1510test_expect_success 'format-patch format.outputDirectory option' '
1511        test_config format.outputDirectory patches &&
1512        rm -fr patches &&
1513        git format-patch master..side &&
1514        test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
1515'
1516
1517test_expect_success 'format-patch -o overrides format.outputDirectory' '
1518        test_config format.outputDirectory patches &&
1519        rm -fr patches patchset &&
1520        git format-patch master..side -o patchset &&
1521        test_path_is_missing patches &&
1522        test_path_is_dir patchset
1523'
1524
1525test_expect_success 'format-patch --base' '
1526        git checkout side &&
1527        git format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual &&
1528        echo >expected &&
1529        echo "base-commit: $(git rev-parse HEAD~3)" >>expected &&
1530        echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1531        echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1532        signature >> expected &&
1533        test_cmp expected actual
1534'
1535
1536test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1537        test_must_fail git format-patch --base=HEAD -2 &&
1538        test_must_fail git format-patch --base=HEAD~1 -2 &&
1539        git format-patch --stdout --base=HEAD~2 -2 >patch &&
1540        grep "^base-commit:" patch >actual &&
1541        echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
1542        test_cmp expected actual
1543'
1544
1545test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1546        # For history as below:
1547        #
1548        #    ---Q---P---Z---Y---*---X
1549        #        \             /
1550        #         ------------W
1551        #
1552        # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1553        git checkout -b topic1 master &&
1554        git rev-parse HEAD >commit-id-base &&
1555        test_commit P &&
1556        git rev-parse HEAD >commit-id-P &&
1557        test_commit Z &&
1558        git rev-parse HEAD >commit-id-Z &&
1559        test_commit Y &&
1560        git checkout -b topic2 master &&
1561        test_commit W &&
1562        git merge topic1 &&
1563        test_commit X &&
1564        test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1565        test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1566        git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1567        grep "^base-commit:" patch >actual &&
1568        echo "base-commit: $(cat commit-id-base)" >expected &&
1569        test_cmp expected actual
1570'
1571
1572test_expect_success 'format-patch --base=auto' '
1573        git checkout -b upstream master &&
1574        git checkout -b local upstream &&
1575        git branch --set-upstream-to=upstream &&
1576        test_commit N1 &&
1577        test_commit N2 &&
1578        git format-patch --stdout --base=auto -2 >patch &&
1579        grep "^base-commit:" patch >actual &&
1580        echo "base-commit: $(git rev-parse upstream)" >expected &&
1581        test_cmp expected actual
1582'
1583
1584test_expect_success 'format-patch errors out when history involves criss-cross' '
1585        # setup criss-cross history
1586        #
1587        #   B---M1---D
1588        #  / \ /
1589        # A   X
1590        #  \ / \
1591        #   C---M2---E
1592        #
1593        git checkout master &&
1594        test_commit A &&
1595        git checkout -b xb master &&
1596        test_commit B &&
1597        git checkout -b xc master &&
1598        test_commit C &&
1599        git checkout -b xbc xb -- &&
1600        git merge xc &&
1601        git checkout -b xcb xc -- &&
1602        git branch --set-upstream-to=xbc &&
1603        git merge xb &&
1604        git checkout xbc &&
1605        test_commit D &&
1606        git checkout xcb &&
1607        test_commit E &&
1608        test_must_fail  git format-patch --base=auto -1
1609'
1610
1611test_expect_success 'format-patch format.useAutoBaseoption' '
1612        test_when_finished "git config --unset format.useAutoBase" &&
1613        git checkout local &&
1614        git config format.useAutoBase true &&
1615        git format-patch --stdout -1 >patch &&
1616        grep "^base-commit:" patch >actual &&
1617        echo "base-commit: $(git rev-parse upstream)" >expected &&
1618        test_cmp expected actual
1619'
1620
1621test_expect_success 'format-patch --base overrides format.useAutoBase' '
1622        test_when_finished "git config --unset format.useAutoBase" &&
1623        git config format.useAutoBase true &&
1624        git format-patch --stdout --base=HEAD~1 -1 >patch &&
1625        grep "^base-commit:" patch >actual &&
1626        echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
1627        test_cmp expected actual
1628'
1629
1630test_expect_success 'format-patch --base with --attach' '
1631        git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
1632        sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
1633                patch >actual &&
1634        test_write_lines 1 2 >expect &&
1635        test_cmp expect actual
1636'
1637
1638test_expect_success 'format-patch --pretty=mboxrd' '
1639        sp=" " &&
1640        cat >msg <<-INPUT_END &&
1641        mboxrd should escape the body
1642
1643        From could trip up a loose mbox parser
1644        >From extra escape for reversibility
1645        >>From extra escape for reversibility 2
1646        from lower case not escaped
1647        Fromm bad speling not escaped
1648         From with leading space not escaped
1649
1650        F
1651        From
1652        From$sp
1653        From    $sp
1654        From    $sp
1655        INPUT_END
1656
1657        cat >expect <<-INPUT_END &&
1658        >From could trip up a loose mbox parser
1659        >>From extra escape for reversibility
1660        >>>From extra escape for reversibility 2
1661        from lower case not escaped
1662        Fromm bad speling not escaped
1663         From with leading space not escaped
1664
1665        F
1666        From
1667        From
1668        From
1669        From
1670        INPUT_END
1671
1672        C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
1673        git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
1674        git grep -h --no-index -A11 \
1675                "^>From could trip up a loose mbox parser" patch >actual &&
1676        test_cmp expect actual
1677'
1678
1679test_done