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