Merge branch 'fc/remote-helper-refmap'
[git.git] / t / t4014-format-patch.sh
blob282bee4a54c924b8168b6a28dfdbeb7ab300d7b7
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 (ascii)' '
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_failure 'additional command line cc (rfc822)' '
155 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
156 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
157 grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
158 grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" patch5
161 test_expect_success 'command line headers' '
163 git config --unset-all format.headers &&
164 git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
165 grep "^Cc: R E Cipient <rcipient@example.com>\$" patch6
168 test_expect_success 'configuration headers and command line headers' '
170 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
171 git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
172 grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch7 &&
173 grep "^ *S E Cipient <scipient@example.com>\$" patch7
176 test_expect_success 'command line To: header (ascii)' '
178 git config --unset-all format.headers &&
179 git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
180 grep "^To: R E Cipient <rcipient@example.com>\$" patch8
183 test_expect_failure 'command line To: header (rfc822)' '
185 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
186 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch8
189 test_expect_failure 'command line To: header (rfc2047)' '
191 git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
192 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch8
195 test_expect_success 'configuration To: header (ascii)' '
197 git config format.to "R E Cipient <rcipient@example.com>" &&
198 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
199 grep "^To: R E Cipient <rcipient@example.com>\$" patch9
202 test_expect_failure 'configuration To: header (rfc822)' '
204 git config format.to "R. E. Cipient <rcipient@example.com>" &&
205 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
206 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch9
209 test_expect_failure 'configuration To: header (rfc2047)' '
211 git config format.to "R Ä Cipient <rcipient@example.com>" &&
212 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
213 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch9
216 # check_patch <patch>: Verify that <patch> looks like a half-sane
217 # patch email to avoid a false positive with !grep
218 check_patch () {
219 grep -e "^From:" "$1" &&
220 grep -e "^Date:" "$1" &&
221 grep -e "^Subject:" "$1"
224 test_expect_success '--no-to overrides config.to' '
226 git config --replace-all format.to \
227 "R E Cipient <rcipient@example.com>" &&
228 git format-patch --no-to --stdout master..side |
229 sed -e "/^\$/q" >patch10 &&
230 check_patch patch10 &&
231 ! grep "^To: R E Cipient <rcipient@example.com>\$" patch10
234 test_expect_success '--no-to and --to replaces config.to' '
236 git config --replace-all format.to \
237 "Someone <someone@out.there>" &&
238 git format-patch --no-to --to="Someone Else <else@out.there>" \
239 --stdout master..side |
240 sed -e "/^\$/q" >patch11 &&
241 check_patch patch11 &&
242 ! grep "^To: Someone <someone@out.there>\$" patch11 &&
243 grep "^To: Someone Else <else@out.there>\$" patch11
246 test_expect_success '--no-cc overrides config.cc' '
248 git config --replace-all format.cc \
249 "C E Cipient <rcipient@example.com>" &&
250 git format-patch --no-cc --stdout master..side |
251 sed -e "/^\$/q" >patch12 &&
252 check_patch patch12 &&
253 ! grep "^Cc: C E Cipient <rcipient@example.com>\$" patch12
256 test_expect_success '--no-add-header overrides config.headers' '
258 git config --replace-all format.headers \
259 "Header1: B E Cipient <rcipient@example.com>" &&
260 git format-patch --no-add-header --stdout master..side |
261 sed -e "/^\$/q" >patch13 &&
262 check_patch patch13 &&
263 ! grep "^Header1: B E Cipient <rcipient@example.com>\$" patch13
266 test_expect_success 'multiple files' '
268 rm -rf patches/ &&
269 git checkout side &&
270 git format-patch -o patches/ master &&
271 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
274 test_expect_success 'reroll count' '
275 rm -fr patches &&
276 git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
277 ! grep -v "^patches/v4-000[0-3]-" list &&
278 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
279 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
282 test_expect_success 'reroll count (-v)' '
283 rm -fr patches &&
284 git format-patch -o patches --cover-letter -v4 master..side >list &&
285 ! grep -v "^patches/v4-000[0-3]-" list &&
286 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
287 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
290 check_threading () {
291 expect="$1" &&
292 shift &&
293 (git format-patch --stdout "$@"; echo $? > status.out) |
294 # Prints everything between the Message-ID and In-Reply-To,
295 # and replaces all Message-ID-lookalikes by a sequence number
296 perl -ne '
297 if (/^(message-id|references|in-reply-to)/i) {
298 $printing = 1;
299 } elsif (/^\S/) {
300 $printing = 0;
302 if ($printing) {
303 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
304 for $k (keys %h) {s/$k/$h{$k}/};
305 print;
307 print "---\n" if /^From /i;
308 ' > actual &&
309 test 0 = "$(cat status.out)" &&
310 test_cmp "$expect" actual
313 cat >> expect.no-threading <<EOF
319 test_expect_success 'no threading' '
320 git checkout side &&
321 check_threading expect.no-threading master
324 cat > expect.thread <<EOF
326 Message-Id: <0>
328 Message-Id: <1>
329 In-Reply-To: <0>
330 References: <0>
332 Message-Id: <2>
333 In-Reply-To: <0>
334 References: <0>
337 test_expect_success 'thread' '
338 check_threading expect.thread --thread master
341 cat > expect.in-reply-to <<EOF
343 Message-Id: <0>
344 In-Reply-To: <1>
345 References: <1>
347 Message-Id: <2>
348 In-Reply-To: <1>
349 References: <1>
351 Message-Id: <3>
352 In-Reply-To: <1>
353 References: <1>
356 test_expect_success 'thread in-reply-to' '
357 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
358 --thread master
361 cat > expect.cover-letter <<EOF
363 Message-Id: <0>
365 Message-Id: <1>
366 In-Reply-To: <0>
367 References: <0>
369 Message-Id: <2>
370 In-Reply-To: <0>
371 References: <0>
373 Message-Id: <3>
374 In-Reply-To: <0>
375 References: <0>
378 test_expect_success 'thread cover-letter' '
379 check_threading expect.cover-letter --cover-letter --thread master
382 cat > expect.cl-irt <<EOF
384 Message-Id: <0>
385 In-Reply-To: <1>
386 References: <1>
388 Message-Id: <2>
389 In-Reply-To: <0>
390 References: <1>
393 Message-Id: <3>
394 In-Reply-To: <0>
395 References: <1>
398 Message-Id: <4>
399 In-Reply-To: <0>
400 References: <1>
404 test_expect_success 'thread cover-letter in-reply-to' '
405 check_threading expect.cl-irt --cover-letter \
406 --in-reply-to="<test.message>" --thread master
409 test_expect_success 'thread explicit shallow' '
410 check_threading expect.cl-irt --cover-letter \
411 --in-reply-to="<test.message>" --thread=shallow master
414 cat > expect.deep <<EOF
416 Message-Id: <0>
418 Message-Id: <1>
419 In-Reply-To: <0>
420 References: <0>
422 Message-Id: <2>
423 In-Reply-To: <1>
424 References: <0>
428 test_expect_success 'thread deep' '
429 check_threading expect.deep --thread=deep master
432 cat > expect.deep-irt <<EOF
434 Message-Id: <0>
435 In-Reply-To: <1>
436 References: <1>
438 Message-Id: <2>
439 In-Reply-To: <0>
440 References: <1>
443 Message-Id: <3>
444 In-Reply-To: <2>
445 References: <1>
450 test_expect_success 'thread deep in-reply-to' '
451 check_threading expect.deep-irt --thread=deep \
452 --in-reply-to="<test.message>" master
455 cat > expect.deep-cl <<EOF
457 Message-Id: <0>
459 Message-Id: <1>
460 In-Reply-To: <0>
461 References: <0>
463 Message-Id: <2>
464 In-Reply-To: <1>
465 References: <0>
468 Message-Id: <3>
469 In-Reply-To: <2>
470 References: <0>
475 test_expect_success 'thread deep cover-letter' '
476 check_threading expect.deep-cl --cover-letter --thread=deep master
479 cat > expect.deep-cl-irt <<EOF
481 Message-Id: <0>
482 In-Reply-To: <1>
483 References: <1>
485 Message-Id: <2>
486 In-Reply-To: <0>
487 References: <1>
490 Message-Id: <3>
491 In-Reply-To: <2>
492 References: <1>
496 Message-Id: <4>
497 In-Reply-To: <3>
498 References: <1>
504 test_expect_success 'thread deep cover-letter in-reply-to' '
505 check_threading expect.deep-cl-irt --cover-letter \
506 --in-reply-to="<test.message>" --thread=deep master
509 test_expect_success 'thread via config' '
510 test_config format.thread true &&
511 check_threading expect.thread master
514 test_expect_success 'thread deep via config' '
515 test_config format.thread deep &&
516 check_threading expect.deep master
519 test_expect_success 'thread config + override' '
520 test_config format.thread deep &&
521 check_threading expect.thread --thread master
524 test_expect_success 'thread config + --no-thread' '
525 test_config format.thread deep &&
526 check_threading expect.no-threading --no-thread master
529 test_expect_success 'excessive subject' '
531 rm -rf patches/ &&
532 git checkout side &&
533 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
534 git update-index file &&
535 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." &&
536 git format-patch -o patches/ master..side &&
537 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
540 test_expect_success 'cover-letter inherits diff options' '
542 git mv file foo &&
543 git commit -m foo &&
544 git format-patch --cover-letter -1 &&
545 check_patch 0000-cover-letter.patch &&
546 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
547 git format-patch --cover-letter -1 -M &&
548 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
552 cat > expect << EOF
553 This is an excessively long subject line for a message due to the
554 habit some projects have of not having a short, one-line subject at
555 the start of the commit message, but rather sticking a whole
556 paragraph right at the start as the only thing in the commit
557 message. It had better not become the filename for the patch.
562 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
564 git format-patch --cover-letter -2 &&
565 sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
566 test_cmp expect output
570 cat > expect << EOF
571 index 40f36c6..2dc5c23 100644
572 --- a/file
573 +++ b/file
574 @@ -13,4 +13,20 @@ C
582 test_expect_success 'format-patch respects -U' '
584 git format-patch -U4 -2 &&
585 sed -e "1,/^diff/d" -e "/^+5/q" \
586 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
587 >output &&
588 test_cmp expect output
592 cat > expect << EOF
594 diff --git a/file b/file
595 index 40f36c6..2dc5c23 100644
596 --- a/file
597 +++ b/file
598 @@ -14,3 +14,19 @@ C
605 test_expect_success 'format-patch -p suppresses stat' '
607 git format-patch -p -2 &&
608 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
609 test_cmp expect output
613 test_expect_success 'format-patch from a subdirectory (1)' '
614 filename=$(
615 rm -rf sub &&
616 mkdir -p sub/dir &&
617 cd sub/dir &&
618 git format-patch -1
619 ) &&
620 case "$filename" in
622 ;; # ok
624 echo "Oops? $filename"
625 false
627 esac &&
628 test -f "$filename"
631 test_expect_success 'format-patch from a subdirectory (2)' '
632 filename=$(
633 rm -rf sub &&
634 mkdir -p sub/dir &&
635 cd sub/dir &&
636 git format-patch -1 -o ..
637 ) &&
638 case "$filename" in
639 ../0*)
640 ;; # ok
642 echo "Oops? $filename"
643 false
645 esac &&
646 basename=$(expr "$filename" : ".*/\(.*\)") &&
647 test -f "sub/$basename"
650 test_expect_success 'format-patch from a subdirectory (3)' '
651 rm -f 0* &&
652 filename=$(
653 rm -rf sub &&
654 mkdir -p sub/dir &&
655 cd sub/dir &&
656 git format-patch -1 -o "$TRASH_DIRECTORY"
657 ) &&
658 basename=$(expr "$filename" : ".*/\(.*\)") &&
659 test -f "$basename"
662 test_expect_success 'format-patch --in-reply-to' '
663 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
664 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
665 grep "^References: <baz@foo.bar>" patch8
668 test_expect_success 'format-patch --signoff' '
669 git format-patch -1 --signoff --stdout >out &&
670 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
673 test_expect_success 'format-patch --notes --signoff' '
674 git notes --ref test add -m "test message" HEAD &&
675 git format-patch -1 --signoff --stdout --notes=test >out &&
676 # Three dashes must come after S-o-b
677 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
678 sed "1,/^Signed-off-by: /d" out | grep "test message" &&
679 # Notes message must come after three dashes
680 ! sed "/^---$/q" out | grep "test message" &&
681 sed "1,/^---$/d" out | grep "test message"
684 echo "fatal: --name-only does not make sense" > expect.name-only
685 echo "fatal: --name-status does not make sense" > expect.name-status
686 echo "fatal: --check does not make sense" > expect.check
688 test_expect_success 'options no longer allowed for format-patch' '
689 test_must_fail git format-patch --name-only 2> output &&
690 test_i18ncmp expect.name-only output &&
691 test_must_fail git format-patch --name-status 2> output &&
692 test_i18ncmp expect.name-status output &&
693 test_must_fail git format-patch --check 2> output &&
694 test_i18ncmp expect.check output'
696 test_expect_success 'format-patch --numstat should produce a patch' '
697 git format-patch --numstat --stdout master..side > output &&
698 test 6 = $(grep "^diff --git a/" output | wc -l)'
700 test_expect_success 'format-patch -- <path>' '
701 git format-patch master..side -- file 2>error &&
702 ! grep "Use .--" error
705 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
706 git format-patch --ignore-if-in-upstream HEAD
709 test_expect_success 'format-patch --signature' '
710 git format-patch --stdout --signature="my sig" -1 >output &&
711 grep "my sig" output
714 test_expect_success 'format-patch with format.signature config' '
715 git config format.signature "config sig" &&
716 git format-patch --stdout -1 >output &&
717 grep "config sig" output
720 test_expect_success 'format-patch --signature overrides format.signature' '
721 git config format.signature "config sig" &&
722 git format-patch --stdout --signature="overrides" -1 >output &&
723 ! grep "config sig" output &&
724 grep "overrides" output
727 test_expect_success 'format-patch --no-signature ignores format.signature' '
728 git config format.signature "config sig" &&
729 git format-patch --stdout --signature="my sig" --no-signature \
730 -1 >output &&
731 check_patch output &&
732 ! grep "config sig" output &&
733 ! grep "my sig" output &&
734 ! grep "^-- \$" output
737 test_expect_success 'format-patch --signature --cover-letter' '
738 git config --unset-all format.signature &&
739 git format-patch --stdout --signature="my sig" --cover-letter \
740 -1 >output &&
741 grep "my sig" output &&
742 test 2 = $(grep "my sig" output | wc -l)
745 test_expect_success 'format.signature="" suppresses signatures' '
746 git config format.signature "" &&
747 git format-patch --stdout -1 >output &&
748 check_patch output &&
749 ! grep "^-- \$" output
752 test_expect_success 'format-patch --no-signature suppresses signatures' '
753 git config --unset-all format.signature &&
754 git format-patch --stdout --no-signature -1 >output &&
755 check_patch output &&
756 ! grep "^-- \$" output
759 test_expect_success 'format-patch --signature="" suppresses signatures' '
760 git format-patch --stdout --signature="" -1 >output &&
761 check_patch output &&
762 ! grep "^-- \$" output
765 test_expect_success TTY 'format-patch --stdout paginates' '
766 rm -f pager_used &&
767 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
768 test_path_is_file pager_used
771 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
772 rm -f pager_used &&
773 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
774 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
775 test_path_is_missing pager_used &&
776 test_path_is_missing .git/pager_used
779 test_expect_success 'format-patch handles multi-line subjects' '
780 rm -rf patches/ &&
781 echo content >>file &&
782 for i in one two three; do echo $i; done >msg &&
783 git add file &&
784 git commit -F msg &&
785 git format-patch -o patches -1 &&
786 grep ^Subject: patches/0001-one.patch >actual &&
787 echo "Subject: [PATCH] one two three" >expect &&
788 test_cmp expect actual
791 test_expect_success 'format-patch handles multi-line encoded subjects' '
792 rm -rf patches/ &&
793 echo content >>file &&
794 for i in en två tre; do echo $i; done >msg &&
795 git add file &&
796 git commit -F msg &&
797 git format-patch -o patches -1 &&
798 grep ^Subject: patches/0001-en.patch >actual &&
799 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
800 test_cmp expect actual
803 M8="foo bar "
804 M64=$M8$M8$M8$M8$M8$M8$M8$M8
805 M512=$M64$M64$M64$M64$M64$M64$M64$M64
806 cat >expect <<'EOF'
807 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
808 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
809 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
810 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
811 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
812 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
813 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
815 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
816 echo content >>file &&
817 git add file &&
818 git commit -m "$M512" &&
819 git format-patch --stdout -1 >patch &&
820 sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
821 test_cmp expect subject
824 M8="föö bar "
825 M64=$M8$M8$M8$M8$M8$M8$M8$M8
826 M512=$M64$M64$M64$M64$M64$M64$M64$M64
827 cat >expect <<'EOF'
828 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
829 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
830 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
831 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
832 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
833 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
834 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
835 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
836 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
837 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
838 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
839 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
840 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
841 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
842 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
843 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
844 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
845 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
846 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
847 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
848 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
849 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
850 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
851 =?UTF-8?q?bar?=
853 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
854 rm -rf patches/ &&
855 echo content >>file &&
856 git add file &&
857 git commit -m "$M512" &&
858 git format-patch --stdout -1 >patch &&
859 sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
860 test_cmp expect subject
863 check_author() {
864 echo content >>file &&
865 git add file &&
866 GIT_AUTHOR_NAME=$1 git commit -m author-check &&
867 git format-patch --stdout -1 >patch &&
868 sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
869 test_cmp expect actual
872 cat >expect <<'EOF'
873 From: "Foo B. Bar" <author@example.com>
875 test_expect_success 'format-patch quotes dot in from-headers' '
876 check_author "Foo B. Bar"
879 cat >expect <<'EOF'
880 From: "Foo \"The Baz\" Bar" <author@example.com>
882 test_expect_success 'format-patch quotes double-quote in from-headers' '
883 check_author "Foo \"The Baz\" Bar"
886 cat >expect <<'EOF'
887 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
889 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
890 check_author "Föo Bar"
893 cat >expect <<'EOF'
894 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
896 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
897 check_author "Föo B. Bar"
900 cat >expect <<EOF
901 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
902 <author@example.com>
904 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
905 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
908 cat >expect <<'EOF'
909 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
910 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
911 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
913 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
914 check_author "Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
917 cat >expect <<'EOF'
918 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
919 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
920 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
922 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
923 check_author "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
926 cat >expect <<'EOF'
927 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
928 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
929 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
930 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
931 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
933 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
934 check_author "Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
937 cat >expect <<'EOF'
938 Subject: header with . in it
940 test_expect_success 'subject lines do not have 822 atom-quoting' '
941 echo content >>file &&
942 git add file &&
943 git commit -m "header with . in it" &&
944 git format-patch -k -1 --stdout >patch &&
945 grep ^Subject: patch >actual &&
946 test_cmp expect actual
949 cat >expect <<'EOF'
950 Subject: [PREFIX 1/1] header with . in it
952 test_expect_success 'subject prefixes have space prepended' '
953 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
954 grep ^Subject: patch >actual &&
955 test_cmp expect actual
958 cat >expect <<'EOF'
959 Subject: [1/1] header with . in it
961 test_expect_success 'empty subject prefix does not have extra space' '
962 git format-patch -n -1 --stdout --subject-prefix= >patch &&
963 grep ^Subject: patch >actual &&
964 test_cmp expect actual
967 test_expect_success '--from=ident notices bogus ident' '
968 test_must_fail git format-patch -1 --stdout --from=foo >patch
971 test_expect_success '--from=ident replaces author' '
972 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
973 cat >expect <<-\EOF &&
974 From: Me <me@example.com>
976 From: A U Thor <author@example.com>
979 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
980 test_cmp expect patch.head
983 test_expect_success '--from uses committer ident' '
984 git format-patch -1 --stdout --from >patch &&
985 cat >expect <<-\EOF &&
986 From: C O Mitter <committer@example.com>
988 From: A U Thor <author@example.com>
991 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
992 test_cmp expect patch.head
995 test_expect_success '--from omits redundant in-body header' '
996 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
997 cat >expect <<-\EOF &&
998 From: A U Thor <author@example.com>
1001 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1002 test_cmp expect patch.head
1005 test_expect_success 'in-body headers trigger content encoding' '
1006 GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1007 test_when_finished "git reset --hard HEAD^" &&
1008 git format-patch -1 --stdout --from >patch &&
1009 cat >expect <<-\EOF &&
1010 From: C O Mitter <committer@example.com>
1011 Content-Type: text/plain; charset=UTF-8
1013 From: éxötìc <author@example.com>
1016 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1017 test_cmp expect patch.head
1020 append_signoff()
1022 C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1023 git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1024 sed -n -e "1,/^---$/p" append_signoff.patch |
1025 egrep -n "^Subject|Sign|^$"
1028 test_expect_success 'signoff: commit with no body' '
1029 append_signoff </dev/null >actual &&
1030 cat <<\EOF | sed "s/EOL$//" >expected &&
1031 4:Subject: [PATCH] EOL
1033 9:Signed-off-by: C O Mitter <committer@example.com>
1035 test_cmp expected actual
1038 test_expect_success 'signoff: commit with only subject' '
1039 echo subject | append_signoff >actual &&
1040 cat >expected <<\EOF &&
1041 4:Subject: [PATCH] subject
1043 9:Signed-off-by: C O Mitter <committer@example.com>
1045 test_cmp expected actual
1048 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1049 printf subject | append_signoff >actual &&
1050 cat >expected <<\EOF &&
1051 4:Subject: [PATCH] subject
1053 9:Signed-off-by: C O Mitter <committer@example.com>
1055 test_cmp expected actual
1058 test_expect_success 'signoff: no existing signoffs' '
1059 append_signoff <<\EOF >actual &&
1060 subject
1062 body
1064 cat >expected <<\EOF &&
1065 4:Subject: [PATCH] subject
1068 11:Signed-off-by: C O Mitter <committer@example.com>
1070 test_cmp expected actual
1073 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1074 printf "subject\n\nbody" | append_signoff >actual &&
1075 cat >expected <<\EOF &&
1076 4:Subject: [PATCH] subject
1079 11:Signed-off-by: C O Mitter <committer@example.com>
1081 test_cmp expected actual
1084 test_expect_success 'signoff: some random signoff' '
1085 append_signoff <<\EOF >actual &&
1086 subject
1088 body
1090 Signed-off-by: my@house
1092 cat >expected <<\EOF &&
1093 4:Subject: [PATCH] subject
1096 11:Signed-off-by: my@house
1097 12:Signed-off-by: C O Mitter <committer@example.com>
1099 test_cmp expected actual
1102 test_expect_success 'signoff: misc conforming footer elements' '
1103 append_signoff <<\EOF >actual &&
1104 subject
1106 body
1108 Signed-off-by: my@house
1109 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1110 Tested-by: Some One <someone@example.com>
1111 Bug: 1234
1113 cat >expected <<\EOF &&
1114 4:Subject: [PATCH] subject
1117 11:Signed-off-by: my@house
1118 15:Signed-off-by: C O Mitter <committer@example.com>
1120 test_cmp expected actual
1123 test_expect_success 'signoff: some random signoff-alike' '
1124 append_signoff <<\EOF >actual &&
1125 subject
1127 body
1128 Fooled-by-me: my@house
1130 cat >expected <<\EOF &&
1131 4:Subject: [PATCH] subject
1134 12:Signed-off-by: C O Mitter <committer@example.com>
1136 test_cmp expected actual
1139 test_expect_success 'signoff: not really a signoff' '
1140 append_signoff <<\EOF >actual &&
1141 subject
1143 I want to mention about Signed-off-by: here.
1145 cat >expected <<\EOF &&
1146 4:Subject: [PATCH] subject
1148 9:I want to mention about Signed-off-by: here.
1150 11:Signed-off-by: C O Mitter <committer@example.com>
1152 test_cmp expected actual
1155 test_expect_success 'signoff: not really a signoff (2)' '
1156 append_signoff <<\EOF >actual &&
1157 subject
1159 My unfortunate
1160 Signed-off-by: example happens to be wrapped here.
1162 cat >expected <<\EOF &&
1163 4:Subject: [PATCH] subject
1165 10:Signed-off-by: example happens to be wrapped here.
1167 12:Signed-off-by: C O Mitter <committer@example.com>
1169 test_cmp expected actual
1172 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1173 append_signoff <<\EOF >actual &&
1174 subject
1176 Signed-off-by: my@house
1177 Signed-off-by: your@house
1179 A lot of houses.
1181 cat >expected <<\EOF &&
1182 4:Subject: [PATCH] subject
1184 9:Signed-off-by: my@house
1185 10:Signed-off-by: your@house
1188 14:Signed-off-by: C O Mitter <committer@example.com>
1190 test_cmp expected actual
1193 test_expect_success 'signoff: the same signoff at the end' '
1194 append_signoff <<\EOF >actual &&
1195 subject
1197 body
1199 Signed-off-by: C O Mitter <committer@example.com>
1201 cat >expected <<\EOF &&
1202 4:Subject: [PATCH] subject
1205 11:Signed-off-by: C O Mitter <committer@example.com>
1207 test_cmp expected actual
1210 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1211 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1212 append_signoff >actual &&
1213 cat >expected <<\EOF &&
1214 4:Subject: [PATCH] subject
1216 9:Signed-off-by: C O Mitter <committer@example.com>
1218 test_cmp expected actual
1221 test_expect_success 'signoff: the same signoff NOT at the end' '
1222 append_signoff <<\EOF >actual &&
1223 subject
1225 body
1227 Signed-off-by: C O Mitter <committer@example.com>
1228 Signed-off-by: my@house
1230 cat >expected <<\EOF &&
1231 4:Subject: [PATCH] subject
1234 11:Signed-off-by: C O Mitter <committer@example.com>
1235 12:Signed-off-by: my@house
1237 test_cmp expected actual
1240 test_expect_success 'signoff: detect garbage in non-conforming footer' '
1241 append_signoff <<\EOF >actual &&
1242 subject
1244 body
1246 Tested-by: my@house
1247 Some Trash
1248 Signed-off-by: C O Mitter <committer@example.com>
1250 cat >expected <<\EOF &&
1251 4:Subject: [PATCH] subject
1254 13:Signed-off-by: C O Mitter <committer@example.com>
1256 15:Signed-off-by: C O Mitter <committer@example.com>
1258 test_cmp expected actual
1261 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1262 append_signoff <<\EOF >actual &&
1263 subject
1265 body
1267 Reviewed-id: Noone
1268 Tested-by: my@house
1269 Change-id: Ideadbeef
1270 Signed-off-by: C O Mitter <committer@example.com>
1271 Bug: 1234
1273 cat >expected <<\EOF &&
1274 4:Subject: [PATCH] subject
1277 14:Signed-off-by: C O Mitter <committer@example.com>
1279 test_cmp expected actual
1282 test_expect_success 'format patch ignores color.ui' '
1283 test_unconfig color.ui &&
1284 git format-patch --stdout -1 >expect &&
1285 test_config color.ui always &&
1286 git format-patch --stdout -1 >actual &&
1287 test_cmp expect actual
1290 test_expect_success 'cover letter using branch description (1)' '
1291 git checkout rebuild-1 &&
1292 test_config branch.rebuild-1.description hello &&
1293 git format-patch --stdout --cover-letter master >actual &&
1294 grep hello actual >/dev/null
1297 test_expect_success 'cover letter using branch description (2)' '
1298 git checkout rebuild-1 &&
1299 test_config branch.rebuild-1.description hello &&
1300 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1301 grep hello actual >/dev/null
1304 test_expect_success 'cover letter using branch description (3)' '
1305 git checkout rebuild-1 &&
1306 test_config branch.rebuild-1.description hello &&
1307 git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1308 grep hello actual >/dev/null
1311 test_expect_success 'cover letter using branch description (4)' '
1312 git checkout rebuild-1 &&
1313 test_config branch.rebuild-1.description hello &&
1314 git format-patch --stdout --cover-letter master.. >actual &&
1315 grep hello actual >/dev/null
1318 test_expect_success 'cover letter using branch description (5)' '
1319 git checkout rebuild-1 &&
1320 test_config branch.rebuild-1.description hello &&
1321 git format-patch --stdout --cover-letter -2 HEAD >actual &&
1322 grep hello actual >/dev/null
1325 test_expect_success 'cover letter using branch description (6)' '
1326 git checkout rebuild-1 &&
1327 test_config branch.rebuild-1.description hello &&
1328 git format-patch --stdout --cover-letter -2 >actual &&
1329 grep hello actual >/dev/null
1332 test_expect_success 'cover letter with nothing' '
1333 git format-patch --stdout --cover-letter >actual &&
1334 test_line_count = 0 actual
1337 test_expect_success 'cover letter auto' '
1338 mkdir -p tmp &&
1339 test_when_finished "rm -rf tmp;
1340 git config --unset format.coverletter" &&
1342 git config format.coverletter auto &&
1343 git format-patch -o tmp -1 >list &&
1344 test_line_count = 1 list &&
1345 git format-patch -o tmp -2 >list &&
1346 test_line_count = 3 list
1349 test_expect_success 'cover letter auto user override' '
1350 mkdir -p tmp &&
1351 test_when_finished "rm -rf tmp;
1352 git config --unset format.coverletter" &&
1354 git config format.coverletter auto &&
1355 git format-patch -o tmp --cover-letter -1 >list &&
1356 test_line_count = 2 list &&
1357 git format-patch -o tmp --cover-letter -2 >list &&
1358 test_line_count = 3 list &&
1359 git format-patch -o tmp --no-cover-letter -1 >list &&
1360 test_line_count = 1 list &&
1361 git format-patch -o tmp --no-cover-letter -2 >list &&
1362 test_line_count = 2 list
1365 test_done