830ddb0cbe6749154a74d6e8d255ff4a8659f221
   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 'multiple files' '
 161
 162        rm -rf patches/ &&
 163        git checkout side &&
 164        git format-patch -o patches/ master &&
 165        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
 166'
 167
 168check_threading () {
 169        expect="$1" &&
 170        shift &&
 171        (git format-patch --stdout "$@"; echo $? > status.out) |
 172        # Prints everything between the Message-ID and In-Reply-To,
 173        # and replaces all Message-ID-lookalikes by a sequence number
 174        perl -ne '
 175                if (/^(message-id|references|in-reply-to)/i) {
 176                        $printing = 1;
 177                } elsif (/^\S/) {
 178                        $printing = 0;
 179                }
 180                if ($printing) {
 181                        $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
 182                        for $k (keys %h) {s/$k/$h{$k}/};
 183                        print;
 184                }
 185                print "---\n" if /^From /i;
 186        ' > actual &&
 187        test 0 = "$(cat status.out)" &&
 188        test_cmp "$expect" actual
 189}
 190
 191cat >> expect.no-threading <<EOF
 192---
 193---
 194---
 195EOF
 196
 197test_expect_success 'no threading' '
 198        git checkout side &&
 199        check_threading expect.no-threading master
 200'
 201
 202cat > expect.thread <<EOF
 203---
 204Message-Id: <0>
 205---
 206Message-Id: <1>
 207In-Reply-To: <0>
 208References: <0>
 209---
 210Message-Id: <2>
 211In-Reply-To: <0>
 212References: <0>
 213EOF
 214
 215test_expect_success 'thread' '
 216        check_threading expect.thread --thread master
 217'
 218
 219cat > expect.in-reply-to <<EOF
 220---
 221Message-Id: <0>
 222In-Reply-To: <1>
 223References: <1>
 224---
 225Message-Id: <2>
 226In-Reply-To: <1>
 227References: <1>
 228---
 229Message-Id: <3>
 230In-Reply-To: <1>
 231References: <1>
 232EOF
 233
 234test_expect_success 'thread in-reply-to' '
 235        check_threading expect.in-reply-to --in-reply-to="<test.message>" \
 236                --thread master
 237'
 238
 239cat > expect.cover-letter <<EOF
 240---
 241Message-Id: <0>
 242---
 243Message-Id: <1>
 244In-Reply-To: <0>
 245References: <0>
 246---
 247Message-Id: <2>
 248In-Reply-To: <0>
 249References: <0>
 250---
 251Message-Id: <3>
 252In-Reply-To: <0>
 253References: <0>
 254EOF
 255
 256test_expect_success 'thread cover-letter' '
 257        check_threading expect.cover-letter --cover-letter --thread master
 258'
 259
 260cat > expect.cl-irt <<EOF
 261---
 262Message-Id: <0>
 263In-Reply-To: <1>
 264References: <1>
 265---
 266Message-Id: <2>
 267In-Reply-To: <0>
 268References: <1>
 269        <0>
 270---
 271Message-Id: <3>
 272In-Reply-To: <0>
 273References: <1>
 274        <0>
 275---
 276Message-Id: <4>
 277In-Reply-To: <0>
 278References: <1>
 279        <0>
 280EOF
 281
 282test_expect_success 'thread cover-letter in-reply-to' '
 283        check_threading expect.cl-irt --cover-letter \
 284                --in-reply-to="<test.message>" --thread master
 285'
 286
 287test_expect_success 'thread explicit shallow' '
 288        check_threading expect.cl-irt --cover-letter \
 289                --in-reply-to="<test.message>" --thread=shallow master
 290'
 291
 292cat > expect.deep <<EOF
 293---
 294Message-Id: <0>
 295---
 296Message-Id: <1>
 297In-Reply-To: <0>
 298References: <0>
 299---
 300Message-Id: <2>
 301In-Reply-To: <1>
 302References: <0>
 303        <1>
 304EOF
 305
 306test_expect_success 'thread deep' '
 307        check_threading expect.deep --thread=deep master
 308'
 309
 310cat > expect.deep-irt <<EOF
 311---
 312Message-Id: <0>
 313In-Reply-To: <1>
 314References: <1>
 315---
 316Message-Id: <2>
 317In-Reply-To: <0>
 318References: <1>
 319        <0>
 320---
 321Message-Id: <3>
 322In-Reply-To: <2>
 323References: <1>
 324        <0>
 325        <2>
 326EOF
 327
 328test_expect_success 'thread deep in-reply-to' '
 329        check_threading expect.deep-irt  --thread=deep \
 330                --in-reply-to="<test.message>" master
 331'
 332
 333cat > expect.deep-cl <<EOF
 334---
 335Message-Id: <0>
 336---
 337Message-Id: <1>
 338In-Reply-To: <0>
 339References: <0>
 340---
 341Message-Id: <2>
 342In-Reply-To: <1>
 343References: <0>
 344        <1>
 345---
 346Message-Id: <3>
 347In-Reply-To: <2>
 348References: <0>
 349        <1>
 350        <2>
 351EOF
 352
 353test_expect_success 'thread deep cover-letter' '
 354        check_threading expect.deep-cl --cover-letter --thread=deep master
 355'
 356
 357cat > expect.deep-cl-irt <<EOF
 358---
 359Message-Id: <0>
 360In-Reply-To: <1>
 361References: <1>
 362---
 363Message-Id: <2>
 364In-Reply-To: <0>
 365References: <1>
 366        <0>
 367---
 368Message-Id: <3>
 369In-Reply-To: <2>
 370References: <1>
 371        <0>
 372        <2>
 373---
 374Message-Id: <4>
 375In-Reply-To: <3>
 376References: <1>
 377        <0>
 378        <2>
 379        <3>
 380EOF
 381
 382test_expect_success 'thread deep cover-letter in-reply-to' '
 383        check_threading expect.deep-cl-irt --cover-letter \
 384                --in-reply-to="<test.message>" --thread=deep master
 385'
 386
 387test_expect_success 'thread via config' '
 388        git config format.thread true &&
 389        check_threading expect.thread master
 390'
 391
 392test_expect_success 'thread deep via config' '
 393        git config format.thread deep &&
 394        check_threading expect.deep master
 395'
 396
 397test_expect_success 'thread config + override' '
 398        git config format.thread deep &&
 399        check_threading expect.thread --thread master
 400'
 401
 402test_expect_success 'thread config + --no-thread' '
 403        git config format.thread deep &&
 404        check_threading expect.no-threading --no-thread master
 405'
 406
 407test_expect_success 'excessive subject' '
 408
 409        rm -rf patches/ &&
 410        git checkout side &&
 411        for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
 412        git update-index file &&
 413        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." &&
 414        git format-patch -o patches/ master..side &&
 415        ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
 416'
 417
 418test_expect_success 'cover-letter inherits diff options' '
 419
 420        git mv file foo &&
 421        git commit -m foo &&
 422        git format-patch --cover-letter -1 &&
 423        ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
 424        git format-patch --cover-letter -1 -M &&
 425        grep "file => foo .* 0 *\$" 0000-cover-letter.patch
 426
 427'
 428
 429cat > expect << EOF
 430  This is an excessively long subject line for a message due to the
 431    habit some projects have of not having a short, one-line subject at
 432    the start of the commit message, but rather sticking a whole
 433    paragraph right at the start as the only thing in the commit
 434    message. It had better not become the filename for the patch.
 435  foo
 436
 437EOF
 438
 439test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
 440
 441        git format-patch --cover-letter -2 &&
 442        sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
 443        test_cmp expect output
 444
 445'
 446
 447cat > expect << EOF
 448---
 449 file |   16 ++++++++++++++++
 450 1 files changed, 16 insertions(+), 0 deletions(-)
 451
 452diff --git a/file b/file
 453index 40f36c6..2dc5c23 100644
 454--- a/file
 455+++ b/file
 456@@ -13,4 +13,20 @@ C
 457 10
 458 D
 459 E
 460 F
 461+5
 462EOF
 463
 464test_expect_success 'format-patch respects -U' '
 465
 466        git format-patch -U4 -2 &&
 467        sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
 468        test_cmp expect output
 469
 470'
 471
 472cat > expect << EOF
 473
 474diff --git a/file b/file
 475index 40f36c6..2dc5c23 100644
 476--- a/file
 477+++ b/file
 478@@ -14,3 +14,19 @@ C
 479 D
 480 E
 481 F
 482+5
 483EOF
 484
 485test_expect_success 'format-patch -p suppresses stat' '
 486
 487        git format-patch -p -2 &&
 488        sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
 489        test_cmp expect output
 490
 491'
 492
 493test_expect_success 'format-patch from a subdirectory (1)' '
 494        filename=$(
 495                rm -rf sub &&
 496                mkdir -p sub/dir &&
 497                cd sub/dir &&
 498                git format-patch -1
 499        ) &&
 500        case "$filename" in
 501        0*)
 502                ;; # ok
 503        *)
 504                echo "Oops? $filename"
 505                false
 506                ;;
 507        esac &&
 508        test -f "$filename"
 509'
 510
 511test_expect_success 'format-patch from a subdirectory (2)' '
 512        filename=$(
 513                rm -rf sub &&
 514                mkdir -p sub/dir &&
 515                cd sub/dir &&
 516                git format-patch -1 -o ..
 517        ) &&
 518        case "$filename" in
 519        ../0*)
 520                ;; # ok
 521        *)
 522                echo "Oops? $filename"
 523                false
 524                ;;
 525        esac &&
 526        basename=$(expr "$filename" : ".*/\(.*\)") &&
 527        test -f "sub/$basename"
 528'
 529
 530test_expect_success 'format-patch from a subdirectory (3)' '
 531        rm -f 0* &&
 532        filename=$(
 533                rm -rf sub &&
 534                mkdir -p sub/dir &&
 535                cd sub/dir &&
 536                git format-patch -1 -o "$TRASH_DIRECTORY"
 537        ) &&
 538        basename=$(expr "$filename" : ".*/\(.*\)") &&
 539        test -f "$basename"
 540'
 541
 542test_expect_success 'format-patch --in-reply-to' '
 543        git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
 544        grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
 545        grep "^References: <baz@foo.bar>" patch8
 546'
 547
 548test_expect_success 'format-patch --signoff' '
 549        git format-patch -1 --signoff --stdout |
 550        grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
 551'
 552
 553echo "fatal: --name-only does not make sense" > expect.name-only
 554echo "fatal: --name-status does not make sense" > expect.name-status
 555echo "fatal: --check does not make sense" > expect.check
 556
 557test_expect_success 'options no longer allowed for format-patch' '
 558        test_must_fail git format-patch --name-only 2> output &&
 559        test_cmp expect.name-only output &&
 560        test_must_fail git format-patch --name-status 2> output &&
 561        test_cmp expect.name-status output &&
 562        test_must_fail git format-patch --check 2> output &&
 563        test_cmp expect.check output'
 564
 565test_expect_success 'format-patch --numstat should produce a patch' '
 566        git format-patch --numstat --stdout master..side > output &&
 567        test 6 = $(grep "^diff --git a/" output | wc -l)'
 568
 569test_expect_success 'format-patch -- <path>' '
 570        git format-patch master..side -- file 2>error &&
 571        ! grep "Use .--" error
 572'
 573
 574test_done