t / t4014-format-patch.shon commit send-email: add --no-cc, --no-to, and --no-bcc (f434c08)
   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
  10test_expect_success setup '
  11
  12        for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
  13        cat file >elif &&
  14        git add file elif &&
  15        git commit -m Initial &&
  16        git checkout -b side &&
  17
  18        for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
  19        test_chmod +x elif &&
  20        git commit -m "Side changes #1" &&
  21
  22        for i in D E F; do echo "$i"; done >>file &&
  23        git update-index file &&
  24        git commit -m "Side changes #2" &&
  25        git tag C2 &&
  26
  27        for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
  28        git update-index file &&
  29        git commit -m "Side changes #3 with \\n backslash-n in it." &&
  30
  31        git checkout master &&
  32        git diff-tree -p C2 | git apply --index &&
  33        git commit -m "Master accepts moral equivalent of #2"
  34
  35'
  36
  37test_expect_success "format-patch --ignore-if-in-upstream" '
  38
  39        git format-patch --stdout master..side >patch0 &&
  40        cnt=`grep "^From " patch0 | wc -l` &&
  41        test $cnt = 3
  42
  43'
  44
  45test_expect_success "format-patch --ignore-if-in-upstream" '
  46
  47        git format-patch --stdout \
  48                --ignore-if-in-upstream master..side >patch1 &&
  49        cnt=`grep "^From " patch1 | wc -l` &&
  50        test $cnt = 2
  51
  52'
  53
  54test_expect_success "format-patch result applies" '
  55
  56        git checkout -b rebuild-0 master &&
  57        git am -3 patch0 &&
  58        cnt=`git rev-list master.. | wc -l` &&
  59        test $cnt = 2
  60'
  61
  62test_expect_success "format-patch --ignore-if-in-upstream result applies" '
  63
  64        git checkout -b rebuild-1 master &&
  65        git am -3 patch1 &&
  66        cnt=`git rev-list master.. | wc -l` &&
  67        test $cnt = 2
  68'
  69
  70test_expect_success 'commit did not screw up the log message' '
  71
  72        git cat-file commit side | grep "^Side .* with .* backslash-n"
  73
  74'
  75
  76test_expect_success 'format-patch did not screw up the log message' '
  77
  78        grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
  79        grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
  80
  81'
  82
  83test_expect_success 'replay did not screw up the log message' '
  84
  85        git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
  86
  87'
  88
  89test_expect_success 'extra headers' '
  90
  91        git config format.headers "To: R. E. Cipient <rcipient@example.com>
  92" &&
  93        git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>
  94" &&
  95        git format-patch --stdout master..side > patch2 &&
  96        sed -e "/^\$/q" patch2 > hdrs2 &&
  97        grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs2 &&
  98        grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs2
  99
 100'
 101
 102test_expect_success 'extra headers without newlines' '
 103
 104        git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
 105        git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>" &&
 106        git format-patch --stdout master..side >patch3 &&
 107        sed -e "/^\$/q" patch3 > hdrs3 &&
 108        grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs3 &&
 109        grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs3
 110
 111'
 112
 113test_expect_success 'extra headers with multiple To:s' '
 114
 115        git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
 116        git config --add format.headers "To: S. E. Cipient <scipient@example.com>" &&
 117        git format-patch --stdout master..side > patch4 &&
 118        sed -e "/^\$/q" patch4 > hdrs4 &&
 119        grep "^To: R. E. Cipient <rcipient@example.com>,\$" hdrs4 &&
 120        grep "^ *S. E. Cipient <scipient@example.com>\$" hdrs4
 121'
 122
 123test_expect_success 'additional command line cc' '
 124
 125        git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
 126        git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
 127        grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch5 &&
 128        grep "^ *S. E. Cipient <scipient@example.com>\$" patch5
 129'
 130
 131test_expect_success 'command line headers' '
 132
 133        git config --unset-all format.headers &&
 134        git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
 135        grep "^Cc: R. E. Cipient <rcipient@example.com>\$" patch6
 136'
 137
 138test_expect_success 'configuration headers and command line headers' '
 139
 140        git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
 141        git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
 142        grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch7 &&
 143        grep "^ *S. E. Cipient <scipient@example.com>\$" patch7
 144'
 145
 146test_expect_success 'command line To: header' '
 147
 148        git config --unset-all format.headers &&
 149        git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
 150        grep "^To: R. E. Cipient <rcipient@example.com>\$" patch8
 151'
 152
 153test_expect_success 'configuration To: header' '
 154
 155        git config format.to "R. E. Cipient <rcipient@example.com>" &&
 156        git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
 157        grep "^To: R. E. Cipient <rcipient@example.com>\$" patch9
 158'
 159
 160test_expect_success '--no-to overrides config.to' '
 161
 162        git config --replace-all format.to \
 163                "R. E. Cipient <rcipient@example.com>" &&
 164        git format-patch --no-to --stdout master..side |
 165        sed -e "/^\$/q" >patch10 &&
 166        ! grep "^To: R. E. Cipient <rcipient@example.com>\$" patch10
 167'
 168
 169test_expect_success '--no-to and --to replaces config.to' '
 170
 171        git config --replace-all format.to \
 172                "Someone <someone@out.there>" &&
 173        git format-patch --no-to --to="Someone Else <else@out.there>" \
 174                --stdout master..side |
 175        sed -e "/^\$/q" >patch11 &&
 176        ! grep "^To: Someone <someone@out.there>\$" patch11 &&
 177        grep "^To: Someone Else <else@out.there>\$" patch11
 178'
 179
 180test_expect_success '--no-cc overrides config.cc' '
 181
 182        git config --replace-all format.cc \
 183                "C. E. Cipient <rcipient@example.com>" &&
 184        git format-patch --no-cc --stdout master..side |
 185        sed -e "/^\$/q" >patch12 &&
 186        ! grep "^Cc: C. E. Cipient <rcipient@example.com>\$" patch12
 187'
 188
 189test_expect_success '--no-add-headers overrides config.headers' '
 190
 191        git config --replace-all format.headers \
 192                "Header1: B. E. Cipient <rcipient@example.com>" &&
 193        git format-patch --no-add-headers --stdout master..side |
 194        sed -e "/^\$/q" >patch13 &&
 195        ! grep "^Header1: B. E. Cipient <rcipient@example.com>\$" patch13
 196'
 197
 198test_expect_success 'multiple files' '
 199
 200        rm -rf patches/ &&
 201        git checkout side &&
 202        git format-patch -o patches/ master &&
 203        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
 204'
 205
 206check_threading () {
 207        expect="$1" &&
 208        shift &&
 209        (git format-patch --stdout "$@"; echo $? > status.out) |
 210        # Prints everything between the Message-ID and In-Reply-To,
 211        # and replaces all Message-ID-lookalikes by a sequence number
 212        perl -ne '
 213                if (/^(message-id|references|in-reply-to)/i) {
 214                        $printing = 1;
 215                } elsif (/^\S/) {
 216                        $printing = 0;
 217                }
 218                if ($printing) {
 219                        $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
 220                        for $k (keys %h) {s/$k/$h{$k}/};
 221                        print;
 222                }
 223                print "---\n" if /^From /i;
 224        ' > actual &&
 225        test 0 = "$(cat status.out)" &&
 226        test_cmp "$expect" actual
 227}
 228
 229cat >> expect.no-threading <<EOF
 230---
 231---
 232---
 233EOF
 234
 235test_expect_success 'no threading' '
 236        git checkout side &&
 237        check_threading expect.no-threading master
 238'
 239
 240cat > expect.thread <<EOF
 241---
 242Message-Id: <0>
 243---
 244Message-Id: <1>
 245In-Reply-To: <0>
 246References: <0>
 247---
 248Message-Id: <2>
 249In-Reply-To: <0>
 250References: <0>
 251EOF
 252
 253test_expect_success 'thread' '
 254        check_threading expect.thread --thread master
 255'
 256
 257cat > expect.in-reply-to <<EOF
 258---
 259Message-Id: <0>
 260In-Reply-To: <1>
 261References: <1>
 262---
 263Message-Id: <2>
 264In-Reply-To: <1>
 265References: <1>
 266---
 267Message-Id: <3>
 268In-Reply-To: <1>
 269References: <1>
 270EOF
 271
 272test_expect_success 'thread in-reply-to' '
 273        check_threading expect.in-reply-to --in-reply-to="<test.message>" \
 274                --thread master
 275'
 276
 277cat > expect.cover-letter <<EOF
 278---
 279Message-Id: <0>
 280---
 281Message-Id: <1>
 282In-Reply-To: <0>
 283References: <0>
 284---
 285Message-Id: <2>
 286In-Reply-To: <0>
 287References: <0>
 288---
 289Message-Id: <3>
 290In-Reply-To: <0>
 291References: <0>
 292EOF
 293
 294test_expect_success 'thread cover-letter' '
 295        check_threading expect.cover-letter --cover-letter --thread master
 296'
 297
 298cat > expect.cl-irt <<EOF
 299---
 300Message-Id: <0>
 301In-Reply-To: <1>
 302References: <1>
 303---
 304Message-Id: <2>
 305In-Reply-To: <0>
 306References: <1>
 307        <0>
 308---
 309Message-Id: <3>
 310In-Reply-To: <0>
 311References: <1>
 312        <0>
 313---
 314Message-Id: <4>
 315In-Reply-To: <0>
 316References: <1>
 317        <0>
 318EOF
 319
 320test_expect_success 'thread cover-letter in-reply-to' '
 321        check_threading expect.cl-irt --cover-letter \
 322                --in-reply-to="<test.message>" --thread master
 323'
 324
 325test_expect_success 'thread explicit shallow' '
 326        check_threading expect.cl-irt --cover-letter \
 327                --in-reply-to="<test.message>" --thread=shallow master
 328'
 329
 330cat > expect.deep <<EOF
 331---
 332Message-Id: <0>
 333---
 334Message-Id: <1>
 335In-Reply-To: <0>
 336References: <0>
 337---
 338Message-Id: <2>
 339In-Reply-To: <1>
 340References: <0>
 341        <1>
 342EOF
 343
 344test_expect_success 'thread deep' '
 345        check_threading expect.deep --thread=deep master
 346'
 347
 348cat > expect.deep-irt <<EOF
 349---
 350Message-Id: <0>
 351In-Reply-To: <1>
 352References: <1>
 353---
 354Message-Id: <2>
 355In-Reply-To: <0>
 356References: <1>
 357        <0>
 358---
 359Message-Id: <3>
 360In-Reply-To: <2>
 361References: <1>
 362        <0>
 363        <2>
 364EOF
 365
 366test_expect_success 'thread deep in-reply-to' '
 367        check_threading expect.deep-irt  --thread=deep \
 368                --in-reply-to="<test.message>" master
 369'
 370
 371cat > expect.deep-cl <<EOF
 372---
 373Message-Id: <0>
 374---
 375Message-Id: <1>
 376In-Reply-To: <0>
 377References: <0>
 378---
 379Message-Id: <2>
 380In-Reply-To: <1>
 381References: <0>
 382        <1>
 383---
 384Message-Id: <3>
 385In-Reply-To: <2>
 386References: <0>
 387        <1>
 388        <2>
 389EOF
 390
 391test_expect_success 'thread deep cover-letter' '
 392        check_threading expect.deep-cl --cover-letter --thread=deep master
 393'
 394
 395cat > expect.deep-cl-irt <<EOF
 396---
 397Message-Id: <0>
 398In-Reply-To: <1>
 399References: <1>
 400---
 401Message-Id: <2>
 402In-Reply-To: <0>
 403References: <1>
 404        <0>
 405---
 406Message-Id: <3>
 407In-Reply-To: <2>
 408References: <1>
 409        <0>
 410        <2>
 411---
 412Message-Id: <4>
 413In-Reply-To: <3>
 414References: <1>
 415        <0>
 416        <2>
 417        <3>
 418EOF
 419
 420test_expect_success 'thread deep cover-letter in-reply-to' '
 421        check_threading expect.deep-cl-irt --cover-letter \
 422                --in-reply-to="<test.message>" --thread=deep master
 423'
 424
 425test_expect_success 'thread via config' '
 426        git config format.thread true &&
 427        check_threading expect.thread master
 428'
 429
 430test_expect_success 'thread deep via config' '
 431        git config format.thread deep &&
 432        check_threading expect.deep master
 433'
 434
 435test_expect_success 'thread config + override' '
 436        git config format.thread deep &&
 437        check_threading expect.thread --thread master
 438'
 439
 440test_expect_success 'thread config + --no-thread' '
 441        git config format.thread deep &&
 442        check_threading expect.no-threading --no-thread master
 443'
 444
 445test_expect_success 'excessive subject' '
 446
 447        rm -rf patches/ &&
 448        git checkout side &&
 449        for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
 450        git update-index file &&
 451        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." &&
 452        git format-patch -o patches/ master..side &&
 453        ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
 454'
 455
 456test_expect_success 'cover-letter inherits diff options' '
 457
 458        git mv file foo &&
 459        git commit -m foo &&
 460        git format-patch --cover-letter -1 &&
 461        ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
 462        git format-patch --cover-letter -1 -M &&
 463        grep "file => foo .* 0 *\$" 0000-cover-letter.patch
 464
 465'
 466
 467cat > expect << EOF
 468  This is an excessively long subject line for a message due to the
 469    habit some projects have of not having a short, one-line subject at
 470    the start of the commit message, but rather sticking a whole
 471    paragraph right at the start as the only thing in the commit
 472    message. It had better not become the filename for the patch.
 473  foo
 474
 475EOF
 476
 477test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
 478
 479        git format-patch --cover-letter -2 &&
 480        sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
 481        test_cmp expect output
 482
 483'
 484
 485cat > expect << EOF
 486---
 487 file |   16 ++++++++++++++++
 488 1 files changed, 16 insertions(+), 0 deletions(-)
 489
 490diff --git a/file b/file
 491index 40f36c6..2dc5c23 100644
 492--- a/file
 493+++ b/file
 494@@ -13,4 +13,20 @@ C
 495 10
 496 D
 497 E
 498 F
 499+5
 500EOF
 501
 502test_expect_success 'format-patch respects -U' '
 503
 504        git format-patch -U4 -2 &&
 505        sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
 506        test_cmp expect output
 507
 508'
 509
 510cat > expect << EOF
 511
 512diff --git a/file b/file
 513index 40f36c6..2dc5c23 100644
 514--- a/file
 515+++ b/file
 516@@ -14,3 +14,19 @@ C
 517 D
 518 E
 519 F
 520+5
 521EOF
 522
 523test_expect_success 'format-patch -p suppresses stat' '
 524
 525        git format-patch -p -2 &&
 526        sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
 527        test_cmp expect output
 528
 529'
 530
 531test_expect_success 'format-patch from a subdirectory (1)' '
 532        filename=$(
 533                rm -rf sub &&
 534                mkdir -p sub/dir &&
 535                cd sub/dir &&
 536                git format-patch -1
 537        ) &&
 538        case "$filename" in
 539        0*)
 540                ;; # ok
 541        *)
 542                echo "Oops? $filename"
 543                false
 544                ;;
 545        esac &&
 546        test -f "$filename"
 547'
 548
 549test_expect_success 'format-patch from a subdirectory (2)' '
 550        filename=$(
 551                rm -rf sub &&
 552                mkdir -p sub/dir &&
 553                cd sub/dir &&
 554                git format-patch -1 -o ..
 555        ) &&
 556        case "$filename" in
 557        ../0*)
 558                ;; # ok
 559        *)
 560                echo "Oops? $filename"
 561                false
 562                ;;
 563        esac &&
 564        basename=$(expr "$filename" : ".*/\(.*\)") &&
 565        test -f "sub/$basename"
 566'
 567
 568test_expect_success 'format-patch from a subdirectory (3)' '
 569        rm -f 0* &&
 570        filename=$(
 571                rm -rf sub &&
 572                mkdir -p sub/dir &&
 573                cd sub/dir &&
 574                git format-patch -1 -o "$TRASH_DIRECTORY"
 575        ) &&
 576        basename=$(expr "$filename" : ".*/\(.*\)") &&
 577        test -f "$basename"
 578'
 579
 580test_expect_success 'format-patch --in-reply-to' '
 581        git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
 582        grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
 583        grep "^References: <baz@foo.bar>" patch8
 584'
 585
 586test_expect_success 'format-patch --signoff' '
 587        git format-patch -1 --signoff --stdout |
 588        grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
 589'
 590
 591echo "fatal: --name-only does not make sense" > expect.name-only
 592echo "fatal: --name-status does not make sense" > expect.name-status
 593echo "fatal: --check does not make sense" > expect.check
 594
 595test_expect_success 'options no longer allowed for format-patch' '
 596        test_must_fail git format-patch --name-only 2> output &&
 597        test_cmp expect.name-only output &&
 598        test_must_fail git format-patch --name-status 2> output &&
 599        test_cmp expect.name-status output &&
 600        test_must_fail git format-patch --check 2> output &&
 601        test_cmp expect.check output'
 602
 603test_expect_success 'format-patch --numstat should produce a patch' '
 604        git format-patch --numstat --stdout master..side > output &&
 605        test 6 = $(grep "^diff --git a/" output | wc -l)'
 606
 607test_expect_success 'format-patch -- <path>' '
 608        git format-patch master..side -- file 2>error &&
 609        ! grep "Use .--" error
 610'
 611
 612test_done