t / t4014-format-patch.shon commit revision: new rev^-n shorthand for rev^n..rev (8779351)
   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
 757test_expect_success 'format-patch --signature' '
 758        git format-patch --stdout --signature="my sig" -1 >output &&
 759        grep "my sig" output
 760'
 761
 762test_expect_success 'format-patch with format.signature config' '
 763        git config format.signature "config sig" &&
 764        git format-patch --stdout -1 >output &&
 765        grep "config sig" output
 766'
 767
 768test_expect_success 'format-patch --signature overrides format.signature' '
 769        git config format.signature "config sig" &&
 770        git format-patch --stdout --signature="overrides" -1 >output &&
 771        ! grep "config sig" output &&
 772        grep "overrides" output
 773'
 774
 775test_expect_success 'format-patch --no-signature ignores format.signature' '
 776        git config format.signature "config sig" &&
 777        git format-patch --stdout --signature="my sig" --no-signature \
 778                -1 >output &&
 779        check_patch output &&
 780        ! grep "config sig" output &&
 781        ! grep "my sig" output &&
 782        ! grep "^-- \$" output
 783'
 784
 785test_expect_success 'format-patch --signature --cover-letter' '
 786        git config --unset-all format.signature &&
 787        git format-patch --stdout --signature="my sig" --cover-letter \
 788                -1 >output &&
 789        grep "my sig" output &&
 790        test 2 = $(grep "my sig" output | wc -l)
 791'
 792
 793test_expect_success 'format.signature="" suppresses signatures' '
 794        git config format.signature "" &&
 795        git format-patch --stdout -1 >output &&
 796        check_patch output &&
 797        ! grep "^-- \$" output
 798'
 799
 800test_expect_success 'format-patch --no-signature suppresses signatures' '
 801        git config --unset-all format.signature &&
 802        git format-patch --stdout --no-signature -1 >output &&
 803        check_patch output &&
 804        ! grep "^-- \$" output
 805'
 806
 807test_expect_success 'format-patch --signature="" suppresses signatures' '
 808        git format-patch --stdout --signature="" -1 >output &&
 809        check_patch output &&
 810        ! grep "^-- \$" output
 811'
 812
 813test_expect_success 'prepare mail-signature input' '
 814        cat >mail-signature <<-\EOF
 815
 816        Test User <test.email@kernel.org>
 817        http://git.kernel.org/cgit/git/git.git
 818
 819        git.kernel.org/?p=git/git.git;a=summary
 820
 821        EOF
 822'
 823
 824test_expect_success '--signature-file=file works' '
 825        git format-patch --stdout --signature-file=mail-signature -1 >output &&
 826        check_patch output &&
 827        sed -e "1,/^-- \$/d" <output >actual &&
 828        {
 829                cat mail-signature && echo
 830        } >expect &&
 831        test_cmp expect actual
 832'
 833
 834test_expect_success 'format.signaturefile works' '
 835        test_config format.signaturefile mail-signature &&
 836        git format-patch --stdout -1 >output &&
 837        check_patch output &&
 838        sed -e "1,/^-- \$/d" <output >actual &&
 839        {
 840                cat mail-signature && echo
 841        } >expect &&
 842        test_cmp expect actual
 843'
 844
 845test_expect_success '--no-signature suppresses format.signaturefile ' '
 846        test_config format.signaturefile mail-signature &&
 847        git format-patch --stdout --no-signature -1 >output &&
 848        check_patch output &&
 849        ! grep "^-- \$" output
 850'
 851
 852test_expect_success '--signature-file overrides format.signaturefile' '
 853        cat >other-mail-signature <<-\EOF &&
 854        Use this other signature instead of mail-signature.
 855        EOF
 856        test_config format.signaturefile mail-signature &&
 857        git format-patch --stdout \
 858                        --signature-file=other-mail-signature -1 >output &&
 859        check_patch output &&
 860        sed -e "1,/^-- \$/d" <output >actual &&
 861        {
 862                cat other-mail-signature && echo
 863        } >expect &&
 864        test_cmp expect actual
 865'
 866
 867test_expect_success '--signature overrides format.signaturefile' '
 868        test_config format.signaturefile mail-signature &&
 869        git format-patch --stdout --signature="my sig" -1 >output &&
 870        check_patch output &&
 871        grep "my sig" output
 872'
 873
 874test_expect_success TTY 'format-patch --stdout paginates' '
 875        rm -f pager_used &&
 876        test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
 877        test_path_is_file pager_used
 878'
 879
 880 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
 881        rm -f pager_used &&
 882        test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
 883        test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
 884        test_path_is_missing pager_used &&
 885        test_path_is_missing .git/pager_used
 886'
 887
 888test_expect_success 'format-patch handles multi-line subjects' '
 889        rm -rf patches/ &&
 890        echo content >>file &&
 891        for i in one two three; do echo $i; done >msg &&
 892        git add file &&
 893        git commit -F msg &&
 894        git format-patch -o patches -1 &&
 895        grep ^Subject: patches/0001-one.patch >actual &&
 896        echo "Subject: [PATCH] one two three" >expect &&
 897        test_cmp expect actual
 898'
 899
 900test_expect_success 'format-patch handles multi-line encoded subjects' '
 901        rm -rf patches/ &&
 902        echo content >>file &&
 903        for i in en två tre; do echo $i; done >msg &&
 904        git add file &&
 905        git commit -F msg &&
 906        git format-patch -o patches -1 &&
 907        grep ^Subject: patches/0001-en.patch >actual &&
 908        echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
 909        test_cmp expect actual
 910'
 911
 912M8="foo bar "
 913M64=$M8$M8$M8$M8$M8$M8$M8$M8
 914M512=$M64$M64$M64$M64$M64$M64$M64$M64
 915cat >expect <<'EOF'
 916Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 917 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 918 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 919 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 920 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 921 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 922 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 923EOF
 924test_expect_success 'format-patch wraps extremely long subject (ascii)' '
 925        echo content >>file &&
 926        git add file &&
 927        git commit -m "$M512" &&
 928        git format-patch --stdout -1 >patch &&
 929        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 930        test_cmp expect subject
 931'
 932
 933M8="föö bar "
 934M64=$M8$M8$M8$M8$M8$M8$M8$M8
 935M512=$M64$M64$M64$M64$M64$M64$M64$M64
 936cat >expect <<'EOF'
 937Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 938 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 939 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 940 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 941 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 942 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 943 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 944 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 945 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 946 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 947 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 948 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 949 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 950 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 951 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 952 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 953 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 954 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 955 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 956 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 957 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 958 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 959 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 960 =?UTF-8?q?bar?=
 961EOF
 962test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
 963        rm -rf patches/ &&
 964        echo content >>file &&
 965        git add file &&
 966        git commit -m "$M512" &&
 967        git format-patch --stdout -1 >patch &&
 968        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 969        test_cmp expect subject
 970'
 971
 972check_author() {
 973        echo content >>file &&
 974        git add file &&
 975        GIT_AUTHOR_NAME=$1 git commit -m author-check &&
 976        git format-patch --stdout -1 >patch &&
 977        sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
 978        test_cmp expect actual
 979}
 980
 981cat >expect <<'EOF'
 982From: "Foo B. Bar" <author@example.com>
 983EOF
 984test_expect_success 'format-patch quotes dot in from-headers' '
 985        check_author "Foo B. Bar"
 986'
 987
 988cat >expect <<'EOF'
 989From: "Foo \"The Baz\" Bar" <author@example.com>
 990EOF
 991test_expect_success 'format-patch quotes double-quote in from-headers' '
 992        check_author "Foo \"The Baz\" Bar"
 993'
 994
 995cat >expect <<'EOF'
 996From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
 997EOF
 998test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
 999        check_author "Föo Bar"
