vcs-svn: tweak test-line-buffer to not assume line-oriented input
[git/mjg.git] / t / t4014-format-patch.sh
blob027c13d52cd701ba28e3c5e29c5431acfccdad73
1 #!/bin/sh
3 # Copyright (c) 2006 Junio C Hamano
6 test_description='various format-patch tests'
8 . ./test-lib.sh
9 . "$TEST_DIRECTORY"/lib-terminal.sh
11 test_expect_success setup '
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 &&
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" &&
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 &&
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." &&
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"
43 test_expect_success "format-patch --ignore-if-in-upstream" '
45 git format-patch --stdout master..side >patch0 &&
46 cnt=`grep "^From " patch0 | wc -l` &&
47 test $cnt = 3
51 test_expect_success "format-patch --ignore-if-in-upstream" '
53 git format-patch --stdout \
54 --ignore-if-in-upstream master..side >patch1 &&
55 cnt=`grep "^From " patch1 | wc -l` &&
56 test $cnt = 2
60 test_expect_success "format-patch doesn't consider merge commits" '
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
76 test_expect_success "format-patch result applies" '
78 git checkout -b rebuild-0 master &&
79 git am -3 patch0 &&
80 cnt=`git rev-list master.. | wc -l` &&
81 test $cnt = 2
84 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
86 git checkout -b rebuild-1 master &&
87 git am -3 patch1 &&
88 cnt=`git rev-list master.. | wc -l` &&
89 test $cnt = 2
92 test_expect_success 'commit did not screw up the log message' '
94 git cat-file commit side | grep "^Side .* with .* backslash-n"
98 test_expect_success 'format-patch did not screw up the log message' '
100 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
101 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
105 test_expect_success 'replay did not screw up the log message' '
107 git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
111 test_expect_success 'extra headers' '
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
124 test_expect_success 'extra headers without newlines' '
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
135 test_expect_success 'extra headers with multiple To:s' '
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
145 test_expect_success 'additional command line cc' '
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
153 test_expect_success 'command line headers' '
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
160 test_expect_success 'configuration headers and command line headers' '
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
168 test_expect_success 'command line To: header' '
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
175 test_expect_success 'configuration To: header' '
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
182 test_expect_success '--no-to overrides config.to' '
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
191 test_expect_success '--no-to and --to replaces config.to' '
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
202 test_expect_success '--no-cc overrides config.cc' '
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
211 test_expect_success '--no-add-headers overrides config.headers' '
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
220 test_expect_success 'multiple files' '
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
228 check_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;
240 if ($printing) {
241 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
242 for $k (keys %h) {s/$k/$h{$k}/};
243 print;
245 print "---\n" if /^From /i;
246 ' > actual &&
247 test 0 = "$(cat status.out)" &&
248 test_cmp "$expect" actual
251 cat >> expect.no-threading <<EOF
257 test_expect_success 'no threading' '
258 git checkout side &&
259 check_threading expect.no-threading master
262 cat > expect.thread <<EOF
264 Message-Id: <0>
266 Message-Id: <1>
267 In-Reply-To: <0>
268 References: <0>
270 Message-Id: <2>
271 In-Reply-To: <0>
272 References: <0>
275 test_expect_success 'thread' '
276 check_threading expect.thread --thread master
279 cat > expect.in-reply-to <<EOF
281 Message-Id: <0>
282 In-Reply-To: <1>
283 References: <1>
285 Message-Id: <2>
286 In-Reply-To: <1>
287 References: <1>
289 Message-Id: <3>
290 In-Reply-To: <1>
291 References: <1>
294 test_expect_success 'thread in-reply-to' '
295 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
296 --thread master
299 cat > expect.cover-letter <<EOF
301 Message-Id: <0>
303 Message-Id: <1>
304 In-Reply-To: <0>
305 References: <0>
307 Message-Id: <2>
308 In-Reply-To: <0>
309 References: <0>
311 Message-Id: <3>
312 In-Reply-To: <0>
313 References: <0>
316 test_expect_success 'thread cover-letter' '
317 check_threading expect.cover-letter --cover-letter --thread master
320 cat > expect.cl-irt <<EOF
322 Message-Id: <0>
323 In-Reply-To: <1>
324 References: <1>
326 Message-Id: <2>
327 In-Reply-To: <0>
328 References: <1>
331 Message-Id: <3>
332 In-Reply-To: <0>
333 References: <1>
336 Message-Id: <4>
337 In-Reply-To: <0>
338 References: <1>
342 test_expect_success 'thread cover-letter in-reply-to' '
343 check_threading expect.cl-irt --cover-letter \
344 --in-reply-to="<test.message>" --thread master
347 test_expect_success 'thread explicit shallow' '
348 check_threading expect.cl-irt --cover-letter \
349 --in-reply-to="<test.message>" --thread=shallow master
352 cat > expect.deep <<EOF
354 Message-Id: <0>
356 Message-Id: <1>
357 In-Reply-To: <0>
358 References: <0>
360 Message-Id: <2>
361 In-Reply-To: <1>
362 References: <0>
366 test_expect_success 'thread deep' '
367 check_threading expect.deep --thread=deep master
370 cat > expect.deep-irt <<EOF
372 Message-Id: <0>
373 In-Reply-To: <1>
374 References: <1>
376 Message-Id: <2>
377 In-Reply-To: <0>
378 References: <1>
381 Message-Id: <3>
382 In-Reply-To: <2>
383 References: <1>
388 test_expect_success 'thread deep in-reply-to' '
389 check_threading expect.deep-irt --thread=deep \
390 --in-reply-to="<test.message>" master
393 cat > expect.deep-cl <<EOF
395 Message-Id: <0>
397 Message-Id: <1>
398 In-Reply-To: <0>
399 References: <0>
401 Message-Id: <2>
402 In-Reply-To: <1>
403 References: <0>
406 Message-Id: <3>
407 In-Reply-To: <2>
408 References: <0>
413 test_expect_success 'thread deep cover-letter' '
414 check_threading expect.deep-cl --cover-letter --thread=deep master
417 cat > expect.deep-cl-irt <<EOF
419 Message-Id: <0>
420 In-Reply-To: <1>
421 References: <1>
423 Message-Id: <2>
424 In-Reply-To: <0>
425 References: <1>
428 Message-Id: <3>
429 In-Reply-To: <2>
430 References: <1>
434 Message-Id: <4>
435 In-Reply-To: <3>
436 References: <1>
442 test_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
447 test_expect_success 'thread via config' '
448 git config format.thread true &&
449 check_threading expect.thread master
452 test_expect_success 'thread deep via config' '
453 git config format.thread deep &&
454 check_threading expect.deep master
457 test_expect_success 'thread config + override' '
458 git config format.thread deep &&
459 check_threading expect.thread --thread master
462 test_expect_success 'thread config + --no-thread' '
463 git config format.thread deep &&
464 check_threading expect.no-threading --no-thread master
467 test_expect_success 'excessive subject' '
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
478 test_expect_success 'cover-letter inherits diff options' '
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
489 cat > 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.
499 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
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
507 cat > expect << EOF
509 file | 16 ++++++++++++++++
510 1 files changed, 16 insertions(+), 0 deletions(-)
512 diff --git a/file b/file
513 index 40f36c6..2dc5c23 100644
514 --- a/file
515 +++ b/file
516 @@ -13,4 +13,20 @@ C
524 test_expect_success 'format-patch respects -U' '
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
532 cat > expect << EOF
534 diff --git a/file b/file
535 index 40f36c6..2dc5c23 100644
536 --- a/file
537 +++ b/file
538 @@ -14,3 +14,19 @@ C
545 test_expect_success 'format-patch -p suppresses stat' '
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
553 test_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
562 ;; # ok
564 echo "Oops? $filename"
565 false
567 esac &&
568 test -f "$filename"
571 test_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
582 echo "Oops? $filename"
583 false
585 esac &&
586 basename=$(expr "$filename" : ".*/\(.*\)") &&
587 test -f "sub/$basename"
590 test_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"
602 test_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
608 test_expect_success 'format-patch --signoff' '
609 git format-patch -1 --signoff --stdout |
610 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
613 echo "fatal: --name-only does not make sense" > expect.name-only
614 echo "fatal: --name-status does not make sense" > expect.name-status
615 echo "fatal: --check does not make sense" > expect.check
617 test_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'
625 test_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)'
629 test_expect_success 'format-patch -- <path>' '
630 git format-patch master..side -- file 2>error &&
631 ! grep "Use .--" error
634 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
635 git format-patch --ignore-if-in-upstream HEAD
638 test_expect_success 'format-patch --signature' '
639 git format-patch --stdout --signature="my sig" -1 >output &&
640 grep "my sig" output
643 test_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
649 test_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
656 test_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
665 test_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)
673 test_expect_success 'format.signature="" supresses signatures' '
674 git config format.signature "" &&
675 git format-patch --stdout -1 >output &&
676 ! grep "^-- \$" output
679 test_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
685 test_expect_success 'format-patch --signature="" supresses signatures' '
686 git format-patch --signature="" -1 >output &&
687 ! grep "^-- \$" output
690 test_expect_success TTY 'format-patch --stdout paginates' '
691 rm -f pager_used &&
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
700 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
701 rm -f pager_used &&
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
712 test_done