3 # Copyright (c) 2006 Junio C Hamano
6 test_description='various format-patch tests'
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 &&
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 &&
23 git commit -m "Side changes #1" &&
25 for i in D E F; do echo "$i"; done >>file &&
26 git update-index file &&
28 git commit -m "Side changes #2" &&
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 &&
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 &&
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) &&
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) &&
60 test_expect_success "format-patch --ignore-if-in-upstream handles tags" '
61 git tag -a v1 -m tag side &&
62 git tag -a v2 -m tag master &&
63 git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
64 cnt=$(grep "^From " patch1 | wc -l) &&
68 test_expect_success "format-patch doesn't consider merge commits" '
70 git checkout -b slave master &&
71 echo "Another line" >>file &&
73 git commit -am "Slave change #1" &&
74 echo "Yet another line" >>file &&
76 git commit -am "Slave change #2" &&
77 git checkout -b merger master &&
79 git merge --no-ff slave &&
80 cnt=$(git format-patch -3 --stdout | grep "^From " | wc -l) &&
84 test_expect_success "format-patch result applies" '
86 git checkout -b rebuild-0 master &&
88 cnt=$(git rev-list master.. | wc -l) &&
92 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
94 git checkout -b rebuild-1 master &&
96 cnt=$(git rev-list master.. | wc -l) &&
100 test_expect_success 'commit did not screw up the log message' '
102 git cat-file commit side | grep "^Side .* with .* backslash-n"
106 test_expect_success 'format-patch did not screw up the log message' '
108 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
109 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
113 test_expect_success 'replay did not screw up the log message' '
115 git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
119 test_expect_success 'extra headers' '
121 git config format.headers "To: R E Cipient <rcipient@example.com>
123 git config --add format.headers "Cc: S E Cipient <scipient@example.com>
125 git format-patch --stdout master..side > patch2 &&
126 sed -e "/^\$/q" patch2 > hdrs2 &&
127 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
128 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
132 test_expect_success 'extra headers without newlines' '
134 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
135 git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
136 git format-patch --stdout master..side >patch3 &&
137 sed -e "/^\$/q" patch3 > hdrs3 &&
138 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
139 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
143 test_expect_success 'extra headers with multiple To:s' '
145 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
146 git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
147 git format-patch --stdout master..side > patch4 &&
148 sed -e "/^\$/q" patch4 > hdrs4 &&
149 grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
150 grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
153 test_expect_success 'additional command line cc (ascii)' '
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_failure 'additional command line cc (rfc822)' '
163 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
164 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
165 grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
166 grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" patch5
169 test_expect_success 'command line headers' '
171 git config --unset-all format.headers &&
172 git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
173 grep "^Cc: R E Cipient <rcipient@example.com>\$" patch6
176 test_expect_success 'configuration headers and command line headers' '
178 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
179 git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
180 grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch7 &&
181 grep "^ *S E Cipient <scipient@example.com>\$" patch7
184 test_expect_success 'command line To: header (ascii)' '
186 git config --unset-all format.headers &&
187 git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
188 grep "^To: R E Cipient <rcipient@example.com>\$" patch8
191 test_expect_failure 'command line To: header (rfc822)' '
193 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
194 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch8
197 test_expect_failure 'command line To: header (rfc2047)' '
199 git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
200 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch8
203 test_expect_success 'configuration To: header (ascii)' '
205 git config format.to "R E Cipient <rcipient@example.com>" &&
206 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
207 grep "^To: R E Cipient <rcipient@example.com>\$" patch9
210 test_expect_failure 'configuration To: header (rfc822)' '
212 git config format.to "R. E. Cipient <rcipient@example.com>" &&
213 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
214 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch9
217 test_expect_failure 'configuration To: header (rfc2047)' '
219 git config format.to "R Ä Cipient <rcipient@example.com>" &&
220 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
221 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch9
224 # check_patch <patch>: Verify that <patch> looks like a half-sane
225 # patch email to avoid a false positive with !grep
227 grep -e "^From:" "$1" &&
228 grep -e "^Date:" "$1" &&
229 grep -e "^Subject:" "$1"
232 test_expect_success '--no-to overrides config.to' '
234 git config --replace-all format.to \
235 "R E Cipient <rcipient@example.com>" &&
236 git format-patch --no-to --stdout master..side |
237 sed -e "/^\$/q" >patch10 &&
238 check_patch patch10 &&
239 ! grep "^To: R E Cipient <rcipient@example.com>\$" patch10
242 test_expect_success '--no-to and --to replaces config.to' '
244 git config --replace-all format.to \
245 "Someone <someone@out.there>" &&
246 git format-patch --no-to --to="Someone Else <else@out.there>" \
247 --stdout master..side |
248 sed -e "/^\$/q" >patch11 &&
249 check_patch patch11 &&
250 ! grep "^To: Someone <someone@out.there>\$" patch11 &&
251 grep "^To: Someone Else <else@out.there>\$" patch11
254 test_expect_success '--no-cc overrides config.cc' '
256 git config --replace-all format.cc \
257 "C E Cipient <rcipient@example.com>" &&
258 git format-patch --no-cc --stdout master..side |
259 sed -e "/^\$/q" >patch12 &&
260 check_patch patch12 &&
261 ! grep "^Cc: C E Cipient <rcipient@example.com>\$" patch12
264 test_expect_success '--no-add-header overrides config.headers' '
266 git config --replace-all format.headers \
267 "Header1: B E Cipient <rcipient@example.com>" &&
268 git format-patch --no-add-header --stdout master..side |
269 sed -e "/^\$/q" >patch13 &&
270 check_patch patch13 &&
271 ! grep "^Header1: B E Cipient <rcipient@example.com>\$" patch13
274 test_expect_success 'multiple files' '
278 git format-patch -o patches/ master &&
279 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
282 test_expect_success 'reroll count' '
284 git format-patch -o patches --cover-letter --reroll-count 4 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 test_expect_success 'reroll count (-v)' '
292 git format-patch -o patches --cover-letter -v4 master..side >list &&
293 ! grep -v "^patches/v4-000[0-3]-" list &&
294 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
295 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
301 (git format-patch --stdout "$@"; echo $? > status.out) |
302 # Prints everything between the Message-ID and In-Reply-To,
303 # and replaces all Message-ID-lookalikes by a sequence number
305 if (/^(message-id|references|in-reply-to)/i) {
311 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
312 for $k (keys %h) {s/$k/$h{$k}/};
315 print "---\n" if /^From /i;
317 test 0 = "$(cat status.out)" &&
318 test_cmp "$expect" actual
321 cat >> expect.no-threading <<EOF
327 test_expect_success 'no threading' '
329 check_threading expect.no-threading master
332 cat > expect.thread <<EOF
345 test_expect_success 'thread' '
346 check_threading expect.thread --thread master
349 cat > expect.in-reply-to <<EOF
364 test_expect_success 'thread in-reply-to' '
365 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
369 cat > expect.cover-letter <<EOF
386 test_expect_success 'thread cover-letter' '
387 check_threading expect.cover-letter --cover-letter --thread master
390 cat > expect.cl-irt <<EOF
412 test_expect_success 'thread cover-letter in-reply-to' '
413 check_threading expect.cl-irt --cover-letter \
414 --in-reply-to="<test.message>" --thread master
417 test_expect_success 'thread explicit shallow' '
418 check_threading expect.cl-irt --cover-letter \
419 --in-reply-to="<test.message>" --thread=shallow master
422 cat > expect.deep <<EOF
436 test_expect_success 'thread deep' '
437 check_threading expect.deep --thread=deep master
440 cat > expect.deep-irt <<EOF
458 test_expect_success 'thread deep in-reply-to' '
459 check_threading expect.deep-irt --thread=deep \
460 --in-reply-to="<test.message>" master
463 cat > expect.deep-cl <<EOF
483 test_expect_success 'thread deep cover-letter' '
484 check_threading expect.deep-cl --cover-letter --thread=deep master
487 cat > expect.deep-cl-irt <<EOF
512 test_expect_success 'thread deep cover-letter in-reply-to' '
513 check_threading expect.deep-cl-irt --cover-letter \
514 --in-reply-to="<test.message>" --thread=deep master
517 test_expect_success 'thread via config' '
518 test_config format.thread true &&
519 check_threading expect.thread master
522 test_expect_success 'thread deep via config' '
523 test_config format.thread deep &&
524 check_threading expect.deep master
527 test_expect_success 'thread config + override' '
528 test_config format.thread deep &&
529 check_threading expect.thread --thread master
532 test_expect_success 'thread config + --no-thread' '
533 test_config format.thread deep &&
534 check_threading expect.no-threading --no-thread master
537 test_expect_success 'excessive subject' '
541 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
542 git update-index file &&
543 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." &&
544 git format-patch -o patches/ master..side &&
545 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
548 test_expect_success 'cover-letter inherits diff options' '
552 git format-patch --no-renames --cover-letter -1 &&
553 check_patch 0000-cover-letter.patch &&
554 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
555 git format-patch --cover-letter -1 -M &&
556 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
561 This is an excessively long subject line for a message due to the
562 habit some projects have of not having a short, one-line subject at
563 the start of the commit message, but rather sticking a whole
564 paragraph right at the start as the only thing in the commit
565 message. It had better not become the filename for the patch.
570 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
572 git format-patch --cover-letter -2 &&
573 sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
574 test_cmp expect output
579 index 40f36c6..2dc5c23 100644
590 test_expect_success 'format-patch respects -U' '
592 git format-patch -U4 -2 &&
593 sed -e "1,/^diff/d" -e "/^+5/q" \
594 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
596 test_cmp expect output
602 diff --git a/file b/file
603 index 40f36c6..2dc5c23 100644
613 test_expect_success 'format-patch -p suppresses stat' '
615 git format-patch -p -2 &&
616 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
617 test_cmp expect output
621 test_expect_success 'format-patch from a subdirectory (1)' '
632 echo "Oops? $filename"
639 test_expect_success 'format-patch from a subdirectory (2)' '
644 git format-patch -1 -o ..
650 echo "Oops? $filename"
654 basename=$(expr "$filename" : ".*/\(.*\)") &&
655 test -f "sub/$basename"
658 test_expect_success 'format-patch from a subdirectory (3)' '
664 git format-patch -1 -o "$TRASH_DIRECTORY"
666 basename=$(expr "$filename" : ".*/\(.*\)") &&
670 test_expect_success 'format-patch --in-reply-to' '
671 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
672 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
673 grep "^References: <baz@foo.bar>" patch8
676 test_expect_success 'format-patch --signoff' '
677 git format-patch -1 --signoff --stdout >out &&
678 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
681 test_expect_success 'format-patch --notes --signoff' '
682 git notes --ref test add -m "test message" HEAD &&
683 git format-patch -1 --signoff --stdout --notes=test >out &&
684 # Three dashes must come after S-o-b
685 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
686 sed "1,/^Signed-off-by: /d" out | grep "test message" &&
687 # Notes message must come after three dashes
688 ! sed "/^---$/q" out | grep "test message" &&
689 sed "1,/^---$/d" out | grep "test message"
692 echo "fatal: --name-only does not make sense" > expect.name-only
693 echo "fatal: --name-status does not make sense" > expect.name-status
694 echo "fatal: --check does not make sense" > expect.check
696 test_expect_success 'options no longer allowed for format-patch' '
697 test_must_fail git format-patch --name-only 2> output &&
698 test_i18ncmp expect.name-only output &&
699 test_must_fail git format-patch --name-status 2> output &&
700 test_i18ncmp expect.name-status output &&
701 test_must_fail git format-patch --check 2> output &&
702 test_i18ncmp expect.check output'
704 test_expect_success 'format-patch --numstat should produce a patch' '
705 git format-patch --numstat --stdout master..side > output &&
706 test 5 = $(grep "^diff --git a/" output | wc -l)'
708 test_expect_success 'format-patch -- <path>' '
709 git format-patch master..side -- file 2>error &&
710 ! grep "Use .--" error
713 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
714 git format-patch --ignore-if-in-upstream HEAD
717 test_expect_success 'format-patch --signature' '
718 git format-patch --stdout --signature="my sig" -1 >output &&
722 test_expect_success 'format-patch with format.signature config' '
723 git config format.signature "config sig" &&
724 git format-patch --stdout -1 >output &&
725 grep "config sig" output
728 test_expect_success 'format-patch --signature overrides format.signature' '
729 git config format.signature "config sig" &&
730 git format-patch --stdout --signature="overrides" -1 >output &&
731 ! grep "config sig" output &&
732 grep "overrides" output
735 test_expect_success 'format-patch --no-signature ignores format.signature' '
736 git config format.signature "config sig" &&
737 git format-patch --stdout --signature="my sig" --no-signature \
739 check_patch output &&
740 ! grep "config sig" output &&
741 ! grep "my sig" output &&
742 ! grep "^-- \$" output
745 test_expect_success 'format-patch --signature --cover-letter' '
746 git config --unset-all format.signature &&
747 git format-patch --stdout --signature="my sig" --cover-letter \
749 grep "my sig" output &&
750 test 2 = $(grep "my sig" output | wc -l)
753 test_expect_success 'format.signature="" suppresses signatures' '
754 git config format.signature "" &&
755 git format-patch --stdout -1 >output &&
756 check_patch output &&
757 ! grep "^-- \$" output
760 test_expect_success 'format-patch --no-signature suppresses signatures' '
761 git config --unset-all format.signature &&
762 git format-patch --stdout --no-signature -1 >output &&
763 check_patch output &&
764 ! grep "^-- \$" output
767 test_expect_success 'format-patch --signature="" suppresses signatures' '
768 git format-patch --stdout --signature="" -1 >output &&
769 check_patch output &&
770 ! grep "^-- \$" output
773 test_expect_success 'prepare mail-signature input' '
774 cat >mail-signature <<-\EOF
776 Test User <test.email@kernel.org>
777 http://git.kernel.org/cgit/git/git.git
779 git.kernel.org/?p=git/git.git;a=summary
784 test_expect_success '--signature-file=file works' '
785 git format-patch --stdout --signature-file=mail-signature -1 >output &&
786 check_patch output &&
787 sed -e "1,/^-- \$/d" <output >actual &&
789 cat mail-signature && echo
791 test_cmp expect actual
794 test_expect_success 'format.signaturefile works' '
795 test_config format.signaturefile mail-signature &&
796 git format-patch --stdout -1 >output &&
797 check_patch output &&
798 sed -e "1,/^-- \$/d" <output >actual &&
800 cat mail-signature && echo
802 test_cmp expect actual
805 test_expect_success '--no-signature suppresses format.signaturefile ' '
806 test_config format.signaturefile mail-signature &&
807 git format-patch --stdout --no-signature -1 >output &&
808 check_patch output &&
809 ! grep "^-- \$" output
812 test_expect_success '--signature-file overrides format.signaturefile' '
813 cat >other-mail-signature <<-\EOF &&
814 Use this other signature instead of mail-signature.
816 test_config format.signaturefile mail-signature &&
817 git format-patch --stdout \
818 --signature-file=other-mail-signature -1 >output &&
819 check_patch output &&
820 sed -e "1,/^-- \$/d" <output >actual &&
822 cat other-mail-signature && echo
824 test_cmp expect actual
827 test_expect_success '--signature overrides format.signaturefile' '
828 test_config format.signaturefile mail-signature &&
829 git format-patch --stdout --signature="my sig" -1 >output &&
830 check_patch output &&
834 test_expect_success TTY 'format-patch --stdout paginates' '
836 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
837 test_path_is_file pager_used
840 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
842 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
843 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
844 test_path_is_missing pager_used &&
845 test_path_is_missing .git/pager_used
848 test_expect_success 'format-patch handles multi-line subjects' '
850 echo content >>file &&
851 for i in one two three; do echo $i; done >msg &&
854 git format-patch -o patches -1 &&
855 grep ^Subject: patches/0001-one.patch >actual &&
856 echo "Subject: [PATCH] one two three" >expect &&
857 test_cmp expect actual
860 test_expect_success 'format-patch handles multi-line encoded subjects' '
862 echo content >>file &&
863 for i in en två tre; do echo $i; done >msg &&
866 git format-patch -o patches -1 &&
867 grep ^Subject: patches/0001-en.patch >actual &&
868 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
869 test_cmp expect actual
873 M64=$M8$M8$M8$M8$M8$M8$M8$M8
874 M512=$M64$M64$M64$M64$M64$M64$M64$M64
876 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
877 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
878 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
879 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
880 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
881 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
882 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
884 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
885 echo content >>file &&
887 git commit -m "$M512" &&
888 git format-patch --stdout -1 >patch &&
889 sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
890 test_cmp expect subject
894 M64=$M8$M8$M8$M8$M8$M8$M8$M8
895 M512=$M64$M64$M64$M64$M64$M64$M64$M64
897 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
898 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
899 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
900 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
901 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
902 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
903 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
904 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
905 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
906 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
907 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
908 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
909 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
910 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
911 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
912 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
913 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
914 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
915 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
916 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
917 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
918 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
919 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
922 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
924 echo content >>file &&
926 git commit -m "$M512" &&
927 git format-patch --stdout -1 >patch &&
928 sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
929 test_cmp expect subject
933 echo content >>file &&
935 GIT_AUTHOR_NAME=$1 git commit -m author-check &&
936 git format-patch --stdout -1 >patch &&
937 sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
938 test_cmp expect actual
942 From: "Foo B. Bar" <author@example.com>
944 test_expect_success 'format-patch quotes dot in from-headers' '
945 check_author "Foo B. Bar"
949 From: "Foo \"The Baz\" Bar" <author@example.com>
951 test_expect_success 'format-patch quotes double-quote in from-headers' '
952 check_author "Foo \"The Baz\" Bar"
956 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
958 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
959 check_author "Föo Bar"
963 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
965 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
966 check_author "Föo B. Bar"
970 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
973 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
974 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
978 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
979 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
980 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
982 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
983 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"
987 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
988 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
989 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
991 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
992 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"
996 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
997 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
998 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
999 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1000 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1002 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1003 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"
1007 Subject: header with . in it
1009 test_expect_success 'subject lines do not have 822 atom-quoting' '
1010 echo content >>file &&
1012 git commit -m "header with . in it" &&
1013 git format-patch -k -1 --stdout >patch &&
1014 grep ^Subject: patch >actual &&
1015 test_cmp expect actual
1019 Subject: [PREFIX 1/1] header with . in it
1021 test_expect_success 'subject prefixes have space prepended' '
1022 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1023 grep ^Subject: patch >actual &&
1024 test_cmp expect actual
1028 Subject: [1/1] header with . in it
1030 test_expect_success 'empty subject prefix does not have extra space' '
1031 git format-patch -n -1 --stdout --subject-prefix= >patch &&
1032 grep ^Subject: patch >actual &&
1033 test_cmp expect actual
1036 test_expect_success '--from=ident notices bogus ident' '
1037 test_must_fail git format-patch -1 --stdout --from=foo >patch
1040 test_expect_success '--from=ident replaces author' '
1041 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1042 cat >expect <<-\EOF &&
1043 From: Me <me@example.com>
1045 From: A U Thor <author@example.com>
1048 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1049 test_cmp expect patch.head
1052 test_expect_success '--from uses committer ident' '
1053 git format-patch -1 --stdout --from >patch &&
1054 cat >expect <<-\EOF &&
1055 From: C O Mitter <committer@example.com>
1057 From: A U Thor <author@example.com>
1060 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1061 test_cmp expect patch.head
1064 test_expect_success '--from omits redundant in-body header' '
1065 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1066 cat >expect <<-\EOF &&
1067 From: A U Thor <author@example.com>
1070 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1071 test_cmp expect patch.head
1074 test_expect_success 'in-body headers trigger content encoding' '
1075 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1076 test_when_finished "git reset --hard HEAD^" &&
1077 git format-patch -1 --stdout --from >patch &&
1078 cat >expect <<-\EOF &&
1079 From: C O Mitter <committer@example.com>
1080 Content-Type: text/plain; charset=UTF-8
1082 From: éxötìc <author@example.com>
1085 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1086 test_cmp expect patch.head
1091 C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1092 git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1093 sed -n -e "1,/^---$/p" append_signoff.patch |
1094 egrep -n "^Subject|Sign|^$"
1097 test_expect_success 'signoff: commit with no body' '
1098 append_signoff </dev/null >actual &&
1099 cat <<\EOF | sed "s/EOL$//" >expected &&
1100 4:Subject: [PATCH] EOL
1102 9:Signed-off-by: C O Mitter <committer@example.com>
1104 test_cmp expected actual
1107 test_expect_success 'signoff: commit with only subject' '
1108 echo subject | append_signoff >actual &&
1109 cat >expected <<\EOF &&
1110 4:Subject: [PATCH] subject
1112 9:Signed-off-by: C O Mitter <committer@example.com>
1114 test_cmp expected actual
1117 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1118 printf subject | append_signoff >actual &&
1119 cat >expected <<\EOF &&
1120 4:Subject: [PATCH] subject
1122 9:Signed-off-by: C O Mitter <committer@example.com>
1124 test_cmp expected actual
1127 test_expect_success 'signoff: no existing signoffs' '
1128 append_signoff <<\EOF >actual &&
1133 cat >expected <<\EOF &&
1134 4:Subject: [PATCH] subject
1137 11:Signed-off-by: C O Mitter <committer@example.com>
1139 test_cmp expected actual
1142 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1143 printf "subject\n\nbody" | append_signoff >actual &&
1144 cat >expected <<\EOF &&
1145 4:Subject: [PATCH] subject
1148 11:Signed-off-by: C O Mitter <committer@example.com>
1150 test_cmp expected actual
1153 test_expect_success 'signoff: some random signoff' '
1154 append_signoff <<\EOF >actual &&
1159 Signed-off-by: my@house
1161 cat >expected <<\EOF &&
1162 4:Subject: [PATCH] subject
1165 11:Signed-off-by: my@house
1166 12:Signed-off-by: C O Mitter <committer@example.com>
1168 test_cmp expected actual
1171 test_expect_success 'signoff: misc conforming footer elements' '
1172 append_signoff <<\EOF >actual &&
1177 Signed-off-by: my@house
1178 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1179 Tested-by: Some One <someone@example.com>
1182 cat >expected <<\EOF &&
1183 4:Subject: [PATCH] subject
1186 11:Signed-off-by: my@house
1187 15:Signed-off-by: C O Mitter <committer@example.com>
1189 test_cmp expected actual
1192 test_expect_success 'signoff: some random signoff-alike' '
1193 append_signoff <<\EOF >actual &&
1197 Fooled-by-me: my@house
1199 cat >expected <<\EOF &&
1200 4:Subject: [PATCH] subject
1203 12:Signed-off-by: C O Mitter <committer@example.com>
1205 test_cmp expected actual
1208 test_expect_success 'signoff: not really a signoff' '
1209 append_signoff <<\EOF >actual &&
1212 I want to mention about Signed-off-by: here.
1214 cat >expected <<\EOF &&
1215 4:Subject: [PATCH] subject
1217 9:I want to mention about Signed-off-by: here.
1219 11:Signed-off-by: C O Mitter <committer@example.com>
1221 test_cmp expected actual
1224 test_expect_success 'signoff: not really a signoff (2)' '
1225 append_signoff <<\EOF >actual &&
1229 Signed-off-by: example happens to be wrapped here.
1231 cat >expected <<\EOF &&
1232 4:Subject: [PATCH] subject
1234 10:Signed-off-by: example happens to be wrapped here.
1236 12:Signed-off-by: C O Mitter <committer@example.com>
1238 test_cmp expected actual
1241 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1242 append_signoff <<\EOF >actual &&
1245 Signed-off-by: my@house
1246 Signed-off-by: your@house
1250 cat >expected <<\EOF &&
1251 4:Subject: [PATCH] subject
1253 9:Signed-off-by: my@house
1254 10:Signed-off-by: your@house
1257 14:Signed-off-by: C O Mitter <committer@example.com>
1259 test_cmp expected actual
1262 test_expect_success 'signoff: the same signoff at the end' '
1263 append_signoff <<\EOF >actual &&
1268 Signed-off-by: C O Mitter <committer@example.com>
1270 cat >expected <<\EOF &&
1271 4:Subject: [PATCH] subject
1274 11:Signed-off-by: C O Mitter <committer@example.com>
1276 test_cmp expected actual
1279 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1280 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1281 append_signoff >actual &&
1282 cat >expected <<\EOF &&
1283 4:Subject: [PATCH] subject
1285 9:Signed-off-by: C O Mitter <committer@example.com>
1287 test_cmp expected actual
1290 test_expect_success 'signoff: the same signoff NOT at the end' '
1291 append_signoff <<\EOF >actual &&
1296 Signed-off-by: C O Mitter <committer@example.com>
1297 Signed-off-by: my@house
1299 cat >expected <<\EOF &&
1300 4:Subject: [PATCH] subject
1303 11:Signed-off-by: C O Mitter <committer@example.com>
1304 12:Signed-off-by: my@house
1306 test_cmp expected actual
1309 test_expect_success 'signoff: detect garbage in non-conforming footer' '
1310 append_signoff <<\EOF >actual &&
1317 Signed-off-by: C O Mitter <committer@example.com>
1319 cat >expected <<\EOF &&
1320 4:Subject: [PATCH] subject
1323 13:Signed-off-by: C O Mitter <committer@example.com>
1325 15:Signed-off-by: C O Mitter <committer@example.com>
1327 test_cmp expected actual
1330 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1331 append_signoff <<\EOF >actual &&
1338 Change-id: Ideadbeef
1339 Signed-off-by: C O Mitter <committer@example.com>
1342 cat >expected <<\EOF &&
1343 4:Subject: [PATCH] subject
1346 14:Signed-off-by: C O Mitter <committer@example.com>
1348 test_cmp expected actual
1351 test_expect_success 'format patch ignores color.ui' '
1352 test_unconfig color.ui &&
1353 git format-patch --stdout -1 >expect &&
1354 test_config color.ui always &&
1355 git format-patch --stdout -1 >actual &&
1356 test_cmp expect actual
1359 test_expect_success 'cover letter using branch description (1)' '
1360 git checkout rebuild-1 &&
1361 test_config branch.rebuild-1.description hello &&
1362 git format-patch --stdout --cover-letter master >actual &&
1363 grep hello actual >/dev/null
1366 test_expect_success 'cover letter using branch description (2)' '
1367 git checkout rebuild-1 &&
1368 test_config branch.rebuild-1.description hello &&
1369 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1370 grep hello actual >/dev/null
1373 test_expect_success 'cover letter using branch description (3)' '
1374 git checkout rebuild-1 &&
1375 test_config branch.rebuild-1.description hello &&
1376 git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1377 grep hello actual >/dev/null
1380 test_expect_success 'cover letter using branch description (4)' '
1381 git checkout rebuild-1 &&
1382 test_config branch.rebuild-1.description hello &&
1383 git format-patch --stdout --cover-letter master.. >actual &&
1384 grep hello actual >/dev/null
1387 test_expect_success 'cover letter using branch description (5)' '
1388 git checkout rebuild-1 &&
1389 test_config branch.rebuild-1.description hello &&
1390 git format-patch --stdout --cover-letter -2 HEAD >actual &&
1391 grep hello actual >/dev/null
1394 test_expect_success 'cover letter using branch description (6)' '
1395 git checkout rebuild-1 &&
1396 test_config branch.rebuild-1.description hello &&
1397 git format-patch --stdout --cover-letter -2 >actual &&
1398 grep hello actual >/dev/null
1401 test_expect_success 'cover letter with nothing' '
1402 git format-patch --stdout --cover-letter >actual &&
1403 test_line_count = 0 actual
1406 test_expect_success 'cover letter auto' '
1408 test_when_finished "rm -rf tmp;
1409 git config --unset format.coverletter" &&
1411 git config format.coverletter auto &&
1412 git format-patch -o tmp -1 >list &&
1413 test_line_count = 1 list &&
1414 git format-patch -o tmp -2 >list &&
1415 test_line_count = 3 list
1418 test_expect_success 'cover letter auto user override' '
1420 test_when_finished "rm -rf tmp;
1421 git config --unset format.coverletter" &&
1423 git config format.coverletter auto &&
1424 git format-patch -o tmp --cover-letter -1 >list &&
1425 test_line_count = 2 list &&
1426 git format-patch -o tmp --cover-letter -2 >list &&
1427 test_line_count = 3 list &&
1428 git format-patch -o tmp --no-cover-letter -1 >list &&
1429 test_line_count = 1 list &&
1430 git format-patch -o tmp --no-cover-letter -2 >list &&
1431 test_line_count = 2 list
1434 test_expect_success 'format-patch --zero-commit' '
1435 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1436 grep "^From " patch2 | sort | uniq >actual &&
1437 echo "From $_z40 Mon Sep 17 00:00:00 2001" >expect &&
1438 test_cmp expect actual
1441 test_expect_success 'From line has expected format' '
1442 git format-patch --stdout v2..v1 >patch2 &&
1443 grep "^From " patch2 >from &&
1444 grep "^From $_x40 Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1445 test_cmp from filtered
1448 test_expect_success 'format-patch format.outputDirectory option' '
1449 test_config format.outputDirectory patches &&
1451 git format-patch master..side &&
1452 test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
1455 test_expect_success 'format-patch -o overrides format.outputDirectory' '
1456 test_config format.outputDirectory patches &&
1457 rm -fr patches patchset &&
1458 git format-patch master..side -o patchset &&
1459 test_path_is_missing patches &&
1460 test_path_is_dir patchset
1463 test_expect_success 'format-patch --base' '
1464 git checkout side &&
1465 git format-patch --stdout --base=HEAD~3 -1 >patch &&
1466 grep "^base-commit:" patch >actual &&
1467 grep "^prerequisite-patch-id:" patch >>actual &&
1468 echo "base-commit: $(git rev-parse HEAD~3)" >expected &&
1469 echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1470 echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1471 test_cmp expected actual
1474 test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1475 test_must_fail git format-patch --base=HEAD -2 &&
1476 test_must_fail git format-patch --base=HEAD~1 -2 &&
1477 git format-patch --stdout --base=HEAD~2 -2 >patch &&
1478 grep "^base-commit:" patch >actual &&
1479 echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
1480 test_cmp expected actual
1483 test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1484 # For history as below:
1486 # ---Q---P---Z---Y---*---X
1490 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1491 git checkout -b topic1 master &&
1492 git rev-parse HEAD >commit-id-base &&
1494 git rev-parse HEAD >commit-id-P &&
1496 git rev-parse HEAD >commit-id-Z &&
1498 git checkout -b topic2 master &&
1502 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1503 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1504 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1505 grep "^base-commit:" patch >actual &&
1506 echo "base-commit: $(cat commit-id-base)" >expected &&
1507 test_cmp expected actual
1510 test_expect_success 'format-patch --base=auto' '
1511 git checkout -b upstream master &&
1512 git checkout -b local upstream &&
1513 git branch --set-upstream-to=upstream &&
1516 git format-patch --stdout --base=auto -2 >patch &&
1517 grep "^base-commit:" patch >actual &&
1518 echo "base-commit: $(git rev-parse upstream)" >expected &&
1519 test_cmp expected actual
1522 test_expect_success 'format-patch errors out when history involves criss-cross' '
1523 # setup criss-cross history
1531 git checkout master &&
1533 git checkout -b xb master &&
1535 git checkout -b xc master &&
1537 git checkout -b xbc xb -- &&
1539 git checkout -b xcb xc -- &&
1540 git branch --set-upstream-to=xbc &&
1546 test_must_fail git format-patch --base=auto -1
1549 test_expect_success 'format-patch format.useAutoBaseoption' '
1550 test_when_finished "git config --unset format.useAutoBase" &&
1551 git checkout local &&
1552 git config format.useAutoBase true &&
1553 git format-patch --stdout -1 >patch &&
1554 grep "^base-commit:" patch >actual &&
1555 echo "base-commit: $(git rev-parse upstream)" >expected &&
1556 test_cmp expected actual
1559 test_expect_success 'format-patch --base overrides format.useAutoBase' '
1560 test_when_finished "git config --unset format.useAutoBase" &&
1561 git config format.useAutoBase true &&
1562 git format-patch --stdout --base=HEAD~1 -1 >patch &&
1563 grep "^base-commit:" patch >actual &&
1564 echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
1565 test_cmp expected actual