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
'
12 for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
16 git commit -m Initial &&
17 git checkout -b side &&
19 for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
22 git commit -m "Side changes #1" &&
24 for i in D E F; do echo "$i"; done >>file &&
25 git update-index file &&
27 git commit -m "Side changes #2" &&
30 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
31 git update-index file &&
33 git commit -m "Side changes #3 with \\n backslash-n in it." &&
35 git checkout master &&
36 git diff-tree -p C2 >patch &&
37 git apply --index <patch &&
39 git commit -m "Master accepts moral equivalent of #2" &&
42 git checkout -b patchid &&
43 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file2 &&
44 for i in 1 2 3 A 4 B C 7 8 9 10 D E F 5 6; do echo "$i"; done >file3 &&
45 for i in 8 9 10; do echo "$i"; done >file &&
46 git add file file2 file3 &&
48 git commit -m "patchid 1" &&
49 for i in 4 A B 7 8 9 10; do echo "$i"; done >file2 &&
50 for i in 8 9 10 5 6; do echo "$i"; done >file3 &&
51 git add file2 file3 &&
53 git commit -m "patchid 2" &&
54 for i in 10 5 6; do echo "$i"; done >file &&
57 git commit -m "patchid 3" &&
62 test_expect_success
'format-patch --ignore-if-in-upstream' '
63 git format-patch --stdout master..side >patch0 &&
64 grep "^From " patch0 >from0 &&
65 test_line_count = 3 from0
68 test_expect_success
'format-patch --ignore-if-in-upstream' '
69 git format-patch --stdout \
70 --ignore-if-in-upstream master..side >patch1 &&
71 grep "^From " patch1 >from1 &&
72 test_line_count = 2 from1
75 test_expect_success
'format-patch --ignore-if-in-upstream handles tags' '
76 git tag -a v1 -m tag side &&
77 git tag -a v2 -m tag master &&
78 git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
79 grep "^From " patch1 >from1 &&
80 test_line_count = 2 from1
83 test_expect_success
"format-patch doesn't consider merge commits" '
84 git checkout -b slave master &&
85 echo "Another line" >>file &&
87 git commit -am "Slave change #1" &&
88 echo "Yet another line" >>file &&
90 git commit -am "Slave change #2" &&
91 git checkout -b merger master &&
93 git merge --no-ff slave &&
94 git format-patch -3 --stdout >patch &&
95 grep "^From " patch >from &&
96 test_line_count = 3 from
99 test_expect_success
'format-patch result applies' '
100 git checkout -b rebuild-0 master &&
102 git rev-list master.. >list &&
103 test_line_count = 2 list
106 test_expect_success
'format-patch --ignore-if-in-upstream result applies' '
107 git checkout -b rebuild-1 master &&
109 git rev-list master.. >list &&
110 test_line_count = 2 list
113 test_expect_success
'commit did not screw up the log message' '
114 git cat-file commit side >actual &&
115 grep "^Side .* with .* backslash-n" actual
118 test_expect_success
'format-patch did not screw up the log message' '
119 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
120 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
123 test_expect_success
'replay did not screw up the log message' '
124 git cat-file commit rebuild-1 >actual &&
125 grep "^Side .* with .* backslash-n" actual
128 test_expect_success
'extra headers' '
129 git config format.headers "To: R E Cipient <rcipient@example.com>
131 git config --add format.headers "Cc: S E Cipient <scipient@example.com>
133 git format-patch --stdout master..side >patch2 &&
134 sed -e "/^\$/q" patch2 >hdrs2 &&
135 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
136 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
139 test_expect_success
'extra headers without newlines' '
140 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
141 git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
142 git format-patch --stdout master..side >patch3 &&
143 sed -e "/^\$/q" patch3 >hdrs3 &&
144 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
145 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
148 test_expect_success
'extra headers with multiple To:s' '
149 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
150 git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
151 git format-patch --stdout master..side >patch4 &&
152 sed -e "/^\$/q" patch4 >hdrs4 &&
153 grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
154 grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
157 test_expect_success
'additional command line cc (ascii)' '
158 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
159 git format-patch --cc="S E Cipient <scipient@example.com>" --stdout master..side >patch5 &&
160 sed -e "/^\$/q" patch5 >hdrs5 &&
161 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
162 grep "^ *S E Cipient <scipient@example.com>\$" hdrs5
165 test_expect_failure
'additional command line cc (rfc822)' '
166 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
167 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side >patch5 &&
168 sed -e "/^\$/q" patch5 >hdrs5 &&
169 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
170 grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" hdrs5
173 test_expect_success
'command line headers' '
174 git config --unset-all format.headers &&
175 git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side >patch6 &&
176 sed -e "/^\$/q" patch6 >hdrs6 &&
177 grep "^Cc: R E Cipient <rcipient@example.com>\$" hdrs6
180 test_expect_success
'configuration headers and command line headers' '
181 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
182 git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side >patch7 &&
183 sed -e "/^\$/q" patch7 >hdrs7 &&
184 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs7 &&
185 grep "^ *S E Cipient <scipient@example.com>\$" hdrs7
188 test_expect_success
'command line To: header (ascii)' '
189 git config --unset-all format.headers &&
190 git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side >patch8 &&
191 sed -e "/^\$/q" patch8 >hdrs8 &&
192 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs8
195 test_expect_failure
'command line To: header (rfc822)' '
196 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side >patch8 &&
197 sed -e "/^\$/q" patch8 >hdrs8 &&
198 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs8
201 test_expect_failure
'command line To: header (rfc2047)' '
202 git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side >patch8 &&
203 sed -e "/^\$/q" patch8 >hdrs8 &&
204 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs8
207 test_expect_success
'configuration To: header (ascii)' '
208 git config format.to "R E Cipient <rcipient@example.com>" &&
209 git format-patch --stdout master..side >patch9 &&
210 sed -e "/^\$/q" patch9 >hdrs9 &&
211 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs9
214 test_expect_failure
'configuration To: header (rfc822)' '
215 git config format.to "R. E. Cipient <rcipient@example.com>" &&
216 git format-patch --stdout master..side >patch9 &&
217 sed -e "/^\$/q" patch9 >hdrs9 &&
218 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs9
221 test_expect_failure
'configuration To: header (rfc2047)' '
222 git config format.to "R Ä Cipient <rcipient@example.com>" &&
223 git format-patch --stdout master..side >patch9 &&
224 sed -e "/^\$/q" patch9 >hdrs9 &&
225 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs9
228 # check_patch <patch>: Verify that <patch> looks like a half-sane
229 # patch email to avoid a false positive with !grep
231 grep -e "^From:" "$1" &&
232 grep -e "^Date:" "$1" &&
233 grep -e "^Subject:" "$1"
236 test_expect_success
'format.from=false' '
237 git -c format.from=false format-patch --stdout master..side >patch &&
238 sed -e "/^\$/q" patch >hdrs &&
240 ! grep "^From: C O Mitter <committer@example.com>\$" hdrs
243 test_expect_success
'format.from=true' '
244 git -c format.from=true format-patch --stdout master..side >patch &&
245 sed -e "/^\$/q" patch >hdrs &&
247 grep "^From: C O Mitter <committer@example.com>\$" hdrs
250 test_expect_success
'format.from with address' '
251 git -c format.from="F R Om <from@example.com>" format-patch --stdout master..side >patch &&
252 sed -e "/^\$/q" patch >hdrs &&
254 grep "^From: F R Om <from@example.com>\$" hdrs
257 test_expect_success
'--no-from overrides format.from' '
258 git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout master..side >patch &&
259 sed -e "/^\$/q" patch >hdrs &&
261 ! grep "^From: F R Om <from@example.com>\$" hdrs
264 test_expect_success
'--from overrides format.from' '
265 git -c format.from="F R Om <from@example.com>" format-patch --from --stdout master..side >patch &&
266 sed -e "/^\$/q" patch >hdrs &&
268 ! grep "^From: F R Om <from@example.com>\$" hdrs
271 test_expect_success
'--no-to overrides config.to' '
272 git config --replace-all format.to \
273 "R E Cipient <rcipient@example.com>" &&
274 git format-patch --no-to --stdout master..side >patch10 &&
275 sed -e "/^\$/q" patch10 >hdrs10 &&
276 check_patch hdrs10 &&
277 ! grep "^To: R E Cipient <rcipient@example.com>\$" hdrs10
280 test_expect_success
'--no-to and --to replaces config.to' '
281 git config --replace-all format.to \
282 "Someone <someone@out.there>" &&
283 git format-patch --no-to --to="Someone Else <else@out.there>" \
284 --stdout master..side >patch11 &&
285 sed -e "/^\$/q" patch11 >hdrs11 &&
286 check_patch hdrs11 &&
287 ! grep "^To: Someone <someone@out.there>\$" hdrs11 &&
288 grep "^To: Someone Else <else@out.there>\$" hdrs11
291 test_expect_success
'--no-cc overrides config.cc' '
292 git config --replace-all format.cc \
293 "C E Cipient <rcipient@example.com>" &&
294 git format-patch --no-cc --stdout master..side >patch12 &&
295 sed -e "/^\$/q" patch12 >hdrs12 &&
296 check_patch hdrs12 &&
297 ! grep "^Cc: C E Cipient <rcipient@example.com>\$" hdrs12
300 test_expect_success
'--no-add-header overrides config.headers' '
301 git config --replace-all format.headers \
302 "Header1: B E Cipient <rcipient@example.com>" &&
303 git format-patch --no-add-header --stdout master..side >patch13 &&
304 sed -e "/^\$/q" patch13 >hdrs13 &&
305 check_patch hdrs13 &&
306 ! grep "^Header1: B E Cipient <rcipient@example.com>\$" hdrs13
309 test_expect_success
'multiple files' '
312 git format-patch -o patches/ master &&
313 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
316 test_expect_success
'reroll count' '
318 git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
319 ! grep -v "^patches/v4-000[0-3]-" list &&
320 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
321 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
324 test_expect_success
'reroll count (-v)' '
326 git format-patch -o patches --cover-letter -v4 master..side >list &&
327 ! grep -v "^patches/v4-000[0-3]-" list &&
328 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
329 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
335 git format-patch
--stdout "$@" >patch &&
336 # Prints everything between the Message-ID and In-Reply-To,
337 # and replaces all Message-ID-lookalikes by a sequence number
339 if (/^(message-id|references|in-reply-to)/i) {
345 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
346 for $k (keys %h) {s/$k/$h{$k}/};
349 print "---\n" if /^From /i;
351 test_cmp
"$expect" actual
354 cat >>expect.no-threading
<<EOF
360 test_expect_success
'no threading' '
362 check_threading expect.no-threading master
365 cat >expect.thread
<<EOF
378 test_expect_success
'thread' '
379 check_threading expect.thread --thread master
382 cat >expect.in-reply-to
<<EOF
397 test_expect_success
'thread in-reply-to' '
398 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
402 cat >expect.cover-letter
<<EOF
419 test_expect_success
'thread cover-letter' '
420 check_threading expect.cover-letter --cover-letter --thread master
423 cat >expect.cl-irt
<<EOF
445 test_expect_success
'thread cover-letter in-reply-to' '
446 check_threading expect.cl-irt --cover-letter \
447 --in-reply-to="<test.message>" --thread master
450 test_expect_success
'thread explicit shallow' '
451 check_threading expect.cl-irt --cover-letter \
452 --in-reply-to="<test.message>" --thread=shallow master
455 cat >expect.deep
<<EOF
469 test_expect_success
'thread deep' '
470 check_threading expect.deep --thread=deep master
473 cat >expect.deep-irt
<<EOF
491 test_expect_success
'thread deep in-reply-to' '
492 check_threading expect.deep-irt --thread=deep \
493 --in-reply-to="<test.message>" master
496 cat >expect.deep-cl
<<EOF
516 test_expect_success
'thread deep cover-letter' '
517 check_threading expect.deep-cl --cover-letter --thread=deep master
520 cat >expect.deep-cl-irt
<<EOF
545 test_expect_success
'thread deep cover-letter in-reply-to' '
546 check_threading expect.deep-cl-irt --cover-letter \
547 --in-reply-to="<test.message>" --thread=deep master
550 test_expect_success
'thread via config' '
551 test_config format.thread true &&
552 check_threading expect.thread master
555 test_expect_success
'thread deep via config' '
556 test_config format.thread deep &&
557 check_threading expect.deep master
560 test_expect_success
'thread config + override' '
561 test_config format.thread deep &&
562 check_threading expect.thread --thread master
565 test_expect_success
'thread config + --no-thread' '
566 test_config format.thread deep &&
567 check_threading expect.no-threading --no-thread master
570 test_expect_success
'excessive subject' '
573 before=$(git hash-object file) &&
574 before=$(git rev-parse --short $before) &&
575 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
576 after=$(git hash-object file) &&
577 after=$(git rev-parse --short $after) &&
578 git update-index file &&
579 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." &&
580 git format-patch -o patches/ master..side &&
581 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
584 test_expect_success
'failure to write cover-letter aborts gracefully' '
585 test_when_finished "rmdir 0000-cover-letter.patch" &&
586 mkdir 0000-cover-letter.patch &&
587 test_must_fail git format-patch --no-renames --cover-letter -1
590 test_expect_success
'cover-letter inherits diff options' '
593 git format-patch --no-renames --cover-letter -1 &&
594 check_patch 0000-cover-letter.patch &&
595 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
596 git format-patch --cover-letter -1 -M &&
597 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
601 This is an excessively long subject line for a message due to the
602 habit some projects have of not having a short, one-line subject at
603 the start of the commit message, but rather sticking a whole
604 paragraph right at the start as the only thing in the commit
605 message. It had better not become the filename for the patch.
610 test_expect_success
'shortlog of cover-letter wraps overly-long onelines' '
611 git format-patch --cover-letter -2 &&
612 sed -e "1,/A U Thor/d" -e "/^\$/q" 0000-cover-letter.patch >output &&
613 test_cmp expect output
617 index $before..$after 100644
628 test_expect_success
'format-patch respects -U' '
629 git format-patch -U4 -2 &&
630 sed -e "1,/^diff/d" -e "/^+5/q" \
631 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
633 test_cmp expect output
638 diff --git a/file b/file
639 index $before..$after 100644
649 test_expect_success
'format-patch -p suppresses stat' '
650 git format-patch -p -2 &&
651 sed -e "1,/^\$/d" -e "/^+5/q" 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&
652 test_cmp expect output
655 test_expect_success
'format-patch from a subdirectory (1)' '
666 echo "Oops? $filename"
673 test_expect_success
'format-patch from a subdirectory (2)' '
678 git format-patch -1 -o ..
684 echo "Oops? $filename"
688 basename=$(expr "$filename" : ".*/\(.*\)") &&
689 test -f "sub/$basename"
692 test_expect_success
'format-patch from a subdirectory (3)' '
698 git format-patch -1 -o "$TRASH_DIRECTORY"
700 basename=$(expr "$filename" : ".*/\(.*\)") &&
704 test_expect_success
'format-patch --in-reply-to' '
705 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" >patch8 &&
706 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
707 grep "^References: <baz@foo.bar>" patch8
710 test_expect_success
'format-patch --signoff' '
711 git format-patch -1 --signoff --stdout >out &&
712 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
715 test_expect_success
'format-patch --notes --signoff' '
716 git notes --ref test add -m "test message" HEAD &&
717 git format-patch -1 --signoff --stdout --notes=test >out &&
718 # Three dashes must come after S-o-b
719 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
720 sed "1,/^Signed-off-by: /d" out | grep "test message" &&
721 # Notes message must come after three dashes
722 ! sed "/^---$/q" out | grep "test message" &&
723 sed "1,/^---$/d" out | grep "test message"
726 test_expect_success
'format-patch notes output control' '
727 git notes add -m "notes config message" HEAD &&
728 test_when_finished git notes remove HEAD &&
730 git format-patch -1 --stdout >out &&
731 ! grep "notes config message" out &&
732 git format-patch -1 --stdout --notes >out &&
733 grep "notes config message" out &&
734 git format-patch -1 --stdout --no-notes >out &&
735 ! grep "notes config message" out &&
736 git format-patch -1 --stdout --notes --no-notes >out &&
737 ! grep "notes config message" out &&
738 git format-patch -1 --stdout --no-notes --notes >out &&
739 grep "notes config message" out &&
741 test_config format.notes true &&
742 git format-patch -1 --stdout >out &&
743 grep "notes config message" out &&
744 git format-patch -1 --stdout --notes >out &&
745 grep "notes config message" out &&
746 git format-patch -1 --stdout --no-notes >out &&
747 ! grep "notes config message" out &&
748 git format-patch -1 --stdout --notes --no-notes >out &&
749 ! grep "notes config message" out &&
750 git format-patch -1 --stdout --no-notes --notes >out &&
751 grep "notes config message" out
754 test_expect_success
'format-patch with multiple notes refs' '
755 git notes --ref note1 add -m "this is note 1" HEAD &&
756 test_when_finished git notes --ref note1 remove HEAD &&
757 git notes --ref note2 add -m "this is note 2" HEAD &&
758 test_when_finished git notes --ref note2 remove HEAD &&
760 git format-patch -1 --stdout >out &&
761 ! grep "this is note 1" out &&
762 ! grep "this is note 2" out &&
763 git format-patch -1 --stdout --notes=note1 >out &&
764 grep "this is note 1" out &&
765 ! grep "this is note 2" out &&
766 git format-patch -1 --stdout --notes=note2 >out &&
767 ! grep "this is note 1" out &&
768 grep "this is note 2" out &&
769 git format-patch -1 --stdout --notes=note1 --notes=note2 >out &&
770 grep "this is note 1" out &&
771 grep "this is note 2" out &&
773 test_config format.notes note1 &&
774 git format-patch -1 --stdout >out &&
775 grep "this is note 1" out &&
776 ! grep "this is note 2" out &&
777 git format-patch -1 --stdout --no-notes >out &&
778 ! grep "this is note 1" out &&
779 ! grep "this is note 2" out &&
780 git format-patch -1 --stdout --notes=note2 >out &&
781 grep "this is note 1" out &&
782 grep "this is note 2" out &&
783 git format-patch -1 --stdout --no-notes --notes=note2 >out &&
784 ! grep "this is note 1" out &&
785 grep "this is note 2" out &&
787 git config --add format.notes note2 &&
788 git format-patch -1 --stdout >out &&
789 grep "this is note 1" out &&
790 grep "this is note 2" out &&
791 git format-patch -1 --stdout --no-notes >out &&
792 ! grep "this is note 1" out &&
793 ! grep "this is note 2" out
796 test_expect_success
'format-patch with multiple notes refs in config' '
797 test_when_finished "test_unconfig format.notes" &&
799 git notes --ref note1 add -m "this is note 1" HEAD &&
800 test_when_finished git notes --ref note1 remove HEAD &&
801 git notes --ref note2 add -m "this is note 2" HEAD &&
802 test_when_finished git notes --ref note2 remove HEAD &&
804 git config format.notes note1 &&
805 git format-patch -1 --stdout >out &&
806 grep "this is note 1" out &&
807 ! grep "this is note 2" out &&
808 git config format.notes note2 &&
809 git format-patch -1 --stdout >out &&
810 ! grep "this is note 1" out &&
811 grep "this is note 2" out &&
812 git config --add format.notes note1 &&
813 git format-patch -1 --stdout >out &&
814 grep "this is note 1" out &&
815 grep "this is note 2" out &&
817 git config --replace-all format.notes note1 &&
818 git config --add format.notes false &&
819 git format-patch -1 --stdout >out &&
820 ! grep "this is note 1" out &&
821 ! grep "this is note 2" out &&
822 git config --add format.notes note2 &&
823 git format-patch -1 --stdout >out &&
824 ! grep "this is note 1" out &&
825 grep "this is note 2" out
828 echo "fatal: --name-only does not make sense" >expect.name-only
829 echo "fatal: --name-status does not make sense" >expect.name-status
830 echo "fatal: --check does not make sense" >expect.check
832 test_expect_success
'options no longer allowed for format-patch' '
833 test_must_fail git format-patch --name-only 2>output &&
834 test_i18ncmp expect.name-only output &&
835 test_must_fail git format-patch --name-status 2>output &&
836 test_i18ncmp expect.name-status output &&
837 test_must_fail git format-patch --check 2>output &&
838 test_i18ncmp expect.check output
841 test_expect_success
'format-patch --numstat should produce a patch' '
842 git format-patch --numstat --stdout master..side >output &&
843 grep "^diff --git a/" output >diff &&
844 test_line_count = 5 diff
847 test_expect_success
'format-patch -- <path>' '
848 git format-patch master..side -- file 2>error &&
849 ! grep "Use .--" error
852 test_expect_success
'format-patch --ignore-if-in-upstream HEAD' '
853 git format-patch --ignore-if-in-upstream HEAD
856 test_expect_success
'get git version' '
857 git_version=$(git --version) &&
858 git_version=${git_version##* }
862 printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
865 test_expect_success
'format-patch default signature' '
866 git format-patch --stdout -1 >patch &&
867 tail -n 3 patch >output &&
869 test_cmp expect output
872 test_expect_success
'format-patch --signature' '
873 git format-patch --stdout --signature="my sig" -1 >patch &&
874 tail -n 3 patch >output &&
875 signature "my sig" >expect &&
876 test_cmp expect output
879 test_expect_success
'format-patch with format.signature config' '
880 git config format.signature "config sig" &&
881 git format-patch --stdout -1 >output &&
882 grep "config sig" output
885 test_expect_success
'format-patch --signature overrides format.signature' '
886 git config format.signature "config sig" &&
887 git format-patch --stdout --signature="overrides" -1 >output &&
888 ! grep "config sig" output &&
889 grep "overrides" output
892 test_expect_success
'format-patch --no-signature ignores format.signature' '
893 git config format.signature "config sig" &&
894 git format-patch --stdout --signature="my sig" --no-signature \
896 check_patch output &&
897 ! grep "config sig" output &&
898 ! grep "my sig" output &&
899 ! grep "^-- \$" output
902 test_expect_success
'format-patch --signature --cover-letter' '
903 git config --unset-all format.signature &&
904 git format-patch --stdout --signature="my sig" --cover-letter \
906 grep "my sig" output >sig &&
907 test_line_count = 2 sig
910 test_expect_success
'format.signature="" suppresses signatures' '
911 git config format.signature "" &&
912 git format-patch --stdout -1 >output &&
913 check_patch output &&
914 ! grep "^-- \$" output
917 test_expect_success
'format-patch --no-signature suppresses signatures' '
918 git config --unset-all format.signature &&
919 git format-patch --stdout --no-signature -1 >output &&
920 check_patch output &&
921 ! grep "^-- \$" output
924 test_expect_success
'format-patch --signature="" suppresses signatures' '
925 git format-patch --stdout --signature="" -1 >output &&
926 check_patch output &&
927 ! grep "^-- \$" output
930 test_expect_success
'prepare mail-signature input' '
931 cat >mail-signature <<-\EOF
933 Test User <test.email@kernel.org>
934 http://git.kernel.org/cgit/git/git.git
936 git.kernel.org/?p=git/git.git;a=summary
941 test_expect_success
'--signature-file=file works' '
942 git format-patch --stdout --signature-file=mail-signature -1 >output &&
943 check_patch output &&
944 sed -e "1,/^-- \$/d" output >actual &&
946 cat mail-signature && echo
948 test_cmp expect actual
951 test_expect_success
'format.signaturefile works' '
952 test_config format.signaturefile mail-signature &&
953 git format-patch --stdout -1 >output &&
954 check_patch output &&
955 sed -e "1,/^-- \$/d" output >actual &&
957 cat mail-signature && echo
959 test_cmp expect actual
962 test_expect_success
'--no-signature suppresses format.signaturefile ' '
963 test_config format.signaturefile mail-signature &&
964 git format-patch --stdout --no-signature -1 >output &&
965 check_patch output &&
966 ! grep "^-- \$" output
969 test_expect_success
'--signature-file overrides format.signaturefile' '
970 cat >other-mail-signature <<-\EOF &&
971 Use this other signature instead of mail-signature.
973 test_config format.signaturefile mail-signature &&
974 git format-patch --stdout \
975 --signature-file=other-mail-signature -1 >output &&
976 check_patch output &&
977 sed -e "1,/^-- \$/d" output >actual &&
979 cat other-mail-signature && echo
981 test_cmp expect actual
984 test_expect_success
'--signature overrides format.signaturefile' '
985 test_config format.signaturefile mail-signature &&
986 git format-patch --stdout --signature="my sig" -1 >output &&
987 check_patch output &&
991 test_expect_success TTY
'format-patch --stdout paginates' '
993 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
994 test_path_is_file pager_used
997 test_expect_success TTY
'format-patch --stdout pagination can be disabled' '
999 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
1000 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
1001 test_path_is_missing pager_used &&
1002 test_path_is_missing .git/pager_used
1005 test_expect_success
'format-patch handles multi-line subjects' '
1007 echo content >>file &&
1008 for i in one two three; do echo $i; done >msg &&
1010 git commit -F msg &&
1011 git format-patch -o patches -1 &&
1012 grep ^Subject: patches/0001-one.patch >actual &&
1013 echo "Subject: [PATCH] one two three" >expect &&
1014 test_cmp expect actual
1017 test_expect_success
'format-patch handles multi-line encoded subjects' '
1019 echo content >>file &&
1020 for i in en två tre; do echo $i; done >msg &&
1022 git commit -F msg &&
1023 git format-patch -o patches -1 &&
1024 grep ^Subject: patches/0001-en.patch >actual &&
1025 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
1026 test_cmp expect actual
1030 M64
=$M8$M8$M8$M8$M8$M8$M8$M8
1031 M512
=$M64$M64$M64$M64$M64$M64$M64$M64
1033 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1034 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1035 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1036 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1037 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1038 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1039 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1041 test_expect_success
'format-patch wraps extremely long subject (ascii)' '
1042 echo content >>file &&
1044 git commit -m "$M512" &&
1045 git format-patch --stdout -1 >patch &&
1046 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1047 test_cmp expect subject
1051 M64
=$M8$M8$M8$M8$M8$M8$M8$M8
1052 M512
=$M64$M64$M64$M64$M64$M64$M64$M64
1054 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1055 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1056 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1057 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1058 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1059 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1060 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1061 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1062 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1063 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1064 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1065 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1066 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1067 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1068 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1069 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1070 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1071 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1072 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1073 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1074 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1075 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1076 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1079 test_expect_success
'format-patch wraps extremely long subject (rfc2047)' '
1081 echo content >>file &&
1083 git commit -m "$M512" &&
1084 git format-patch --stdout -1 >patch &&
1085 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1086 test_cmp expect subject
1090 echo content
>>file &&
1092 GIT_AUTHOR_NAME
=$1 git commit
-m author-check
&&
1093 git format-patch
--stdout -1 >patch &&
1094 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual
&&
1095 test_cmp expect actual
1099 From: "Foo B. Bar" <author@example.com>
1101 test_expect_success
'format-patch quotes dot in from-headers' '
1102 check_author "Foo B. Bar"
1106 From: "Foo \"The Baz\" Bar" <author@example.com>
1108 test_expect_success
'format-patch quotes double-quote in from-headers' '
1109 check_author "Foo \"The Baz\" Bar"
1113 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1115 test_expect_success
'format-patch uses rfc2047-encoded from-headers when necessary' '
1116 check_author "Föo Bar"
1120 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1122 test_expect_success
'rfc2047-encoded from-headers leave no rfc822 specials' '
1123 check_author "Föo B. Bar"
1127 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1128 <author@example.com>
1130 test_expect_success
'format-patch wraps moderately long from-header (ascii)' '
1131 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1135 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1136 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1137 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1139 test_expect_success
'format-patch wraps extremely long from-header (ascii)' '
1140 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"
1144 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1145 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1146 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1148 test_expect_success
'format-patch wraps extremely long from-header (rfc822)' '
1149 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"
1153 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1154 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1155 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1156 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1157 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1159 test_expect_success
'format-patch wraps extremely long from-header (rfc2047)' '
1160 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"
1164 From: Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1165 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1166 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1168 test_expect_success
'format-patch wraps extremely long from-header (non-ASCII without Q-encoding)' '
1169 echo content >>file &&
1171 GIT_AUTHOR_NAME="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" \
1172 git commit -m author-check &&
1173 git format-patch --no-encode-email-headers --stdout -1 >patch &&
1174 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1175 test_cmp expect actual
1179 Subject: [PATCH] Foö
1181 test_expect_success
'subject lines are unencoded with --no-encode-email-headers' '
1182 echo content >>file &&
1184 git commit -m "Foö" &&
1185 git format-patch --no-encode-email-headers -1 --stdout >patch &&
1186 grep ^Subject: patch >actual &&
1187 test_cmp expect actual
1191 Subject: [PATCH] Foö
1193 test_expect_success
'subject lines are unencoded with format.encodeEmailHeaders=false' '
1194 echo content >>file &&
1196 git commit -m "Foö" &&
1197 git config format.encodeEmailHeaders false &&
1198 git format-patch -1 --stdout >patch &&
1199 grep ^Subject: patch >actual &&
1200 test_cmp expect actual
1204 Subject: [PATCH] =?UTF-8?q?Fo=C3=B6?=
1206 test_expect_success
'--encode-email-headers overrides format.encodeEmailHeaders' '
1207 echo content >>file &&
1209 git commit -m "Foö" &&
1210 git config format.encodeEmailHeaders false &&
1211 git format-patch --encode-email-headers -1 --stdout >patch &&
1212 grep ^Subject: patch >actual &&
1213 test_cmp expect actual
1217 Subject: header with . in it
1219 test_expect_success
'subject lines do not have 822 atom-quoting' '
1220 echo content >>file &&
1222 git commit -m "header with . in it" &&
1223 git format-patch -k -1 --stdout >patch &&
1224 grep ^Subject: patch >actual &&
1225 test_cmp expect actual
1229 Subject: [PREFIX 1/1] header with . in it
1231 test_expect_success
'subject prefixes have space prepended' '
1232 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1233 grep ^Subject: patch >actual &&
1234 test_cmp expect actual
1238 Subject: [1/1] header with . in it
1240 test_expect_success
'empty subject prefix does not have extra space' '
1241 git format-patch -n -1 --stdout --subject-prefix= >patch &&
1242 grep ^Subject: patch >actual &&
1243 test_cmp expect actual
1246 test_expect_success
'--rfc' '
1247 cat >expect <<-\EOF &&
1248 Subject: [RFC PATCH 1/1] header with . in it
1250 git format-patch -n -1 --stdout --rfc >patch &&
1251 grep ^Subject: patch >actual &&
1252 test_cmp expect actual
1255 test_expect_success
'--from=ident notices bogus ident' '
1256 test_must_fail git format-patch -1 --stdout --from=foo >patch
1259 test_expect_success
'--from=ident replaces author' '
1260 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1261 cat >expect <<-\EOF &&
1262 From: Me <me@example.com>
1264 From: A U Thor <author@example.com>
1267 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1268 test_cmp expect patch.head
1271 test_expect_success
'--from uses committer ident' '
1272 git format-patch -1 --stdout --from >patch &&
1273 cat >expect <<-\EOF &&
1274 From: C O Mitter <committer@example.com>
1276 From: A U Thor <author@example.com>
1279 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1280 test_cmp expect patch.head
1283 test_expect_success
'--from omits redundant in-body header' '
1284 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1285 cat >expect <<-\EOF &&
1286 From: A U Thor <author@example.com>
1289 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1290 test_cmp expect patch.head
1293 test_expect_success
'in-body headers trigger content encoding' '
1294 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1295 test_when_finished "git reset --hard HEAD^" &&
1296 git format-patch -1 --stdout --from >patch &&
1297 cat >expect <<-\EOF &&
1298 From: C O Mitter <committer@example.com>
1299 Content-Type: text/plain; charset=UTF-8
1301 From: éxötìc <author@example.com>
1304 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" patch >patch.head &&
1305 test_cmp expect patch.head
1310 C
=$
(git commit-tree HEAD^^
{tree
} -p HEAD
) &&
1311 git format-patch
--stdout --signoff $C^..
$C >append_signoff.
patch &&
1312 sed -n -e "1,/^---$/p" append_signoff.
patch |
1313 egrep -n "^Subject|Sign|^$"
1316 test_expect_success
'signoff: commit with no body' '
1317 append_signoff </dev/null >actual &&
1318 cat <<-\EOF | sed "s/EOL$//" >expect &&
1319 4:Subject: [PATCH] EOL
1321 9:Signed-off-by: C O Mitter <committer@example.com>
1323 test_cmp expect actual
1326 test_expect_success
'signoff: commit with only subject' '
1327 echo subject | append_signoff >actual &&
1328 cat >expect <<-\EOF &&
1329 4:Subject: [PATCH] subject
1331 9:Signed-off-by: C O Mitter <committer@example.com>
1333 test_cmp expect actual
1336 test_expect_success
'signoff: commit with only subject that does not end with NL' '
1337 printf subject | append_signoff >actual &&
1338 cat >expect <<-\EOF &&
1339 4:Subject: [PATCH] subject
1341 9:Signed-off-by: C O Mitter <committer@example.com>
1343 test_cmp expect actual
1346 test_expect_success
'signoff: no existing signoffs' '
1347 append_signoff <<-\EOF >actual &&
1352 cat >expect <<-\EOF &&
1353 4:Subject: [PATCH] subject
1356 11:Signed-off-by: C O Mitter <committer@example.com>
1358 test_cmp expect actual
1361 test_expect_success
'signoff: no existing signoffs and no trailing NL' '
1362 printf "subject\n\nbody" | append_signoff >actual &&
1363 cat >expect <<-\EOF &&
1364 4:Subject: [PATCH] subject
1367 11:Signed-off-by: C O Mitter <committer@example.com>
1369 test_cmp expect actual
1372 test_expect_success
'signoff: some random signoff' '
1373 append_signoff <<-\EOF >actual &&
1378 Signed-off-by: my@house
1380 cat >expect <<-\EOF &&
1381 4:Subject: [PATCH] subject
1384 11:Signed-off-by: my@house
1385 12:Signed-off-by: C O Mitter <committer@example.com>
1387 test_cmp expect actual
1390 test_expect_success
'signoff: misc conforming footer elements' '
1391 append_signoff <<-\EOF >actual &&
1396 Signed-off-by: my@house
1397 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1398 Tested-by: Some One <someone@example.com>
1401 cat >expect <<-\EOF &&
1402 4:Subject: [PATCH] subject
1405 11:Signed-off-by: my@house
1406 15:Signed-off-by: C O Mitter <committer@example.com>
1408 test_cmp expect actual
1411 test_expect_success
'signoff: some random signoff-alike' '
1412 append_signoff <<-\EOF >actual &&
1416 Fooled-by-me: my@house
1418 cat >expect <<-\EOF &&
1419 4:Subject: [PATCH] subject
1422 12:Signed-off-by: C O Mitter <committer@example.com>
1424 test_cmp expect actual
1427 test_expect_success
'signoff: not really a signoff' '
1428 append_signoff <<-\EOF >actual &&
1431 I want to mention about Signed-off-by: here.
1433 cat >expect <<-\EOF &&
1434 4:Subject: [PATCH] subject
1436 9:I want to mention about Signed-off-by: here.
1438 11:Signed-off-by: C O Mitter <committer@example.com>
1440 test_cmp expect actual
1443 test_expect_success
'signoff: not really a signoff (2)' '
1444 append_signoff <<-\EOF >actual &&
1448 Signed-off-by: example happens to be wrapped here.
1450 cat >expect <<-\EOF &&
1451 4:Subject: [PATCH] subject
1453 10:Signed-off-by: example happens to be wrapped here.
1454 11:Signed-off-by: C O Mitter <committer@example.com>
1456 test_cmp expect actual
1459 test_expect_success
'signoff: valid S-o-b paragraph in the middle' '
1460 append_signoff <<-\EOF >actual &&
1463 Signed-off-by: my@house
1464 Signed-off-by: your@house
1468 cat >expect <<-\EOF &&
1469 4:Subject: [PATCH] subject
1471 9:Signed-off-by: my@house
1472 10:Signed-off-by: your@house
1475 14:Signed-off-by: C O Mitter <committer@example.com>
1477 test_cmp expect actual
1480 test_expect_success
'signoff: the same signoff at the end' '
1481 append_signoff <<-\EOF >actual &&
1486 Signed-off-by: C O Mitter <committer@example.com>
1488 cat >expect <<-\EOF &&
1489 4:Subject: [PATCH] subject
1492 11:Signed-off-by: C O Mitter <committer@example.com>
1494 test_cmp expect actual
1497 test_expect_success
'signoff: the same signoff at the end, no trailing NL' '
1498 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1499 append_signoff >actual &&
1500 cat >expect <<-\EOF &&
1501 4:Subject: [PATCH] subject
1503 9:Signed-off-by: C O Mitter <committer@example.com>
1505 test_cmp expect actual
1508 test_expect_success
'signoff: the same signoff NOT at the end' '
1509 append_signoff <<-\EOF >actual &&
1514 Signed-off-by: C O Mitter <committer@example.com>
1515 Signed-off-by: my@house
1517 cat >expect <<-\EOF &&
1518 4:Subject: [PATCH] subject
1521 11:Signed-off-by: C O Mitter <committer@example.com>
1522 12:Signed-off-by: my@house
1524 test_cmp expect actual
1527 test_expect_success
'signoff: tolerate garbage in conforming footer' '
1528 append_signoff <<-\EOF >actual &&
1535 Signed-off-by: C O Mitter <committer@example.com>
1537 cat >expect <<-\EOF &&
1538 4:Subject: [PATCH] subject
1541 13:Signed-off-by: C O Mitter <committer@example.com>
1543 test_cmp expect actual
1546 test_expect_success
'signoff: respect trailer config' '
1547 append_signoff <<-\EOF >actual &&
1553 cat >expect <<-\EOF &&
1554 4:Subject: [PATCH] subject
1557 12:Signed-off-by: C O Mitter <committer@example.com>
1559 test_cmp expect actual &&
1561 test_config trailer.Myfooter.ifexists add &&
1562 append_signoff <<-\EOF >actual &&
1568 cat >expect <<-\EOF &&
1569 4:Subject: [PATCH] subject
1571 11:Signed-off-by: C O Mitter <committer@example.com>
1573 test_cmp expect actual
1576 test_expect_success
'signoff: footer begins with non-signoff without @ sign' '
1577 append_signoff <<-\EOF >actual &&
1584 Change-id: Ideadbeef
1585 Signed-off-by: C O Mitter <committer@example.com>
1588 cat >expect <<-\EOF &&
1589 4:Subject: [PATCH] subject
1592 14:Signed-off-by: C O Mitter <committer@example.com>
1594 test_cmp expect actual
1597 test_expect_success
'format patch ignores color.ui' '
1598 test_unconfig color.ui &&
1599 git format-patch --stdout -1 >expect &&
1600 test_config color.ui always &&
1601 git format-patch --stdout -1 >actual &&
1602 test_cmp expect actual
1605 test_expect_success
'format patch respects diff.relative' '
1608 echo other content >subdir/file2 &&
1609 git add subdir/file2 &&
1610 git commit -F msg &&
1611 test_unconfig diff.relative &&
1612 git format-patch --relative=subdir --stdout -1 >expect &&
1613 test_config diff.relative true &&
1614 git -C subdir format-patch --stdout -1 >actual &&
1615 test_cmp expect actual
1618 test_expect_success
'cover letter with invalid --cover-from-description and config' '
1619 test_config branch.rebuild-1.description "config subject
1622 test_must_fail git format-patch --cover-letter --cover-from-description garbage master &&
1623 test_config format.coverFromDescription garbage &&
1624 test_must_fail git format-patch --cover-letter master
1627 test_expect_success
'cover letter with format.coverFromDescription = default' '
1628 test_config branch.rebuild-1.description "config subject
1631 test_config format.coverFromDescription default &&
1632 git checkout rebuild-1 &&
1633 git format-patch --stdout --cover-letter master >actual &&
1634 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1635 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1636 grep "^config subject$" actual &&
1637 grep "^body$" actual
1640 test_expect_success
'cover letter with --cover-from-description default' '
1641 test_config branch.rebuild-1.description "config subject
1644 git checkout rebuild-1 &&
1645 git format-patch --stdout --cover-letter --cover-from-description default master >actual &&
1646 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1647 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1648 grep "^config subject$" actual &&
1649 grep "^body$" actual
1652 test_expect_success
'cover letter with format.coverFromDescription = none' '
1653 test_config branch.rebuild-1.description "config subject
1656 test_config format.coverFromDescription none &&
1657 git checkout rebuild-1 &&
1658 git format-patch --stdout --cover-letter master >actual &&
1659 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1660 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1661 ! grep "^config subject$" actual &&
1662 ! grep "^body$" actual
1665 test_expect_success
'cover letter with --cover-from-description none' '
1666 test_config branch.rebuild-1.description "config subject
1669 git checkout rebuild-1 &&
1670 git format-patch --stdout --cover-letter --cover-from-description none master >actual &&
1671 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1672 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1673 ! grep "^config subject$" actual &&
1674 ! grep "^body$" actual
1677 test_expect_success
'cover letter with format.coverFromDescription = message' '
1678 test_config branch.rebuild-1.description "config subject
1681 test_config format.coverFromDescription message &&
1682 git checkout rebuild-1 &&
1683 git format-patch --stdout --cover-letter master >actual &&
1684 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1685 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1686 grep "^config subject$" actual &&
1687 grep "^body$" actual
1690 test_expect_success
'cover letter with --cover-from-description message' '
1691 test_config branch.rebuild-1.description "config subject
1694 git checkout rebuild-1 &&
1695 git format-patch --stdout --cover-letter --cover-from-description message master >actual &&
1696 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1697 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1698 grep "^config subject$" actual &&
1699 grep "^body$" actual
1702 test_expect_success
'cover letter with format.coverFromDescription = subject' '
1703 test_config branch.rebuild-1.description "config subject
1706 test_config format.coverFromDescription subject &&
1707 git checkout rebuild-1 &&
1708 git format-patch --stdout --cover-letter master >actual &&
1709 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1710 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1711 ! grep "^config subject$" actual &&
1712 grep "^body$" actual
1715 test_expect_success
'cover letter with --cover-from-description subject' '
1716 test_config branch.rebuild-1.description "config subject
1719 git checkout rebuild-1 &&
1720 git format-patch --stdout --cover-letter --cover-from-description subject master >actual &&
1721 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1722 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1723 ! grep "^config subject$" actual &&
1724 grep "^body$" actual
1727 test_expect_success
'cover letter with format.coverFromDescription = auto (short subject line)' '
1728 test_config branch.rebuild-1.description "config subject
1731 test_config format.coverFromDescription auto &&
1732 git checkout rebuild-1 &&
1733 git format-patch --stdout --cover-letter master >actual &&
1734 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1735 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1736 ! grep "^config subject$" actual &&
1737 grep "^body$" actual
1740 test_expect_success
'cover letter with --cover-from-description auto (short subject line)' '
1741 test_config branch.rebuild-1.description "config subject
1744 git checkout rebuild-1 &&
1745 git format-patch --stdout --cover-letter --cover-from-description auto master >actual &&
1746 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1747 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1748 ! grep "^config subject$" actual &&
1749 grep "^body$" actual
1752 test_expect_success
'cover letter with format.coverFromDescription = auto (long subject line)' '
1753 test_config branch.rebuild-1.description "this is a really long first line and it is over 100 characters long which is the threshold for long subjects
1756 test_config format.coverFromDescription auto &&
1757 git checkout rebuild-1 &&
1758 git format-patch --stdout --cover-letter master >actual &&
1759 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1760 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1761 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1762 grep "^body$" actual
1765 test_expect_success
'cover letter with --cover-from-description auto (long subject line)' '
1766 test_config branch.rebuild-1.description "this is a really long first line and it is over 100 characters long which is the threshold for long subjects
1769 git checkout rebuild-1 &&
1770 git format-patch --stdout --cover-letter --cover-from-description auto master >actual &&
1771 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1772 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1773 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1774 grep "^body$" actual
1777 test_expect_success
'cover letter with command-line --cover-from-description overrides config' '
1778 test_config branch.rebuild-1.description "config subject
1781 test_config format.coverFromDescription none &&
1782 git checkout rebuild-1 &&
1783 git format-patch --stdout --cover-letter --cover-from-description subject master >actual &&
1784 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1785 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1786 ! grep "^config subject$" actual &&
1787 grep "^body$" actual
1790 test_expect_success
'cover letter using branch description (1)' '
1791 git checkout rebuild-1 &&
1792 test_config branch.rebuild-1.description hello &&
1793 git format-patch --stdout --cover-letter master >actual &&
1797 test_expect_success
'cover letter using branch description (2)' '
1798 git checkout rebuild-1 &&
1799 test_config branch.rebuild-1.description hello &&
1800 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1804 test_expect_success
'cover letter using branch description (3)' '
1805 git checkout rebuild-1 &&
1806 test_config branch.rebuild-1.description hello &&
1807 git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1811 test_expect_success
'cover letter using branch description (4)' '
1812 git checkout rebuild-1 &&
1813 test_config branch.rebuild-1.description hello &&
1814 git format-patch --stdout --cover-letter master.. >actual &&
1818 test_expect_success
'cover letter using branch description (5)' '
1819 git checkout rebuild-1 &&
1820 test_config branch.rebuild-1.description hello &&
1821 git format-patch --stdout --cover-letter -2 HEAD >actual &&
1825 test_expect_success
'cover letter using branch description (6)' '
1826 git checkout rebuild-1 &&
1827 test_config branch.rebuild-1.description hello &&
1828 git format-patch --stdout --cover-letter -2 >actual &&
1832 test_expect_success
'cover letter with nothing' '
1833 git format-patch --stdout --cover-letter >actual &&
1834 test_line_count = 0 actual
1837 test_expect_success
'cover letter auto' '
1839 test_when_finished "rm -rf tmp;
1840 git config --unset format.coverletter" &&
1842 git config format.coverletter auto &&
1843 git format-patch -o tmp -1 >list &&
1844 test_line_count = 1 list &&
1845 git format-patch -o tmp -2 >list &&
1846 test_line_count = 3 list
1849 test_expect_success
'cover letter auto user override' '
1851 test_when_finished "rm -rf tmp;
1852 git config --unset format.coverletter" &&
1854 git config format.coverletter auto &&
1855 git format-patch -o tmp --cover-letter -1 >list &&
1856 test_line_count = 2 list &&
1857 git format-patch -o tmp --cover-letter -2 >list &&
1858 test_line_count = 3 list &&
1859 git format-patch -o tmp --no-cover-letter -1 >list &&
1860 test_line_count = 1 list &&
1861 git format-patch -o tmp --no-cover-letter -2 >list &&
1862 test_line_count = 2 list
1865 test_expect_success
'format-patch --zero-commit' '
1866 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1867 grep "^From " patch2 | sort | uniq >actual &&
1868 echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
1869 test_cmp expect actual
1872 test_expect_success
'From line has expected format' '
1873 git format-patch --stdout v2..v1 >patch2 &&
1874 grep "^From " patch2 >from &&
1875 grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1876 test_cmp from filtered
1879 test_expect_success
'format-patch -o with no leading directories' '
1881 git format-patch -o patches master..side &&
1882 count=$(git rev-list --count master..side) &&
1884 test_line_count = $count list
1887 test_expect_success
'format-patch -o with leading existing directories' '
1888 rm -rf existing-dir &&
1889 mkdir existing-dir &&
1890 git format-patch -o existing-dir/patches master..side &&
1891 count=$(git rev-list --count master..side) &&
1892 ls existing-dir/patches >list &&
1893 test_line_count = $count list
1896 test_expect_success
'format-patch -o with leading non-existing directories' '
1897 rm -rf non-existing-dir &&
1898 git format-patch -o non-existing-dir/patches master..side &&
1899 count=$(git rev-list --count master..side) &&
1900 test_path_is_dir non-existing-dir &&
1901 ls non-existing-dir/patches >list &&
1902 test_line_count = $count list
1905 test_expect_success
'format-patch format.outputDirectory option' '
1906 test_config format.outputDirectory patches &&
1908 git format-patch master..side &&
1909 count=$(git rev-list --count master..side) &&
1911 test_line_count = $count list
1914 test_expect_success
'format-patch -o overrides format.outputDirectory' '
1915 test_config format.outputDirectory patches &&
1916 rm -fr patches patchset &&
1917 git format-patch master..side -o patchset &&
1918 test_path_is_missing patches &&
1919 test_path_is_dir patchset
1922 test_expect_success
'format-patch --base' '
1923 git checkout patchid &&
1925 git format-patch --stdout --base=HEAD~3 -1 >patch &&
1926 tail -n 7 patch >actual1 &&
1928 git format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&
1929 tail -n 7 patch >actual2 &&
1932 git rev-parse HEAD~3 >commit-id-base &&
1933 echo "base-commit: $(cat commit-id-base)" >>expect &&
1935 git show --patch HEAD~2 >patch &&
1936 git patch-id --stable <patch >patch.id.raw &&
1937 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
1939 git show --patch HEAD~1 >patch &&
1940 git patch-id --stable <patch >patch.id.raw &&
1941 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
1943 signature >>expect &&
1944 test_cmp expect actual1 &&
1945 test_cmp expect actual2 &&
1948 echo "base-commit: $(cat commit-id-base)" >>fail &&
1950 git show --patch HEAD~2 >patch &&
1951 git patch-id --unstable <patch >patch.id.raw &&
1952 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
1954 git show --patch HEAD~1 >patch &&
1955 git patch-id --unstable <patch >patch.id.raw &&
1956 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
1959 ! test_cmp fail actual1 &&
1960 ! test_cmp fail actual2
1963 test_expect_success
'format-patch --base errors out when base commit is in revision list' '
1964 test_must_fail git format-patch --base=HEAD -2 &&
1965 test_must_fail git format-patch --base=HEAD~1 -2 &&
1966 git format-patch --stdout --base=HEAD~2 -2 >patch &&
1967 grep "^base-commit:" patch >actual &&
1968 git rev-parse HEAD~2 >commit-id-base &&
1969 echo "base-commit: $(cat commit-id-base)" >expect &&
1970 test_cmp expect actual
1973 test_expect_success
'format-patch --base errors out when base commit is not ancestor of revision list' '
1974 # For history as below:
1976 # ---Q---P---Z---Y---*---X
1980 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1981 git checkout -b topic1 master &&
1982 git rev-parse HEAD >commit-id-base &&
1984 git rev-parse HEAD >commit-id-P &&
1986 git rev-parse HEAD >commit-id-Z &&
1988 git checkout -b topic2 master &&
1992 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1993 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1994 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1995 grep "^base-commit:" patch >actual &&
1996 echo "base-commit: $(cat commit-id-base)" >expect &&
1997 test_cmp expect actual
2000 test_expect_success
'format-patch --base=auto' '
2001 git checkout -b upstream master &&
2002 git checkout -b local upstream &&
2003 git branch --set-upstream-to=upstream &&
2006 git format-patch --stdout --base=auto -2 >patch &&
2007 grep "^base-commit:" patch >actual &&
2008 git rev-parse upstream >commit-id-base &&
2009 echo "base-commit: $(cat commit-id-base)" >expect &&
2010 test_cmp expect actual
2013 test_expect_success
'format-patch errors out when history involves criss-cross' '
2014 # setup criss-cross history
2022 git checkout master &&
2024 git checkout -b xb master &&
2026 git checkout -b xc master &&
2028 git checkout -b xbc xb -- &&
2030 git checkout -b xcb xc -- &&
2031 git branch --set-upstream-to=xbc &&
2037 test_must_fail git format-patch --base=auto -1
2040 test_expect_success
'format-patch format.useAutoBase option' '
2041 git checkout local &&
2042 test_config format.useAutoBase true &&
2043 git format-patch --stdout -1 >patch &&
2044 grep "^base-commit:" patch >actual &&
2045 git rev-parse upstream >commit-id-base &&
2046 echo "base-commit: $(cat commit-id-base)" >expect &&
2047 test_cmp expect actual
2050 test_expect_success
'format-patch --base overrides format.useAutoBase' '
2051 test_config format.useAutoBase true &&
2052 git format-patch --stdout --base=HEAD~1 -1 >patch &&
2053 grep "^base-commit:" patch >actual &&
2054 git rev-parse HEAD~1 >commit-id-base &&
2055 echo "base-commit: $(cat commit-id-base)" >expect &&
2056 test_cmp expect actual
2059 test_expect_success
'format-patch --no-base overrides format.useAutoBase' '
2060 test_config format.useAutoBase true &&
2061 git format-patch --stdout --no-base -1 >patch &&
2062 ! grep "^base-commit:" patch
2065 test_expect_success
'format-patch --base with --attach' '
2066 git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
2067 sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
2069 test_write_lines 1 2 >expect &&
2070 test_cmp expect actual
2072 test_expect_success
'format-patch --attach cover-letter only is non-multipart' '
2073 test_when_finished "rm -fr patches" &&
2074 git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
2075 ! egrep "^--+mimemime" patches/0000*.patch &&
2076 egrep "^--+mimemime$" patches/0001*.patch >output &&
2077 test_line_count = 2 output &&
2078 egrep "^--+mimemime--$" patches/0001*.patch >output &&
2079 test_line_count = 1 output
2082 test_expect_success
'format-patch --pretty=mboxrd' '
2084 cat >msg <<-INPUT_END &&
2085 mboxrd should escape the body
2087 From could trip up a loose mbox parser
2088 >From extra escape for reversibility
2089 >>From extra escape for reversibility 2
2090 from lower case not escaped
2091 Fromm bad speling not escaped
2092 From with leading space not escaped
2101 cat >expect <<-INPUT_END &&
2102 >From could trip up a loose mbox parser
2103 >>From extra escape for reversibility
2104 >>>From extra escape for reversibility 2
2105 from lower case not escaped
2106 Fromm bad speling not escaped
2107 From with leading space not escaped
2116 C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
2117 git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
2118 git grep -h --no-index -A11 \
2119 "^>From could trip up a loose mbox parser" patch >actual &&
2120 test_cmp expect actual
2123 test_expect_success
'interdiff: setup' '
2124 git checkout -b boop master &&
2125 test_commit fnorp blorp &&
2126 test_commit fleep blorp
2129 test_expect_success
'interdiff: cover-letter' '
2130 sed "y/q/ /" >expect <<-\EOF &&
2134 git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
2135 test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch &&
2136 test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch &&
2137 sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual &&
2138 test_cmp expect actual
2141 test_expect_success
'interdiff: reroll-count' '
2142 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2143 test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2146 test_expect_success
'interdiff: solo-patch' '
2147 cat >expect <<-\EOF &&
2151 git format-patch --interdiff=boop~2 -1 boop &&
2152 test_i18ngrep "^Interdiff:$" 0001-fleep.patch &&
2153 sed "1,/^ @@ /d; /^$/q" 0001-fleep.patch >actual &&
2154 test_cmp expect actual