Merge branch 'jk/maint-rev-list-nul'
[alt-git.git] / t / t4014-format-patch.sh
blob07bf6eb49dd2879758f64a8c09a0ae8d7e54dd45
1 #!/bin/sh
3 # Copyright (c) 2006 Junio C Hamano
6 test_description='various format-patch tests'
8 . ./test-lib.sh
10 test_expect_success setup '
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 &&
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" &&
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 &&
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." &&
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"
42 test_expect_success "format-patch --ignore-if-in-upstream" '
44 git format-patch --stdout master..side >patch0 &&
45 cnt=`grep "^From " patch0 | wc -l` &&
46 test $cnt = 3
50 test_expect_success "format-patch --ignore-if-in-upstream" '
52 git format-patch --stdout \
53 --ignore-if-in-upstream master..side >patch1 &&
54 cnt=`grep "^From " patch1 | wc -l` &&
55 test $cnt = 2
59 test_expect_success "format-patch doesn't consider merge commits" '
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
75 test_expect_success "format-patch result applies" '
77 git checkout -b rebuild-0 master &&
78 git am -3 patch0 &&
79 cnt=`git rev-list master.. | wc -l` &&
80 test $cnt = 2
83 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
85 git checkout -b rebuild-1 master &&
86 git am -3 patch1 &&
87 cnt=`git rev-list master.. | wc -l` &&
88 test $cnt = 2
91 test_expect_success 'commit did not screw up the log message' '
93 git cat-file commit side | grep "^Side .* with .* backslash-n"
97 test_expect_success 'format-patch did not screw up the log message' '
99 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
100 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
104 test_expect_success 'replay did not screw up the log message' '
106 git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
110 test_expect_success 'extra headers' '
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
123 test_expect_success 'extra headers without newlines' '
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
134 test_expect_success 'extra headers with multiple To:s' '
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
144 test_expect_success 'additional command line cc' '
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
152 test_expect_success 'command line headers' '
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
159 test_expect_success 'configuration headers and command line headers' '
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
167 test_expect_success 'command line To: header' '
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
174 test_expect_success 'configuration To: header' '
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
181 test_expect_success '--no-to overrides config.to' '
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
190 test_expect_success '--no-to and --to replaces config.to' '
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
201 test_expect_success '--no-cc overrides config.cc' '
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
210 test_expect_success '--no-add-headers overrides config.headers' '
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
219 test_expect_success 'multiple files' '
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
227 check_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;
239 if ($printing) {
240 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
241 for $k (keys %h) {s/$k/$h{$k}/};
242 print;
244 print "---\n" if /^From /i;
245 ' > actual &&
246 test 0 = "$(cat status.out)" &&
247 test_cmp "$expect" actual
250 cat >> expect.no-threading <<EOF
256 test_expect_success 'no threading' '
257 git checkout side &&
258 check_threading expect.no-threading master
261 cat > expect.thread <<EOF
263 Message-Id: <0>
265 Message-Id: <1>
266 In-Reply-To: <0>
267 References: <0>
269 Message-Id: <2>
270 In-Reply-To: <0>
271 References: <0>
274 test_expect_success 'thread' '
275 check_threading expect.thread --thread master
278 cat > expect.in-reply-to <<EOF
280 Message-Id: <0>
281 In-Reply-To: <1>
282 References: <1>
284 Message-Id: <2>
285 In-Reply-To: <1>
286 References: <1>
288 Message-Id: <3>
289 In-Reply-To: <1>
290 References: <1>
293 test_expect_success 'thread in-reply-to' '
294 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
295 --thread master
298 cat > expect.cover-letter <<EOF
300 Message-Id: <0>
302 Message-Id: <1>
303 In-Reply-To: <0>
304 References: <0>
306 Message-Id: <2>
307 In-Reply-To: <0>
308 References: <0>
310 Message-Id: <3>
311 In-Reply-To: <0>
312 References: <0>
315 test_expect_success 'thread cover-letter' '
316 check_threading expect.cover-letter --cover-letter --thread master
319 cat > expect.cl-irt <<EOF
321 Message-Id: <0>
322 In-Reply-To: <1>
323 References: <1>
325 Message-Id: <2>
326 In-Reply-To: <0>
327 References: <1>
330 Message-Id: <3>
331 In-Reply-To: <0>
332 References: <1>
335 Message-Id: <4>
336 In-Reply-To: <0>
337 References: <1>
341 test_expect_success 'thread cover-letter in-reply-to' '
342 check_threading expect.cl-irt --cover-letter \
343 --in-reply-to="<test.message>" --thread master
346 test_expect_success 'thread explicit shallow' '
347 check_threading expect.cl-irt --cover-letter \
348 --in-reply-to="<test.message>" --thread=shallow master
351 cat > expect.deep <<EOF
353 Message-Id: <0>
355 Message-Id: <1>
356 In-Reply-To: <0>
357 References: <0>
359 Message-Id: <2>
360 In-Reply-To: <1>
361 References: <0>
365 test_expect_success 'thread deep' '
366 check_threading expect.deep --thread=deep master
369 cat > expect.deep-irt <<EOF
371 Message-Id: <0>
372 In-Reply-To: <1>
373 References: <1>
375 Message-Id: <2>
376 In-Reply-To: <0>
377 References: <1>
380 Message-Id: <3>
381 In-Reply-To: <2>
382 References: <1>
387 test_expect_success 'thread deep in-reply-to' '
388 check_threading expect.deep-irt --thread=deep \
389 --in-reply-to="<test.message>" master
392 cat > expect.deep-cl <<EOF
394 Message-Id: <0>
396 Message-Id: <1>
397 In-Reply-To: <0>
398 References: <0>
400 Message-Id: <2>
401 In-Reply-To: <1>
402 References: <0>
405 Message-Id: <3>
406 In-Reply-To: <2>
407 References: <0>
412 test_expect_success 'thread deep cover-letter' '
413 check_threading expect.deep-cl --cover-letter --thread=deep master
416 cat > expect.deep-cl-irt <<EOF
418 Message-Id: <0>
419 In-Reply-To: <1>
420 References: <1>
422 Message-Id: <2>
423 In-Reply-To: <0>
424 References: <1>
427 Message-Id: <3>
428 In-Reply-To: <2>
429 References: <1>
433 Message-Id: <4>
434 In-Reply-To: <3>
435 References: <1>
441 test_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
446 test_expect_success 'thread via config' '
447 git config format.thread true &&
448 check_threading expect.thread master
451 test_expect_success 'thread deep via config' '
452 git config format.thread deep &&
453 check_threading expect.deep master
456 test_expect_success 'thread config + override' '
457 git config format.thread deep &&
458 check_threading expect.thread --thread master
461 test_expect_success 'thread config + --no-thread' '
462 git config format.thread deep &&
463 check_threading expect.no-threading --no-thread master
466 test_expect_success 'excessive subject' '
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
477 test_expect_success 'cover-letter inherits diff options' '
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
488 cat > 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.
498 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
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
506 cat > expect << EOF
508 file | 16 ++++++++++++++++
509 1 files changed, 16 insertions(+), 0 deletions(-)
511 diff --git a/file b/file
512 index 40f36c6..2dc5c23 100644
513 --- a/file
514 +++ b/file
515 @@ -13,4 +13,20 @@ C
523 test_expect_success 'format-patch respects -U' '
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
531 cat > expect << EOF
533 diff --git a/file b/file
534 index 40f36c6..2dc5c23 100644
535 --- a/file
536 +++ b/file
537 @@ -14,3 +14,19 @@ C
544 test_expect_success 'format-patch -p suppresses stat' '
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
552 test_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
561 ;; # ok
563 echo "Oops? $filename"
564 false
566 esac &&
567 test -f "$filename"
570 test_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
581 echo "Oops? $filename"
582 false
584 esac &&
585 basename=$(expr "$filename" : ".*/\(.*\)") &&
586 test -f "sub/$basename"
589 test_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"
601 test_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
607 test_expect_success 'format-patch --signoff' '
608 git format-patch -1 --signoff --stdout |
609 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
612 echo "fatal: --name-only does not make sense" > expect.name-only
613 echo "fatal: --name-status does not make sense" > expect.name-status
614 echo "fatal: --check does not make sense" > expect.check
616 test_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'
624 test_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)'
628 test_expect_success 'format-patch -- <path>' '
629 git format-patch master..side -- file 2>error &&
630 ! grep "Use .--" error
633 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
634 git format-patch --ignore-if-in-upstream HEAD
637 test_expect_success 'format-patch --signature' '
638 git format-patch --stdout --signature="my sig" -1 >output &&
639 grep "my sig" output
642 test_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
648 test_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
655 test_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
664 test_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)
672 test_expect_success 'format.signature="" supresses signatures' '
673 git config format.signature "" &&
674 git format-patch --stdout -1 >output &&
675 ! grep "^-- \$" output
678 test_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
684 test_expect_success 'format-patch --signature="" supresses signatures' '
685 git format-patch --signature="" -1 >output &&
686 ! grep "^-- \$" output
689 test_done