t / t4014-format-patch.shon commit Merge branch 'jc/format-patch-range-diff-fix' (d32fa3c)
   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        before=$(git hash-object file) &&
 582        before=$(git rev-parse --short $before) &&
 583        for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
 584        after=$(git hash-object file) &&
 585        after=$(git rev-parse --short $after) &&
 586        git update-index file &&
 587        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." &&
 588        git format-patch -o patches/ master..side &&
 589        ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
 590'
 591
 592test_expect_success 'cover-letter inherits diff options' '
 593        git mv file foo &&
 594        git commit -m foo &&
 595        git format-patch --no-renames --cover-letter -1 &&
 596        check_patch 0000-cover-letter.patch &&
 597        ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
 598        git format-patch --cover-letter -1 -M &&
 599        grep "file => foo .* 0 *\$" 0000-cover-letter.patch
 600
 601'
 602
 603cat > expect << EOF
 604  This is an excessively long subject line for a message due to the
 605    habit some projects have of not having a short, one-line subject at
 606    the start of the commit message, but rather sticking a whole
 607    paragraph right at the start as the only thing in the commit
 608    message. It had better not become the filename for the patch.
 609  foo
 610
 611EOF
 612
 613test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
 614
 615        git format-patch --cover-letter -2 &&
 616        sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
 617        test_cmp expect output
 618
 619'
 620
 621cat > expect << EOF
 622index $before..$after 100644
 623--- a/file
 624+++ b/file
 625@@ -13,4 +13,20 @@ C
 626 10
 627 D
 628 E
 629 F
 630+5
 631EOF
 632
 633test_expect_success 'format-patch respects -U' '
 634
 635        git format-patch -U4 -2 &&
 636        sed -e "1,/^diff/d" -e "/^+5/q" \
 637                <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
 638                >output &&
 639        test_cmp expect output
 640
 641'
 642
 643cat > expect << EOF
 644
 645diff --git a/file b/file
 646index $before..$after 100644
 647--- a/file
 648+++ b/file
 649@@ -14,3 +14,19 @@ C
 650 D
 651 E
 652 F
 653+5
 654EOF
 655
 656test_expect_success 'format-patch -p suppresses stat' '
 657
 658        git format-patch -p -2 &&
 659        sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
 660        test_cmp expect output
 661
 662'
 663
 664test_expect_success 'format-patch from a subdirectory (1)' '
 665        filename=$(
 666                rm -rf sub &&
 667                mkdir -p sub/dir &&
 668                cd sub/dir &&
 669                git format-patch -1
 670        ) &&
 671        case "$filename" in
 672        0*)
 673                ;; # ok
 674        *)
 675                echo "Oops? $filename"
 676                false
 677                ;;
 678        esac &&
 679        test -f "$filename"
 680'
 681
 682test_expect_success 'format-patch from a subdirectory (2)' '
 683        filename=$(
 684                rm -rf sub &&
 685                mkdir -p sub/dir &&
 686                cd sub/dir &&
 687                git format-patch -1 -o ..
 688        ) &&
 689        case "$filename" in
 690        ../0*)
 691                ;; # ok
 692        *)
 693                echo "Oops? $filename"
 694                false
 695                ;;
 696        esac &&
 697        basename=$(expr "$filename" : ".*/\(.*\)") &&
 698        test -f "sub/$basename"
 699'
 700
 701test_expect_success 'format-patch from a subdirectory (3)' '
 702        rm -f 0* &&
 703        filename=$(
 704                rm -rf sub &&
 705                mkdir -p sub/dir &&
 706                cd sub/dir &&
 707                git format-patch -1 -o "$TRASH_DIRECTORY"
 708        ) &&
 709        basename=$(expr "$filename" : ".*/\(.*\)") &&
 710        test -f "$basename"
 711'
 712
 713test_expect_success 'format-patch --in-reply-to' '
 714        git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
 715        grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
 716        grep "^References: <baz@foo.bar>" patch8
 717'
 718
 719test_expect_success 'format-patch --signoff' '
 720        git format-patch -1 --signoff --stdout >out &&
 721        grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
 722'
 723
 724test_expect_success 'format-patch --notes --signoff' '
 725        git notes --ref test add -m "test message" HEAD &&
 726        git format-patch -1 --signoff --stdout --notes=test >out &&
 727        # Three dashes must come after S-o-b
 728        ! sed "/^Signed-off-by: /q" out | grep "test message" &&
 729        sed "1,/^Signed-off-by: /d" out | grep "test message" &&
 730        # Notes message must come after three dashes
 731        ! sed "/^---$/q" out | grep "test message" &&
 732        sed "1,/^---$/d" out | grep "test message"
 733'
 734
 735echo "fatal: --name-only does not make sense" > expect.name-only
 736echo "fatal: --name-status does not make sense" > expect.name-status
 737echo "fatal: --check does not make sense" > expect.check
 738
 739test_expect_success 'options no longer allowed for format-patch' '
 740        test_must_fail git format-patch --name-only 2> output &&
 741        test_i18ncmp expect.name-only output &&
 742        test_must_fail git format-patch --name-status 2> output &&
 743        test_i18ncmp expect.name-status output &&
 744        test_must_fail git format-patch --check 2> output &&
 745        test_i18ncmp expect.check output'
 746
 747test_expect_success 'format-patch --numstat should produce a patch' '
 748        git format-patch --numstat --stdout master..side > output &&
 749        test 5 = $(grep "^diff --git a/" output | wc -l)'
 750
 751test_expect_success 'format-patch -- <path>' '
 752        git format-patch master..side -- file 2>error &&
 753        ! grep "Use .--" error
 754'
 755
 756test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
 757        git format-patch --ignore-if-in-upstream HEAD
 758'
 759
 760git_version="$(git --version | sed "s/.* //")"
 761
 762signature() {
 763        printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
 764}
 765
 766test_expect_success 'format-patch default signature' '
 767        git format-patch --stdout -1 | tail -n 3 >output &&
 768        signature >expect &&
 769        test_cmp expect output
 770'
 771
 772test_expect_success 'format-patch --signature' '
 773        git format-patch --stdout --signature="my sig" -1 | tail -n 3 >output &&
 774        signature "my sig" >expect &&
 775        test_cmp expect output
 776'
 777
 778test_expect_success 'format-patch with format.signature config' '
 779        git config format.signature "config sig" &&
 780        git format-patch --stdout -1 >output &&
 781        grep "config sig" output
 782'
 783
 784test_expect_success 'format-patch --signature overrides format.signature' '
 785        git config format.signature "config sig" &&
 786        git format-patch --stdout --signature="overrides" -1 >output &&
 787        ! grep "config sig" output &&
 788        grep "overrides" output
 789'
 790
 791test_expect_success 'format-patch --no-signature ignores format.signature' '
 792        git config format.signature "config sig" &&
 793        git format-patch --stdout --signature="my sig" --no-signature \
 794                -1 >output &&
 795        check_patch output &&
 796        ! grep "config sig" output &&
 797        ! grep "my sig" output &&
 798        ! grep "^-- \$" output
 799'
 800
 801test_expect_success 'format-patch --signature --cover-letter' '
 802        git config --unset-all format.signature &&
 803        git format-patch --stdout --signature="my sig" --cover-letter \
 804                -1 >output &&
 805        grep "my sig" output &&
 806        test 2 = $(grep "my sig" output | wc -l)
 807'
 808
 809test_expect_success 'format.signature="" suppresses signatures' '
 810        git config format.signature "" &&
 811        git format-patch --stdout -1 >output &&
 812        check_patch output &&
 813        ! grep "^-- \$" output
 814'
 815
 816test_expect_success 'format-patch --no-signature suppresses signatures' '
 817        git config --unset-all format.signature &&
 818        git format-patch --stdout --no-signature -1 >output &&
 819        check_patch output &&
 820        ! grep "^-- \$" output
 821'
 822
 823test_expect_success 'format-patch --signature="" suppresses signatures' '
 824        git format-patch --stdout --signature="" -1 >output &&
 825        check_patch output &&
 826        ! grep "^-- \$" output
 827'
 828
 829test_expect_success 'prepare mail-signature input' '
 830        cat >mail-signature <<-\EOF
 831
 832        Test User <test.email@kernel.org>
 833        http://git.kernel.org/cgit/git/git.git
 834
 835        git.kernel.org/?p=git/git.git;a=summary
 836
 837        EOF
 838'
 839
 840test_expect_success '--signature-file=file works' '
 841        git format-patch --stdout --signature-file=mail-signature -1 >output &&
 842        check_patch output &&
 843        sed -e "1,/^-- \$/d" <output >actual &&
 844        {
 845                cat mail-signature && echo
 846        } >expect &&
 847        test_cmp expect actual
 848'
 849
 850test_expect_success 'format.signaturefile works' '
 851        test_config format.signaturefile mail-signature &&
 852        git format-patch --stdout -1 >output &&
 853        check_patch output &&
 854        sed -e "1,/^-- \$/d" <output >actual &&
 855        {
 856                cat mail-signature && echo
 857        } >expect &&
 858        test_cmp expect actual
 859'
 860
 861test_expect_success '--no-signature suppresses format.signaturefile ' '
 862        test_config format.signaturefile mail-signature &&
 863        git format-patch --stdout --no-signature -1 >output &&
 864        check_patch output &&
 865        ! grep "^-- \$" output
 866'
 867
 868test_expect_success '--signature-file overrides format.signaturefile' '
 869        cat >other-mail-signature <<-\EOF &&
 870        Use this other signature instead of mail-signature.
 871        EOF
 872        test_config format.signaturefile mail-signature &&
 873        git format-patch --stdout \
 874                        --signature-file=other-mail-signature -1 >output &&
 875        check_patch output &&
 876        sed -e "1,/^-- \$/d" <output >actual &&
 877        {
 878                cat other-mail-signature && echo
 879        } >expect &&
 880        test_cmp expect actual
 881'
 882
 883test_expect_success '--signature overrides format.signaturefile' '
 884        test_config format.signaturefile mail-signature &&
 885        git format-patch --stdout --signature="my sig" -1 >output &&
 886        check_patch output &&
 887        grep "my sig" output
 888'
 889
 890test_expect_success TTY 'format-patch --stdout paginates' '
 891        rm -f pager_used &&
 892        test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
 893        test_path_is_file pager_used
 894'
 895
 896 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
 897        rm -f pager_used &&
 898        test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
 899        test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
 900        test_path_is_missing pager_used &&
 901        test_path_is_missing .git/pager_used
 902'
 903
 904test_expect_success 'format-patch handles multi-line subjects' '
 905        rm -rf patches/ &&
 906        echo content >>file &&
 907        for i in one two three; do echo $i; done >msg &&
 908        git add file &&
 909        git commit -F msg &&
 910        git format-patch -o patches -1 &&
 911        grep ^Subject: patches/0001-one.patch >actual &&
 912        echo "Subject: [PATCH] one two three" >expect &&
 913        test_cmp expect actual
 914'
 915
 916test_expect_success 'format-patch handles multi-line encoded subjects' '
 917        rm -rf patches/ &&
 918        echo content >>file &&
 919        for i in en två tre; do echo $i; done >msg &&
 920        git add file &&
 921        git commit -F msg &&
 922        git format-patch -o patches -1 &&
 923        grep ^Subject: patches/0001-en.patch >actual &&
 924        echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
 925        test_cmp expect actual
 926'
 927
 928M8="foo bar "
 929M64=$M8$M8$M8$M8$M8$M8$M8$M8
 930M512=$M64$M64$M64$M64$M64$M64$M64$M64
 931cat >expect <<'EOF'
 932Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 933 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 934 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 935 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 936 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
 937 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 938 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
 939EOF
 940test_expect_success 'format-patch wraps extremely long subject (ascii)' '
 941        echo content >>file &&
 942        git add file &&
 943        git commit -m "$M512" &&
 944        git format-patch --stdout -1 >patch &&
 945        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 946        test_cmp expect subject
 947'
 948
 949M8="föö bar "
 950M64=$M8$M8$M8$M8$M8$M8$M8$M8
 951M512=$M64$M64$M64$M64$M64$M64$M64$M64
 952cat >expect <<'EOF'
 953Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 954 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 955 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 956 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 957 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 958 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 959 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 960 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 961 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 962 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 963 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 964 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 965 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 966 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 967 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 968 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 969 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 970 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 971 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
 972 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
 973 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
 974 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
 975 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
 976 =?UTF-8?q?bar?=
 977EOF
 978test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
 979        rm -rf patches/ &&
 980        echo content >>file &&
 981        git add file &&
 982        git commit -m "$M512" &&
 983        git format-patch --stdout -1 >patch &&
 984        sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
 985        test_cmp expect subject
 986'
 987
 988check_author() {
 989        echo content >>file &&
 990        git add file &&
 991        GIT_AUTHOR_NAME=$1 git commit -m author-check &&
 992        git format-patch --stdout -1 >patch &&
 993        sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
 994        test_cmp expect actual
 995}
 996
 997cat >expect <<'EOF'
 998From: "Foo B. Bar" <author@example.com>
 999EOF