1000'
1001
1002cat >expect <<'EOF'
1003From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1004EOF
1005test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1006        check_author "Föo B. Bar"
1007'
1008
1009cat >expect <<EOF
1010From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1011 <author@example.com>
1012EOF
1013test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1014        check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1015'
1016
1017cat >expect <<'EOF'
1018From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1019 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1020 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1021EOF
1022test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1023        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"
1024'
1025
1026cat >expect <<'EOF'
1027From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1028 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1029 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1030EOF
1031test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1032        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"
1033'
1034
1035cat >expect <<'EOF'
1036From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1037 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1038 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1039 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1040 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1041EOF
1042test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1043        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"
1044'
1045
1046cat >expect <<'EOF'
1047Subject: header with . in it
1048EOF
1049test_expect_success 'subject lines do not have 822 atom-quoting' '
1050        echo content >>file &&
1051        git add file &&
1052        git commit -m "header with . in it" &&
1053        git format-patch -k -1 --stdout >patch &&
1054        grep ^Subject: patch >actual &&
1055        test_cmp expect actual
1056'
1057
1058cat >expect <<'EOF'
1059Subject: [PREFIX 1/1] header with . in it
1060EOF
1061test_expect_success 'subject prefixes have space prepended' '
1062        git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1063        grep ^Subject: patch >actual &&
1064        test_cmp expect actual
1065'
1066
1067cat >expect <<'EOF'
1068Subject: [1/1] header with . in it
1069EOF
1070test_expect_success 'empty subject prefix does not have extra space' '
1071        git format-patch -n -1 --stdout --subject-prefix= >patch &&
1072        grep ^Subject: patch >actual &&
1073        test_cmp expect actual
1074'
1075
1076test_expect_success '--from=ident notices bogus ident' '
1077        test_must_fail git format-patch -1 --stdout --from=foo >patch
1078'
1079
1080test_expect_success '--from=ident replaces author' '
1081        git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1082        cat >expect <<-\EOF &&
1083        From: Me <me@example.com>
1084
1085        From: A U Thor <author@example.com>
1086
1087        EOF
1088        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1089        test_cmp expect patch.head
1090'
1091
1092test_expect_success '--from uses committer ident' '
1093        git format-patch -1 --stdout --from >patch &&
1094        cat >expect <<-\EOF &&
1095        From: C O Mitter <committer@example.com>
1096
1097        From: A U Thor <author@example.com>
1098
1099        EOF
1100        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1101        test_cmp expect patch.head
1102'
1103
1104test_expect_success '--from omits redundant in-body header' '
1105        git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1106        cat >expect <<-\EOF &&
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 'in-body headers trigger content encoding' '
1115        test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1116        test_when_finished "git reset --hard HEAD^" &&
1117        git format-patch -1 --stdout --from >patch &&
1118        cat >expect <<-\EOF &&
1119        From: C O Mitter <committer@example.com>
1120        Content-Type: text/plain; charset=UTF-8
1121
1122        From: éxötìc <author@example.com>
1123
1124        EOF
1125        sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1126        test_cmp expect patch.head
1127'
1128
1129append_signoff()
1130{
1131        C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1132        git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1133        sed -n -e "1,/^---$/p" append_signoff.patch |
1134                egrep -n "^Subject|Sign|^$"
1135}
1136
1137test_expect_success 'signoff: commit with no body' '
1138        append_signoff </dev/null >actual &&
1139        cat <<\EOF | sed "s/EOL$//" >expected &&
11404:Subject: [PATCH] EOL
11418:
11429:Signed-off-by: C O Mitter <committer@example.com>
1143EOF
1144        test_cmp expected actual
1145'
1146
1147test_expect_success 'signoff: commit with only subject' '
1148        echo subject | append_signoff >actual &&
1149        cat >expected <<\EOF &&
11504:Subject: [PATCH] subject
11518:
11529:Signed-off-by: C O Mitter <committer@example.com>
1153EOF
1154        test_cmp expected actual
1155'
1156
1157test_expect_success 'signoff: commit with only subject that does not end with NL' '
1158        printf subject | append_signoff >actual &&
1159        cat >expected <<\EOF &&
11604:Subject: [PATCH] subject
11618:
11629:Signed-off-by: C O Mitter <committer@example.com>
1163EOF
1164        test_cmp expected actual
1165'
1166
1167test_expect_success 'signoff: no existing signoffs' '
1168        append_signoff <<\EOF >actual &&
1169subject
1170
1171body
1172EOF
1173        cat >expected <<\EOF &&
11744:Subject: [PATCH] subject
11758:
117610:
117711:Signed-off-by: C O Mitter <committer@example.com>
1178EOF
1179        test_cmp expected actual
1180'
1181
1182test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1183        printf "subject\n\nbody" | append_signoff >actual &&
1184        cat >expected <<\EOF &&
11854:Subject: [PATCH] subject
11868:
118710:
118811:Signed-off-by: C O Mitter <committer@example.com>
1189EOF
1190        test_cmp expected actual
1191'
1192
1193test_expect_success 'signoff: some random signoff' '
1194        append_signoff <<\EOF >actual &&
1195subject
1196
1197body
1198
1199Signed-off-by: my@house
1200EOF
1201        cat >expected <<\EOF &&
12024:Subject: [PATCH] subject
12038:
120410:
120511:Signed-off-by: my@house
120612:Signed-off-by: C O Mitter <committer@example.com>
1207EOF
1208        test_cmp expected actual
1209'
1210
1211test_expect_success 'signoff: misc conforming footer elements' '
1212        append_signoff <<\EOF >actual &&
1213subject
1214
1215body
1216
1217Signed-off-by: my@house
1218(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1219Tested-by: Some One <someone@example.com>
1220Bug: 1234
1221EOF
1222        cat >expected <<\EOF &&
12234:Subject: [PATCH] subject
12248:
122510:
122611:Signed-off-by: my@house
122715:Signed-off-by: C O Mitter <committer@example.com>
1228EOF
1229        test_cmp expected actual
1230'
1231
1232test_expect_success 'signoff: some random signoff-alike' '
1233        append_signoff <<\EOF >actual &&
1234subject
1235
1236body
1237Fooled-by-me: my@house
1238EOF
1239        cat >expected <<\EOF &&
12404:Subject: [PATCH] subject
12418:
124211:
124312:Signed-off-by: C O Mitter <committer@example.com>
1244EOF
1245        test_cmp expected actual
1246'
1247
1248test_expect_success 'signoff: not really a signoff' '
1249        append_signoff <<\EOF >actual &&
1250subject
1251
1252I want to mention about Signed-off-by: here.
1253EOF
1254        cat >expected <<\EOF &&
12554:Subject: [PATCH] subject
12568:
12579:I want to mention about Signed-off-by: here.
125810:
125911:Signed-off-by: C O Mitter <committer@example.com>
1260EOF
1261        test_cmp expected actual
1262'
1263
1264test_expect_success 'signoff: not really a signoff (2)' '
1265        append_signoff <<\EOF >actual &&
1266subject
1267
1268My unfortunate
1269Signed-off-by: example happens to be wrapped here.
1270EOF
1271        cat >expected <<\EOF &&
12724:Subject: [PATCH] subject
12738:
127410:Signed-off-by: example happens to be wrapped here.
127511:
127612:Signed-off-by: C O Mitter <committer@example.com>
1277EOF
1278        test_cmp expected actual
1279'
1280
1281test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1282        append_signoff <<\EOF >actual &&
1283subject
1284
1285Signed-off-by: my@house
1286Signed-off-by: your@house
1287
1288A lot of houses.
1289EOF
1290        cat >expected <<\EOF &&
12914:Subject: [PATCH] subject
12928:
12939:Signed-off-by: my@house
129410:Signed-off-by: your@house
129511:
129613:
129714:Signed-off-by: C O Mitter <committer@example.com>
1298EOF
1299        test_cmp expected actual
1300'
1301
1302test_expect_success 'signoff: the same signoff at the end' '
1303        append_signoff <<\EOF >actual &&
1304subject
1305
1306body
1307
1308Signed-off-by: C O Mitter <committer@example.com>
1309EOF
1310        cat >expected <<\EOF &&
13114:Subject: [PATCH] subject
13128:
131310:
131411:Signed-off-by: C O Mitter <committer@example.com>
1315EOF
1316        test_cmp expected actual
1317'
1318
1319test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1320        printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1321                append_signoff >actual &&
1322        cat >expected <<\EOF &&
13234:Subject: [PATCH] subject
13248:
13259:Signed-off-by: C O Mitter <committer@example.com>
1326EOF
1327        test_cmp expected actual
1328'
1329
1330test_expect_success 'signoff: the same signoff NOT at the end' '
1331        append_signoff <<\EOF >actual &&
1332subject
1333
1334body
1335
1336Signed-off-by: C O Mitter <committer@example.com>
1337Signed-off-by: my@house
1338EOF
1339        cat >expected <<\EOF &&
13404:Subject: [PATCH] subject
13418:
134210:
134311:Signed-off-by: C O Mitter <committer@example.com>
134412:Signed-off-by: my@house
1345EOF
1346        test_cmp expected actual
1347'
1348
1349test_expect_success 'signoff: detect garbage in non-conforming footer' '
1350        append_signoff <<\EOF >actual &&
1351subject
1352
1353body
1354
1355Tested-by: my@house
1356Some Trash
1357Signed-off-by: C O Mitter <committer@example.com>
1358EOF
1359        cat >expected <<\EOF &&
13604:Subject: [PATCH] subject
13618:
136210:
136313:Signed-off-by: C O Mitter <committer@example.com>
136414:
136515:Signed-off-by: C O Mitter <committer@example.com>
1366EOF
1367        test_cmp expected actual
1368'
1369
1370test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1371        append_signoff <<\EOF >actual &&
1372subject
1373
1374body
1375
1376Reviewed-id: Noone
1377Tested-by: my@house
1378Change-id: Ideadbeef
1379Signed-off-by: C O Mitter <committer@example.com>
1380Bug: 1234
1381EOF
1382        cat >expected <<\EOF &&
13834:Subject: [PATCH] subject
13848:
138510:
138614:Signed-off-by: C O Mitter <committer@example.com>
1387EOF
1388        test_cmp expected actual
1389'
1390
1391test_expect_success 'format patch ignores color.ui' '
1392        test_unconfig color.ui &&
1393        git format-patch --stdout -1 >expect &&
1394        test_config color.ui always &&
1395        git format-patch --stdout -1 >actual &&
1396        test_cmp expect actual
1397'
1398
1399test_expect_success 'cover letter using branch description (1)' '
1400        git checkout rebuild-1 &&
1401        test_config branch.rebuild-1.description hello &&
1402        git format-patch --stdout --cover-letter master >actual &&
1403        grep hello actual >/dev/null
1404'
1405
1406test_expect_success 'cover letter using branch description (2)' '
1407        git checkout rebuild-1 &&
1408        test_config branch.rebuild-1.description hello &&
1409        git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1410        grep hello actual >/dev/null
1411'
1412
1413test_expect_success 'cover letter using branch description (3)' '
1414        git checkout rebuild-1 &&
1415        test_config branch.rebuild-1.description hello &&
1416        git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1417        grep hello actual >/dev/null
1418'
1419
1420test_expect_success 'cover letter using branch description (4)' '
1421        git checkout rebuild-1 &&
1422        test_config branch.rebuild-1.description hello &&
1423        git format-patch --stdout --cover-letter master.. >actual &&
1424        grep hello actual >/dev/null
1425'
1426
1427test_expect_success 'cover letter using branch description (5)' '
1428        git checkout rebuild-1 &&
1429        test_config branch.rebuild-1.description hello &&
1430        git format-patch --stdout --cover-letter -2 HEAD >actual &&
1431        grep hello actual >/dev/null
1432'
1433
1434test_expect_success 'cover letter using branch description (6)' '
1435        git checkout rebuild-1 &&
1436        test_config branch.rebuild-1.description hello &&
1437        git format-patch --stdout --cover-letter -2 >actual &&
1438        grep hello actual >/dev/null
1439'
1440
1441test_expect_success 'cover letter with nothing' '
1442        git format-patch --stdout --cover-letter >actual &&
1443        test_line_count = 0 actual
1444'
1445
1446test_expect_success 'cover letter auto' '
1447        mkdir -p tmp &&
1448        test_when_finished "rm -rf tmp;
1449                git config --unset format.coverletter" &&
1450
1451        git config format.coverletter auto &&
1452        git format-patch -o tmp -1 >list &&
1453        test_line_count = 1 list &&
1454        git format-patch -o tmp -2 >list &&
1455        test_line_count = 3 list
1456'
1457
1458test_expect_success 'cover letter auto user override' '
1459        mkdir -p tmp &&
1460        test_when_finished "rm -rf tmp;
1461                git config --unset format.coverletter" &&
1462
1463        git config format.coverletter auto &&
1464        git format-patch -o tmp --cover-letter -1 >list &&
1465        test_line_count = 2 list &&
1466        git format-patch -o tmp --cover-letter -2 >list &&
1467        test_line_count = 3 list &&
1468        git format-patch -o tmp --no-cover-letter -1 >list &&
1469        test_line_count = 1 list &&
1470        git format-patch -o tmp --no-cover-letter -2 >list &&
1471        test_line_count = 2 list
1472'
1473
1474test_expect_success 'format-patch --zero-commit' '
1475        git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1476        grep "^From " patch2 | sort | uniq >actual &&
1477        echo "From $_z40 Mon Sep 17 00:00:00 2001" >expect &&
1478        test_cmp expect actual
1479'
1480
1481test_expect_success 'From line has expected format' '
1482        git format-patch --stdout v2..v1 >patch2 &&
1483        grep "^From " patch2 >from &&
1484        grep "^From $_x40 Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1485        test_cmp from filtered
1486'
1487
1488test_expect_success 'format-patch format.outputDirectory option' '
1489        test_config format.outputDirectory patches &&
1490        rm -fr patches &&
1491        git format-patch master..side &&
1492        test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
1493'
1494
1495test_expect_success 'format-patch -o overrides format.outputDirectory' '
1496        test_config format.outputDirectory patches &&
1497        rm -fr patches patchset &&
1498        git format-patch master..side -o patchset &&
1499        test_path_is_missing patches &&
1500        test_path_is_dir patchset
1501'
1502
1503test_expect_success 'format-patch --base' '
1504        git checkout side &&
1505        git format-patch --stdout --base=HEAD~3 -1 >patch &&
1506        grep "^base-commit:" patch >actual &&
1507        grep "^prerequisite-patch-id:" patch >>actual &&
1508        echo "base-commit: $(git rev-parse HEAD~3)" >expected &&
1509        echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1510        echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1511        test_cmp expected actual
1512'
1513
1514test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1515        test_must_fail git format-patch --base=HEAD -2 &&
1516        test_must_fail git format-patch --base=HEAD~1 -2 &&
1517        git format-patch --stdout --base=HEAD~2 -2 >patch &&
1518        grep "^base-commit:" patch >actual &&
1519        echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
1520        test_cmp expected actual
1521'
1522
1523test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1524        # For history as below:
1525        #
1526        #    ---Q---P---Z---Y---*---X
1527        #        \             /
1528        #         ------------W
1529        #
1530        # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1531        git checkout -b topic1 master &&
1532        git rev-parse HEAD >commit-id-base &&
1533        test_commit P &&
1534        git rev-parse HEAD >commit-id-P &&
1535        test_commit Z &&
1536        git rev-parse HEAD >commit-id-Z &&
1537        test_commit Y &&
1538        git checkout -b topic2 master &&
1539        test_commit W &&
1540        git merge topic1 &&
1541        test_commit X &&
1542        test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1543        test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1544        git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1545        grep "^base-commit:" patch >actual &&
1546        echo "base-commit: $(cat commit-id-base)" >expected &&
1547        test_cmp expected actual
1548'
1549
1550test_expect_success 'format-patch --base=auto' '
1551        git checkout -b upstream master &&
1552        git checkout -b local upstream &&
1553        git branch --set-upstream-to=upstream &&
1554        test_commit N1 &&
1555        test_commit N2 &&
1556        git format-patch --stdout --base=auto -2 >patch &&
1557        grep "^base-commit:" patch >actual &&
1558        echo "base-commit: $(git rev-parse upstream)" >expected &&
1559        test_cmp expected actual
1560'
1561
1562test_expect_success 'format-patch errors out when history involves criss-cross' '
1563        # setup criss-cross history
1564        #
1565        #   B---M1---D
1566        #  / \ /
1567        # A   X
1568        #  \ / \
1569        #   C---M2---E
1570        #
1571        git checkout master &&
1572        test_commit A &&
1573        git checkout -b xb master &&
1574        test_commit B &&
1575        git checkout -b xc master &&
1576        test_commit C &&
1577        git checkout -b xbc xb -- &&
1578        git merge xc &&
1579        git checkout -b xcb xc -- &&
1580        git branch --set-upstream-to=xbc &&
1581        git merge xb &&
1582        git checkout xbc &&
1583        test_commit D &&
1584        git checkout xcb &&
1585        test_commit E &&
1586        test_must_fail  git format-patch --base=auto -1
1587'
1588
1589test_expect_success 'format-patch format.useAutoBaseoption' '
1590        test_when_finished "git config --unset format.useAutoBase" &&
1591        git checkout local &&
1592        git config format.useAutoBase true &&
1593        git format-patch --stdout -1 >patch &&
1594        grep "^base-commit:" patch >actual &&
1595        echo "base-commit: $(git rev-parse upstream)" >expected &&
1596        test_cmp expected actual
1597'
1598
1599test_expect_success 'format-patch --base overrides format.useAutoBase' '
1600        test_when_finished "git config --unset format.useAutoBase" &&
1601        git config format.useAutoBase true &&
1602        git format-patch --stdout --base=HEAD~1 -1 >patch &&
1603        grep "^base-commit:" patch >actual &&
1604        echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
1605        test_cmp expected actual
1606'
1607
1608test_expect_success 'format-patch --pretty=mboxrd' '
1609        sp=" " &&
1610        cat >msg <<-INPUT_END &&
1611        mboxrd should escape the body
1612
1613        From could trip up a loose mbox parser
1614        >From extra escape for reversibility
1615        >>From extra escape for reversibility 2
1616        from lower case not escaped
1617        Fromm bad speling not escaped
1618         From with leading space not escaped
1619
1620        F
1621        From
1622        From$sp
1623        From    $sp
1624        From    $sp
1625        INPUT_END
1626
1627        cat >expect <<-INPUT_END &&
1628        >From could trip up a loose mbox parser
1629        >>From extra escape for reversibility
1630        >>>From extra escape for reversibility 2
1631        from lower case not escaped
1632        Fromm bad speling not escaped
1633         From with leading space not escaped
1634
1635        F
1636        From
1637        From
1638        From
1639        From
1640        INPUT_END
1641
1642        C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
1643        git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
1644        git grep -h --no-index -A11 \
1645                "^>From could trip up a loose mbox parser" patch >actual &&
1646        test_cmp expect actual
1647'
1648
1649test_done