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