1000test_expect_success 'format-patch quotes dot in from-headers' '
1001        check_author "Foo B. Bar"
1002'
1003
1004cat >expect <<'EOF'
1005From: "Foo \"The Baz\" Bar" <author@example.com>
1006EOF
1007test_expect_success 'format-patch quotes double-quote in from-headers' '
1008        check_author "Foo \"The Baz\" Bar"
1009'
1010
1011cat >expect <<'EOF'
1012From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1013EOF
1014test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1015        check_author "Föo Bar"
1016'
1017
1018cat >expect <<'EOF'
1019From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1020EOF
1021test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1022        check_author "Föo B. Bar"
1023'
1024
1025cat >expect <<EOF
1026From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1027 <author@example.com>
1028EOF
1029test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1030        check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1031'
1032
1033cat >expect <<'EOF'
1034From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1035 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1036 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1037EOF
1038test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1039        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"
1040'
1041
1042cat >expect <<'EOF'
1043From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1044 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1045 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1046EOF
1047test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1048        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"
1049'
1050
1051cat >expect <<'EOF'
1052From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1053 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1054 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1055 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1056 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1057EOF
1058test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1059        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"
1060'
1061
1062cat >expect <<'EOF'
1063Subject: header with . in it
1064EOF
1065test_expect_success 'subject lines do not have 822 atom-quoting' '
1066        echo content >>file &&
1067        git add file &&
1068        git commit -m "header with . in it" &&
1069        git format-patch -k -1 --stdout >patch &&
1070        grep ^Subject: patch >actual &&
1071        test_cmp expect actual
1072'
1073
1074cat >expect <<'EOF'
1075Subject: [PREFIX 1/1] header with . in it
1076EOF
1077test_expect_success 'subject prefixes have space prepended' '
1078        git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1079        grep ^Subject: patch >actual &&
1080        test_cmp expect actual
1081'
1082
1083cat >expect <<'EOF'
1084Subject: [1/1] header with . in it
1085EOF
1086test_expect_success 'empty subject prefix does not have extra space' '
1087        git format-patch -n -1 --stdout --subject-prefix= >patch &&
1088        grep ^Subject: patch >actual &&
1089        test_cmp expect actual
1090'
1091
1092test_expect_success '--rfc' '
1093        cat >expect <<-\EOF &&
1094        Subject: [RFC PATCH 1/1] header with . in it
1095        EOF
1096        git format-patch -n -1 --stdout --rfc >patch &&
1097        grep ^Subject: patch >actual &&
1098        test_cmp expect actual
1099'
1100
1101test_expect_success '--from=ident notices bogus ident' '
1102        test_must_fail git format-patch -1 --stdout --from=foo >patch
1103'
1104
1105test_expect_success '--from=ident replaces author' '
1106        git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1107        cat >expect <<-\EOF &&
1108        From: Me <me@example.com>
1109
1110        From: A U Thor <author@example.com>
1111
1112        EOF
1113        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1114        test_cmp expect patch.head
1115'
1116
1117test_expect_success '--from uses committer ident' '
1118        git format-patch -1 --stdout --from >patch &&
1119        cat >expect <<-\EOF &&
1120        From: C O Mitter <committer@example.com>
1121
1122        From: A U Thor <author@example.com>
1123
1124        EOF
1125        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1126        test_cmp expect patch.head
1127'
1128
1129test_expect_success '--from omits redundant in-body header' '
1130        git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1131        cat >expect <<-\EOF &&
1132        From: A U Thor <author@example.com>
1133
1134        EOF
1135        sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1136        test_cmp expect patch.head
1137'
1138
1139test_expect_success 'in-body headers trigger content encoding' '
1140        test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1141        test_when_finished "git reset --hard HEAD^" &&
1142        git format-patch -1 --stdout --from >patch &&
1143        cat >expect <<-\EOF &&
1144        From: C O Mitter <committer@example.com>
1145        Content-Type: text/plain; charset=UTF-8
1146
1147        From: éxötìc <author@example.com>
1148
1149        EOF
1150        sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1151        test_cmp expect patch.head
1152'
1153
1154append_signoff()
1155{
1156        C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1157        git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1158        sed -n -e "1,/^---$/p" append_signoff.patch |
1159                egrep -n "^Subject|Sign|^$"
1160}
1161
1162test_expect_success 'signoff: commit with no body' '
1163        append_signoff </dev/null >actual &&
1164        cat <<\EOF | sed "s/EOL$//" >expected &&
11654:Subject: [PATCH] EOL
11668:
11679:Signed-off-by: C O Mitter <committer@example.com>
1168EOF
1169        test_cmp expected actual
1170'
1171
1172test_expect_success 'signoff: commit with only subject' '
1173        echo subject | append_signoff >actual &&
1174        cat >expected <<\EOF &&
11754:Subject: [PATCH] subject
11768:
11779:Signed-off-by: C O Mitter <committer@example.com>
1178EOF
1179        test_cmp expected actual
1180'
1181
1182test_expect_success 'signoff: commit with only subject that does not end with NL' '
1183        printf subject | append_signoff >actual &&
1184        cat >expected <<\EOF &&
11854:Subject: [PATCH] subject
11868:
11879:Signed-off-by: C O Mitter <committer@example.com>
1188EOF
1189        test_cmp expected actual
1190'
1191
1192test_expect_success 'signoff: no existing signoffs' '
1193        append_signoff <<\EOF >actual &&
1194subject
1195
1196body
1197EOF
1198        cat >expected <<\EOF &&
11994:Subject: [PATCH] subject
12008:
120110:
120211:Signed-off-by: C O Mitter <committer@example.com>
1203EOF
1204        test_cmp expected actual
1205'
1206
1207test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1208        printf "subject\n\nbody" | append_signoff >actual &&
1209        cat >expected <<\EOF &&
12104:Subject: [PATCH] subject
12118:
121210:
121311:Signed-off-by: C O Mitter <committer@example.com>
1214EOF
1215        test_cmp expected actual
1216'
1217
1218test_expect_success 'signoff: some random signoff' '
1219        append_signoff <<\EOF >actual &&
1220subject
1221
1222body
1223
1224Signed-off-by: my@house
1225EOF
1226        cat >expected <<\EOF &&
12274:Subject: [PATCH] subject
12288:
122910:
123011:Signed-off-by: my@house
123112:Signed-off-by: C O Mitter <committer@example.com>
1232EOF
1233        test_cmp expected actual
1234'
1235
1236test_expect_success 'signoff: misc conforming footer elements' '
1237        append_signoff <<\EOF >actual &&
1238subject
1239
1240body
1241
1242Signed-off-by: my@house
1243(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1244Tested-by: Some One <someone@example.com>
1245Bug: 1234
1246EOF
1247        cat >expected <<\EOF &&
12484:Subject: [PATCH] subject
12498:
125010:
125111:Signed-off-by: my@house
125215:Signed-off-by: C O Mitter <committer@example.com>
1253EOF
1254        test_cmp expected actual
1255'
1256
1257test_expect_success 'signoff: some random signoff-alike' '
1258        append_signoff <<\EOF >actual &&
1259subject
1260
1261body
1262Fooled-by-me: my@house
1263EOF
1264        cat >expected <<\EOF &&
12654:Subject: [PATCH] subject
12668:
126711:
126812:Signed-off-by: C O Mitter <committer@example.com>
1269EOF
1270        test_cmp expected actual
1271'
1272
1273test_expect_success 'signoff: not really a signoff' '
1274        append_signoff <<\EOF >actual &&
1275subject
1276
1277I want to mention about Signed-off-by: here.
1278EOF
1279        cat >expected <<\EOF &&
12804:Subject: [PATCH] subject
12818:
12829:I want to mention about Signed-off-by: here.
128310:
128411:Signed-off-by: C O Mitter <committer@example.com>
1285EOF
1286        test_cmp expected actual
1287'
1288
1289test_expect_success 'signoff: not really a signoff (2)' '
1290        append_signoff <<\EOF >actual &&
1291subject
1292
1293My unfortunate
1294Signed-off-by: example happens to be wrapped here.
1295EOF
1296        cat >expected <<\EOF &&
12974:Subject: [PATCH] subject
12988:
129910:Signed-off-by: example happens to be wrapped here.
130011:Signed-off-by: C O Mitter <committer@example.com>
1301EOF
1302        test_cmp expected actual
1303'
1304
1305test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1306        append_signoff <<\EOF >actual &&
1307subject
1308
1309Signed-off-by: my@house
1310Signed-off-by: your@house
1311
1312A lot of houses.
1313EOF
1314        cat >expected <<\EOF &&
13154:Subject: [PATCH] subject
13168:
13179:Signed-off-by: my@house
131810:Signed-off-by: your@house
131911:
132013:
132114:Signed-off-by: C O Mitter <committer@example.com>
1322EOF
1323        test_cmp expected actual
1324'
1325
1326test_expect_success 'signoff: the same signoff at the end' '
1327        append_signoff <<\EOF >actual &&
1328subject
1329
1330body
1331
1332Signed-off-by: C O Mitter <committer@example.com>
1333EOF
1334        cat >expected <<\EOF &&
13354:Subject: [PATCH] subject
13368:
133710:
133811:Signed-off-by: C O Mitter <committer@example.com>
1339EOF
1340        test_cmp expected actual
1341'
1342
1343test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1344        printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1345                append_signoff >actual &&
1346        cat >expected <<\EOF &&
13474:Subject: [PATCH] subject
13488:
13499:Signed-off-by: C O Mitter <committer@example.com>
1350EOF
1351        test_cmp expected actual
1352'
1353
1354test_expect_success 'signoff: the same signoff NOT at the end' '
1355        append_signoff <<\EOF >actual &&
1356subject
1357
1358body
1359
1360Signed-off-by: C O Mitter <committer@example.com>
1361Signed-off-by: my@house
1362EOF
1363        cat >expected <<\EOF &&
13644:Subject: [PATCH] subject
13658:
136610:
136711:Signed-off-by: C O Mitter <committer@example.com>
136812:Signed-off-by: my@house
1369EOF
1370        test_cmp expected actual
1371'
1372
1373test_expect_success 'signoff: tolerate garbage in conforming footer' '
1374        append_signoff <<\EOF >actual &&
1375subject
1376
1377body
1378
1379Tested-by: my@house
1380Some Trash
1381Signed-off-by: C O Mitter <committer@example.com>
1382EOF
1383        cat >expected <<\EOF &&
13844:Subject: [PATCH] subject
13858:
138610:
138713:Signed-off-by: C O Mitter <committer@example.com>
1388EOF
1389        test_cmp expected actual
1390'
1391
1392test_expect_success 'signoff: respect trailer config' '
1393        append_signoff <<\EOF >actual &&
1394subject
1395
1396Myfooter: x
1397Some Trash
1398EOF
1399        cat >expected <<\EOF &&
14004:Subject: [PATCH] subject
14018:
140211:
140312:Signed-off-by: C O Mitter <committer@example.com>
1404EOF
1405        test_cmp expected actual &&
1406
1407        test_config trailer.Myfooter.ifexists add &&
1408        append_signoff <<\EOF >actual &&
1409subject
1410
1411Myfooter: x
1412Some Trash
1413EOF
1414        cat >expected <<\EOF &&
14154:Subject: [PATCH] subject
14168:
141711:Signed-off-by: C O Mitter <committer@example.com>
1418EOF
1419        test_cmp expected actual
1420'
1421
1422test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1423        append_signoff <<\EOF >actual &&
1424subject
1425
1426body
1427
1428Reviewed-id: Noone
1429Tested-by: my@house
1430Change-id: Ideadbeef
1431Signed-off-by: C O Mitter <committer@example.com>
1432Bug: 1234
1433EOF
1434        cat >expected <<\EOF &&
14354:Subject: [PATCH] subject
14368:
143710:
143814:Signed-off-by: C O Mitter <committer@example.com>
1439EOF
1440        test_cmp expected actual
1441'
1442
1443test_expect_success 'format patch ignores color.ui' '
1444        test_unconfig color.ui &&
1445        git format-patch --stdout -1 >expect &&
1446        test_config color.ui always &&
1447        git format-patch --stdout -1 >actual &&
1448        test_cmp expect actual
1449'
1450
1451test_expect_success 'cover letter using branch description (1)' '
1452        git checkout rebuild-1 &&
1453        test_config branch.rebuild-1.description hello &&
1454        git format-patch --stdout --cover-letter master >actual &&
1455        grep hello actual >/dev/null
1456'
1457
1458test_expect_success 'cover letter using branch description (2)' '
1459        git checkout rebuild-1 &&
1460        test_config branch.rebuild-1.description hello &&
1461        git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1462        grep hello actual >/dev/null
1463'
1464
1465test_expect_success 'cover letter using branch description (3)' '
1466        git checkout rebuild-1 &&
1467        test_config branch.rebuild-1.description hello &&
1468        git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1469        grep hello actual >/dev/null
1470'
1471
1472test_expect_success 'cover letter using branch description (4)' '
1473        git checkout rebuild-1 &&
1474        test_config branch.rebuild-1.description hello &&
1475        git format-patch --stdout --cover-letter master.. >actual &&
1476        grep hello actual >/dev/null
1477'
1478
1479test_expect_success 'cover letter using branch description (5)' '
1480        git checkout rebuild-1 &&
1481        test_config branch.rebuild-1.description hello &&
1482        git format-patch --stdout --cover-letter -2 HEAD >actual &&
1483        grep hello actual >/dev/null
1484'
1485
1486test_expect_success 'cover letter using branch description (6)' '
1487        git checkout rebuild-1 &&
1488        test_config branch.rebuild-1.description hello &&
1489        git format-patch --stdout --cover-letter -2 >actual &&
1490        grep hello actual >/dev/null
1491'
1492
1493test_expect_success 'cover letter with nothing' '
1494        git format-patch --stdout --cover-letter >actual &&
1495        test_line_count = 0 actual
1496'
1497
1498test_expect_success 'cover letter auto' '
1499        mkdir -p tmp &&
1500        test_when_finished "rm -rf tmp;
1501                git config --unset format.coverletter" &&
1502
1503        git config format.coverletter auto &&
1504        git format-patch -o tmp -1 >list &&
1505        test_line_count = 1 list &&
1506        git format-patch -o tmp -2 >list &&
1507        test_line_count = 3 list
1508'
1509
1510test_expect_success 'cover letter auto user override' '
1511        mkdir -p tmp &&
1512        test_when_finished "rm -rf tmp;
1513                git config --unset format.coverletter" &&
1514
1515        git config format.coverletter auto &&
1516        git format-patch -o tmp --cover-letter -1 >list &&
1517        test_line_count = 2 list &&
1518        git format-patch -o tmp --cover-letter -2 >list &&
1519        test_line_count = 3 list &&
1520        git format-patch -o tmp --no-cover-letter -1 >list &&
1521        test_line_count = 1 list &&
1522        git format-patch -o tmp --no-cover-letter -2 >list &&
1523        test_line_count = 2 list
1524'
1525
1526test_expect_success 'format-patch --zero-commit' '
1527        git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1528        grep "^From " patch2 | sort | uniq >actual &&
1529        echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
1530        test_cmp expect actual
1531'
1532
1533test_expect_success 'From line has expected format' '
1534        git format-patch --stdout v2..v1 >patch2 &&
1535        grep "^From " patch2 >from &&
1536        grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1537        test_cmp from filtered
1538'
1539
1540test_expect_success 'format-patch format.outputDirectory option' '
1541        test_config format.outputDirectory patches &&
1542        rm -fr patches &&
1543        git format-patch master..side &&
1544        test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
1545'
1546
1547test_expect_success 'format-patch -o overrides format.outputDirectory' '
1548        test_config format.outputDirectory patches &&
1549        rm -fr patches patchset &&
1550        git format-patch master..side -o patchset &&
1551        test_path_is_missing patches &&
1552        test_path_is_dir patchset
1553'
1554
1555test_expect_success 'format-patch --base' '
1556        git checkout side &&
1557        git format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 &&
1558        git format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 &&
1559        echo >expected &&
1560        echo "base-commit: $(git rev-parse HEAD~3)" >>expected &&
1561        echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1562        echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1563        signature >> expected &&
1564        test_cmp expected actual1 &&
1565        test_cmp expected actual2
1566'
1567
1568test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1569        test_must_fail git format-patch --base=HEAD -2 &&
1570        test_must_fail git format-patch --base=HEAD~1 -2 &&
1571        git format-patch --stdout --base=HEAD~2 -2 >patch &&
1572        grep "^base-commit:" patch >actual &&
1573        echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
1574        test_cmp expected actual
1575'
1576
1577test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1578        # For history as below:
1579        #
1580        #    ---Q---P---Z---Y---*---X
1581        #        \             /
1582        #         ------------W
1583        #
1584        # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1585        git checkout -b topic1 master &&
1586        git rev-parse HEAD >commit-id-base &&
1587        test_commit P &&
1588        git rev-parse HEAD >commit-id-P &&
1589        test_commit Z &&
1590        git rev-parse HEAD >commit-id-Z &&
1591        test_commit Y &&
1592        git checkout -b topic2 master &&
1593        test_commit W &&
1594        git merge topic1 &&
1595        test_commit X &&
1596        test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1597        test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1598        git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1599        grep "^base-commit:" patch >actual &&
1600        echo "base-commit: $(cat commit-id-base)" >expected &&
1601        test_cmp expected actual
1602'
1603
1604test_expect_success 'format-patch --base=auto' '
1605        git checkout -b upstream master &&
1606        git checkout -b local upstream &&
1607        git branch --set-upstream-to=upstream &&
1608        test_commit N1 &&
1609        test_commit N2 &&
1610        git format-patch --stdout --base=auto -2 >patch &&
1611        grep "^base-commit:" patch >actual &&
1612        echo "base-commit: $(git rev-parse upstream)" >expected &&
1613        test_cmp expected actual
1614'
1615
1616test_expect_success 'format-patch errors out when history involves criss-cross' '
1617        # setup criss-cross history
1618        #
1619        #   B---M1---D
1620        #  / \ /
1621        # A   X
1622        #  \ / \
1623        #   C---M2---E
1624        #
1625        git checkout master &&
1626        test_commit A &&
1627        git checkout -b xb master &&
1628        test_commit B &&
1629        git checkout -b xc master &&
1630        test_commit C &&
1631        git checkout -b xbc xb -- &&
1632        git merge xc &&
1633        git checkout -b xcb xc -- &&
1634        git branch --set-upstream-to=xbc &&
1635        git merge xb &&
1636        git checkout xbc &&
1637        test_commit D &&
1638        git checkout xcb &&
1639        test_commit E &&
1640        test_must_fail  git format-patch --base=auto -1
1641'
1642
1643test_expect_success 'format-patch format.useAutoBaseoption' '
1644        test_when_finished "git config --unset format.useAutoBase" &&
1645        git checkout local &&
1646        git config format.useAutoBase true &&
1647        git format-patch --stdout -1 >patch &&
1648        grep "^base-commit:" patch >actual &&
1649        echo "base-commit: $(git rev-parse upstream)" >expected &&
1650        test_cmp expected actual
1651'
1652
1653test_expect_success 'format-patch --base overrides format.useAutoBase' '
1654        test_when_finished "git config --unset format.useAutoBase" &&
1655        git config format.useAutoBase true &&
1656        git format-patch --stdout --base=HEAD~1 -1 >patch &&
1657        grep "^base-commit:" patch >actual &&
1658        echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
1659        test_cmp expected actual
1660'
1661
1662test_expect_success 'format-patch --base with --attach' '
1663        git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
1664        sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
1665                patch >actual &&
1666        test_write_lines 1 2 >expect &&
1667        test_cmp expect actual
1668'
1669test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
1670        test_when_finished "rm -fr patches" &&
1671        git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
1672        ! egrep "^--+mimemime" patches/0000*.patch &&
1673        egrep "^--+mimemime$" patches/0001*.patch >output &&
1674        test_line_count = 2 output &&
1675        egrep "^--+mimemime--$" patches/0001*.patch >output &&
1676        test_line_count = 1 output
1677'
1678
1679test_expect_success 'format-patch --pretty=mboxrd' '
1680        sp=" " &&
1681        cat >msg <<-INPUT_END &&
1682        mboxrd should escape the body
1683
1684        From could trip up a loose mbox parser
1685        >From extra escape for reversibility
1686        >>From extra escape for reversibility 2
1687        from lower case not escaped
1688        Fromm bad speling not escaped
1689         From with leading space not escaped
1690
1691        F
1692        From
1693        From$sp
1694        From    $sp
1695        From    $sp
1696        INPUT_END
1697
1698        cat >expect <<-INPUT_END &&
1699        >From could trip up a loose mbox parser
1700        >>From extra escape for reversibility
1701        >>>From extra escape for reversibility 2
1702        from lower case not escaped
1703        Fromm bad speling not escaped
1704         From with leading space not escaped
1705
1706        F
1707        From
1708        From
1709        From
1710        From
1711        INPUT_END
1712
1713        C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
1714        git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
1715        git grep -h --no-index -A11 \
1716                "^>From could trip up a loose mbox parser" patch >actual &&
1717        test_cmp expect actual
1718'
1719
1720test_expect_success 'interdiff: setup' '
1721        git checkout -b boop master &&
1722        test_commit fnorp blorp &&
1723        test_commit fleep blorp
1724'
1725
1726test_expect_success 'interdiff: cover-letter' '
1727        sed "y/q/ /" >expect <<-\EOF &&
1728        +fleep
1729        --q
1730        EOF
1731        git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
1732        test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch &&
1733        test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch &&
1734        sed "1,/^@@ /d; /^-- $/q" <0000-cover-letter.patch >actual &&
1735        test_cmp expect actual
1736'
1737
1738test_expect_success 'interdiff: reroll-count' '
1739        git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
1740        test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
1741'
1742
1743test_expect_success 'interdiff: solo-patch' '
1744        cat >expect <<-\EOF &&
1745          +fleep
1746
1747        EOF
1748        git format-patch --interdiff=boop~2 -1 boop &&
1749        test_i18ngrep "^Interdiff:$" 0001-fleep.patch &&
1750        sed "1,/^  @@ /d; /^$/q" <0001-fleep.patch >actual &&
1751        test_cmp expect actual
1752'
1753
1754test_done