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