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