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