3 # Copyright (c) 2006 Junio C Hamano
6 test_description
='various format-patch tests'
8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
=main
9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
11 TEST_PASSES_SANITIZE_LEAK
=true
13 .
"$TEST_DIRECTORY"/lib-terminal.sh
15 test_expect_success setup
'
16 test_write_lines 1 2 3 4 5 6 7 8 9 10 >file &&
20 git commit -m Initial &&
21 git checkout -b side &&
23 test_write_lines 1 2 5 6 A B C 7 8 9 10 >file &&
26 git commit -m "Side changes #1" &&
28 test_write_lines D E F >>file &&
29 git update-index file &&
31 git commit -m "Side changes #2" &&
34 test_write_lines 5 6 1 2 3 A 4 B C 7 8 9 10 D E F >file &&
35 git update-index file &&
37 git commit -m "Side changes #3 with \\n backslash-n in it." &&
40 git diff-tree -p C2 >patch &&
41 git apply --index <patch &&
43 git commit -m "Main accepts moral equivalent of #2" &&
46 git checkout -b patchid &&
47 test_write_lines 5 6 1 2 3 A 4 B C 7 8 9 10 D E F >file2 &&
48 test_write_lines 1 2 3 A 4 B C 7 8 9 10 D E F 5 6 >file3 &&
49 test_write_lines 8 9 10 >file &&
50 git add file file2 file3 &&
52 git commit -m "patchid 1" &&
53 test_write_lines 4 A B 7 8 9 10 >file2 &&
54 test_write_lines 8 9 10 5 6 >file3 &&
55 git add file2 file3 &&
57 git commit -m "patchid 2" &&
58 test_write_lines 10 5 6 >file &&
61 git commit -m "patchid 3" &&
63 git checkout -b empty main &&
65 git commit --allow-empty -m "empty commit" &&
70 test_expect_success
'format-patch --ignore-if-in-upstream' '
71 git format-patch --stdout main..side >patch0 &&
72 grep "^From " patch0 >from0 &&
73 test_line_count = 3 from0
76 test_expect_success
'format-patch --ignore-if-in-upstream' '
77 git format-patch --stdout \
78 --ignore-if-in-upstream main..side >patch1 &&
79 grep "^From " patch1 >from1 &&
80 test_line_count = 2 from1
83 test_expect_success
'format-patch --ignore-if-in-upstream handles tags' '
84 git tag -a v1 -m tag side &&
85 git tag -a v2 -m tag main &&
86 git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
87 grep "^From " patch1 >from1 &&
88 test_line_count = 2 from1
91 test_expect_success
"format-patch doesn't consider merge commits" '
92 git checkout -b feature main &&
93 echo "Another line" >>file &&
95 git commit -am "Feature branch change #1" &&
96 echo "Yet another line" >>file &&
98 git commit -am "Feature branch change #2" &&
99 git checkout -b merger main &&
101 git merge --no-ff feature &&
102 git format-patch -3 --stdout >patch &&
103 grep "^From " patch >from &&
104 test_line_count = 3 from
107 test_expect_success
'format-patch result applies' '
108 git checkout -b rebuild-0 main &&
110 git rev-list main.. >list &&
111 test_line_count = 2 list
114 test_expect_success
'format-patch --ignore-if-in-upstream result applies' '
115 git checkout -b rebuild-1 main &&
117 git rev-list main.. >list &&
118 test_line_count = 2 list
121 test_expect_success
'commit did not screw up the log message' '
122 git cat-file commit side >actual &&
123 grep "^Side .* with .* backslash-n" actual
126 test_expect_success
'format-patch did not screw up the log message' '
127 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
128 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
131 test_expect_success
'replay did not screw up the log message' '
132 git cat-file commit rebuild-1 >actual &&
133 grep "^Side .* with .* backslash-n" actual
136 test_expect_success
'format-patch empty commit' '
137 git format-patch --stdout main..empty >empty &&
138 grep "^From " empty >from &&
139 test_line_count = 1 from
142 test_expect_success
'extra headers' '
143 git config format.headers "To: R E Cipient <rcipient@example.com>
145 git config --add format.headers "Cc: S E Cipient <scipient@example.com>
147 git format-patch --stdout main..side >patch2 &&
148 sed -e "/^\$/q" patch2 >hdrs2 &&
149 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
150 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
153 test_expect_success
'extra headers without newlines' '
154 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
155 git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
156 git format-patch --stdout main..side >patch3 &&
157 sed -e "/^\$/q" patch3 >hdrs3 &&
158 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
159 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
162 test_expect_success
'extra headers with multiple To:s' '
163 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
164 git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
165 git format-patch --stdout main..side >patch4 &&
166 sed -e "/^\$/q" patch4 >hdrs4 &&
167 grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
168 grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
171 test_expect_success
'additional command line cc (ascii)' '
172 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
173 git format-patch --cc="S E Cipient <scipient@example.com>" --stdout main..side >patch5 &&
174 sed -e "/^\$/q" patch5 >hdrs5 &&
175 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
176 grep "^ *S E Cipient <scipient@example.com>\$" hdrs5
179 test_expect_failure
'additional command line cc (rfc822)' '
180 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
181 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout main..side >patch5 &&
182 sed -e "/^\$/q" patch5 >hdrs5 &&
183 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
184 grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" hdrs5
187 test_expect_success
'command line headers' '
188 git config --unset-all format.headers &&
189 git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout main..side >patch6 &&
190 sed -e "/^\$/q" patch6 >hdrs6 &&
191 grep "^Cc: R E Cipient <rcipient@example.com>\$" hdrs6
194 test_expect_success
'configuration headers and command line headers' '
195 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
196 git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout main..side >patch7 &&
197 sed -e "/^\$/q" patch7 >hdrs7 &&
198 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs7 &&
199 grep "^ *S E Cipient <scipient@example.com>\$" hdrs7
202 test_expect_success
'command line To: header (ascii)' '
203 git config --unset-all format.headers &&
204 git format-patch --to="R E Cipient <rcipient@example.com>" --stdout main..side >patch8 &&
205 sed -e "/^\$/q" patch8 >hdrs8 &&
206 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs8
209 test_expect_failure
'command line To: header (rfc822)' '
210 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout main..side >patch8 &&
211 sed -e "/^\$/q" patch8 >hdrs8 &&
212 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs8
215 test_expect_failure
'command line To: header (rfc2047)' '
216 git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout main..side >patch8 &&
217 sed -e "/^\$/q" patch8 >hdrs8 &&
218 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs8
221 test_expect_success
'configuration To: header (ascii)' '
222 git config format.to "R E Cipient <rcipient@example.com>" &&
223 git format-patch --stdout main..side >patch9 &&
224 sed -e "/^\$/q" patch9 >hdrs9 &&
225 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs9
228 test_expect_failure
'configuration To: header (rfc822)' '
229 git config format.to "R. E. Cipient <rcipient@example.com>" &&
230 git format-patch --stdout main..side >patch9 &&
231 sed -e "/^\$/q" patch9 >hdrs9 &&
232 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs9
235 test_expect_failure
'configuration To: header (rfc2047)' '
236 git config format.to "R Ä Cipient <rcipient@example.com>" &&
237 git format-patch --stdout main..side >patch9 &&
238 sed -e "/^\$/q" patch9 >hdrs9 &&
239 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs9
242 # check_patch <patch>: Verify that <patch> looks like a half-sane
243 # patch email to avoid a false positive with !grep
245 grep -e "^From:" "$1" &&
246 grep -e "^Date:" "$1" &&
247 grep -e "^Subject:" "$1"
250 test_expect_success
'format.from=false' '
251 git -c format.from=false format-patch --stdout main..side >patch &&
252 sed -e "/^\$/q" patch >hdrs &&
254 ! grep "^From: C O Mitter <committer@example.com>\$" hdrs
257 test_expect_success
'format.from=true' '
258 git -c format.from=true format-patch --stdout main..side >patch &&
259 sed -e "/^\$/q" patch >hdrs &&
261 grep "^From: C O Mitter <committer@example.com>\$" hdrs
264 test_expect_success
'format.from with address' '
265 git -c format.from="F R Om <from@example.com>" format-patch --stdout main..side >patch &&
266 sed -e "/^\$/q" patch >hdrs &&
268 grep "^From: F R Om <from@example.com>\$" hdrs
271 test_expect_success
'--no-from overrides format.from' '
272 git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout main..side >patch &&
273 sed -e "/^\$/q" patch >hdrs &&
275 ! grep "^From: F R Om <from@example.com>\$" hdrs
278 test_expect_success
'--from overrides format.from' '
279 git -c format.from="F R Om <from@example.com>" format-patch --from --stdout main..side >patch &&
280 sed -e "/^\$/q" patch >hdrs &&
282 ! grep "^From: F R Om <from@example.com>\$" hdrs
285 test_expect_success
'--no-to overrides config.to' '
286 git config --replace-all format.to \
287 "R E Cipient <rcipient@example.com>" &&
288 git format-patch --no-to --stdout main..side >patch10 &&
289 sed -e "/^\$/q" patch10 >hdrs10 &&
290 check_patch hdrs10 &&
291 ! grep "^To: R E Cipient <rcipient@example.com>\$" hdrs10
294 test_expect_success
'--no-to and --to replaces config.to' '
295 git config --replace-all format.to \
296 "Someone <someone@out.there>" &&
297 git format-patch --no-to --to="Someone Else <else@out.there>" \
298 --stdout main..side >patch11 &&
299 sed -e "/^\$/q" patch11 >hdrs11 &&
300 check_patch hdrs11 &&
301 ! grep "^To: Someone <someone@out.there>\$" hdrs11 &&
302 grep "^To: Someone Else <else@out.there>\$" hdrs11
305 test_expect_success
'--no-cc overrides config.cc' '
306 git config --replace-all format.cc \
307 "C E Cipient <rcipient@example.com>" &&
308 git format-patch --no-cc --stdout main..side >patch12 &&
309 sed -e "/^\$/q" patch12 >hdrs12 &&
310 check_patch hdrs12 &&
311 ! grep "^Cc: C E Cipient <rcipient@example.com>\$" hdrs12
314 test_expect_success
'--no-add-header overrides config.headers' '
315 git config --replace-all format.headers \
316 "Header1: B E Cipient <rcipient@example.com>" &&
317 git format-patch --no-add-header --stdout main..side >patch13 &&
318 sed -e "/^\$/q" patch13 >hdrs13 &&
319 check_patch hdrs13 &&
320 ! grep "^Header1: B E Cipient <rcipient@example.com>\$" hdrs13
323 test_expect_success
'multiple files' '
326 git format-patch -o patches/ main &&
327 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
330 test_expect_success
'filename length limit' '
331 test_when_finished "rm -f 000*" &&
332 rm -rf 000[1-9]-*.patch &&
335 git format-patch --filename-max-length=$len -3 side &&
337 for patch in 000[1-9]-*.patch
339 echo "$patch" | wc -c || exit 1
344 test $max -le $len || return 1
348 test_expect_success
'filename length limit from config' '
349 test_when_finished "rm -f 000*" &&
350 rm -rf 000[1-9]-*.patch &&
353 git -c format.filenameMaxLength=$len format-patch -3 side &&
355 for patch in 000[1-9]-*.patch
357 echo "$patch" | wc -c || exit 1
362 test $max -le $len || return 1
366 test_expect_success
'filename limit applies only to basename' '
367 test_when_finished "rm -rf patches/" &&
371 git format-patch -o patches --filename-max-length=$len -3 side &&
373 for patch in patches/000[1-9]-*.patch
375 echo "${patch#patches/}" | wc -c || exit 1
380 test $max -le $len || return 1
384 test_expect_success
'reroll count' '
386 git format-patch -o patches --cover-letter --reroll-count 4 main..side >list &&
387 ! grep -v "^patches/v4-000[0-3]-" list &&
388 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
389 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
392 test_expect_success
'reroll count (-v)' '
394 git format-patch -o patches --cover-letter -v4 main..side >list &&
395 ! grep -v "^patches/v4-000[0-3]-" list &&
396 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
397 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
400 test_expect_success
'reroll count (-v) with a fractional number' '
402 git format-patch -o patches --cover-letter -v4.4 main..side >list &&
403 ! grep -v "^patches/v4.4-000[0-3]-" list &&
404 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
405 ! grep -v "^Subject: \[PATCH v4.4 [0-3]/3\] " subjects
408 test_expect_success
'reroll (-v) count with a non number' '
410 git format-patch -o patches --cover-letter -v4rev2 main..side >list &&
411 ! grep -v "^patches/v4rev2-000[0-3]-" list &&
412 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
413 ! grep -v "^Subject: \[PATCH v4rev2 [0-3]/3\] " subjects
416 test_expect_success
'reroll (-v) count with a non-pathname character' '
418 git format-patch -o patches --cover-letter -v4---..././../--1/.2// main..side >list &&
419 ! grep -v "patches/v4-\.-\.-\.-1-\.2-000[0-3]-" list &&
420 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
421 ! grep -v "^Subject: \[PATCH v4---\.\.\./\./\.\./--1/\.2// [0-3]/3\] " subjects
427 git format-patch
--stdout "$@" >patch &&
428 # Prints everything between the Message-ID and In-Reply-To,
429 # and replaces all Message-ID-lookalikes by a sequence number
431 if (/^(message-id|references|in-reply-to)/i) {
437 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
438 for $k (keys %h) {s/$k/$h{$k}/};
441 print "---\n" if /^From /i;
443 test_cmp
"$expect" actual
446 cat >>expect.no-threading
<<EOF
452 test_expect_success
'no threading' '
454 check_threading expect.no-threading main
457 cat >expect.thread
<<EOF
470 test_expect_success
'thread' '
471 check_threading expect.thread --thread main
474 test_expect_success
'--thread overrides format.thread=deep' '
475 test_config format.thread deep &&
476 check_threading expect.thread --thread main
479 cat >expect.in-reply-to
<<EOF
494 test_expect_success
'thread in-reply-to' '
495 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
499 cat >expect.cover-letter
<<EOF
516 test_expect_success
'thread cover-letter' '
517 check_threading expect.cover-letter --cover-letter --thread main
520 cat >expect.cl-irt
<<EOF
542 test_expect_success
'thread cover-letter in-reply-to' '
543 check_threading expect.cl-irt --cover-letter \
544 --in-reply-to="<test.message>" --thread main
547 test_expect_success
'thread explicit shallow' '
548 check_threading expect.cl-irt --cover-letter \
549 --in-reply-to="<test.message>" --thread=shallow main
552 cat >expect.deep
<<EOF
566 test_expect_success
'thread deep' '
567 check_threading expect.deep --thread=deep main
570 cat >expect.deep-irt
<<EOF
588 test_expect_success
'thread deep in-reply-to' '
589 check_threading expect.deep-irt --thread=deep \
590 --in-reply-to="<test.message>" main
593 cat >expect.deep-cl
<<EOF
613 test_expect_success
'thread deep cover-letter' '
614 check_threading expect.deep-cl --cover-letter --thread=deep main
617 cat >expect.deep-cl-irt
<<EOF
642 test_expect_success
'thread deep cover-letter in-reply-to' '
643 check_threading expect.deep-cl-irt --cover-letter \
644 --in-reply-to="<test.message>" --thread=deep main
647 test_expect_success
'thread via config' '
648 test_config format.thread true &&
649 check_threading expect.thread main
652 test_expect_success
'thread deep via config' '
653 test_config format.thread deep &&
654 check_threading expect.deep main
657 test_expect_success
'thread config + override' '
658 test_config format.thread deep &&
659 check_threading expect.thread --thread main
662 test_expect_success
'thread config + --no-thread' '
663 test_config format.thread deep &&
664 check_threading expect.no-threading --no-thread main
667 test_expect_success
'excessive subject' '
670 before=$(git hash-object file) &&
671 before=$(git rev-parse --short $before) &&
672 test_write_lines 5 6 1 2 3 A 4 B C 7 8 9 10 D E F >>file &&
673 after=$(git hash-object file) &&
674 after=$(git rev-parse --short $after) &&
675 git update-index file &&
676 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." &&
677 git format-patch -o patches/ main..side &&
678 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
681 test_expect_success
'failure to write cover-letter aborts gracefully' '
682 test_when_finished "rmdir 0000-cover-letter.patch" &&
683 mkdir 0000-cover-letter.patch &&
684 test_must_fail git format-patch --no-renames --cover-letter -1
687 test_expect_success
'cover-letter inherits diff options' '
690 git format-patch --no-renames --cover-letter -1 &&
691 check_patch 0000-cover-letter.patch &&
692 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
693 git format-patch --cover-letter -1 -M &&
694 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
698 This is an excessively long subject line for a message due to the
699 habit some projects have of not having a short, one-line subject at
700 the start of the commit message, but rather sticking a whole
701 paragraph right at the start as the only thing in the commit
702 message. It had better not become the filename for the patch.
707 test_expect_success
'shortlog of cover-letter wraps overly-long onelines' '
708 git format-patch --cover-letter -2 &&
709 sed -e "1,/A U Thor/d" -e "/^\$/q" 0000-cover-letter.patch >output &&
710 test_cmp expect output
714 index $before..$after 100644
725 test_expect_success
'format-patch respects -U' '
726 git format-patch -U4 -2 &&
727 sed -e "1,/^diff/d" -e "/^+5/q" \
728 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
730 test_cmp expect output
735 diff --git a/file b/file
736 index $before..$after 100644
746 test_expect_success
'format-patch -p suppresses stat' '
747 git format-patch -p -2 &&
748 sed -e "1,/^\$/d" -e "/^+5/q" 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&
749 test_cmp expect output
752 test_expect_success
'format-patch from a subdirectory (1)' '
763 echo "Oops? $filename"
770 test_expect_success
'format-patch from a subdirectory (2)' '
775 git format-patch -1 -o ..
781 echo "Oops? $filename"
785 basename=$(expr "$filename" : ".*/\(.*\)") &&
786 test -f "sub/$basename"
789 test_expect_success
'format-patch from a subdirectory (3)' '
795 git format-patch -1 -o "$TRASH_DIRECTORY"
797 basename=$(expr "$filename" : ".*/\(.*\)") &&
801 test_expect_success
'format-patch --in-reply-to' '
802 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" >patch8 &&
803 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
804 grep "^References: <baz@foo.bar>" patch8
807 test_expect_success
'format-patch --signoff' '
808 git format-patch -1 --signoff --stdout >out &&
809 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
812 test_expect_success
'format-patch --notes --signoff' '
813 git notes --ref test add -m "test message" HEAD &&
814 git format-patch -1 --signoff --stdout --notes=test >out &&
815 # Three dashes must come after S-o-b
816 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
817 sed "1,/^Signed-off-by: /d" out | grep "test message" &&
818 # Notes message must come after three dashes
819 ! sed "/^---$/q" out | grep "test message" &&
820 sed "1,/^---$/d" out | grep "test message"
823 test_expect_success
'format-patch notes output control' '
824 test_when_finished "git notes remove HEAD || :" &&
825 git notes add -m "notes config message" HEAD &&
827 git format-patch -1 --stdout >out &&
828 ! grep "notes config message" out &&
829 git format-patch -1 --stdout --notes >out &&
830 grep "notes config message" out &&
831 git format-patch -1 --stdout --no-notes >out &&
832 ! grep "notes config message" out &&
833 git format-patch -1 --stdout --notes --no-notes >out &&
834 ! grep "notes config message" out &&
835 git format-patch -1 --stdout --no-notes --notes >out &&
836 grep "notes config message" out &&
838 test_config format.notes true &&
839 git format-patch -1 --stdout >out &&
840 grep "notes config message" out &&
841 git format-patch -1 --stdout --notes >out &&
842 grep "notes config message" out &&
843 git format-patch -1 --stdout --no-notes >out &&
844 ! grep "notes config message" out &&
845 git format-patch -1 --stdout --notes --no-notes >out &&
846 ! grep "notes config message" out &&
847 git format-patch -1 --stdout --no-notes --notes >out &&
848 grep "notes config message" out
851 test_expect_success
'format-patch with multiple notes refs' '
852 test_when_finished "git notes --ref note1 remove HEAD;
853 git notes --ref note2 remove HEAD || :" &&
854 git notes --ref note1 add -m "this is note 1" HEAD &&
855 git notes --ref note2 add -m "this is note 2" HEAD &&
857 git format-patch -1 --stdout >out &&
858 ! grep "this is note 1" out &&
859 ! grep "this is note 2" out &&
860 git format-patch -1 --stdout --notes=note1 >out &&
861 grep "this is note 1" out &&
862 ! grep "this is note 2" out &&
863 git format-patch -1 --stdout --notes=note2 >out &&
864 ! grep "this is note 1" out &&
865 grep "this is note 2" out &&
866 git format-patch -1 --stdout --notes=note1 --notes=note2 >out &&
867 grep "this is note 1" out &&
868 grep "this is note 2" out &&
870 test_config format.notes note1 &&
871 git format-patch -1 --stdout >out &&
872 grep "this is note 1" out &&
873 ! grep "this is note 2" out &&
874 git format-patch -1 --stdout --no-notes >out &&
875 ! grep "this is note 1" out &&
876 ! grep "this is note 2" out &&
877 git format-patch -1 --stdout --notes=note2 >out &&
878 grep "this is note 1" out &&
879 grep "this is note 2" out &&
880 git format-patch -1 --stdout --no-notes --notes=note2 >out &&
881 ! grep "this is note 1" out &&
882 grep "this is note 2" out &&
884 git config --add format.notes note2 &&
885 git format-patch -1 --stdout >out &&
886 grep "this is note 1" out &&
887 grep "this is note 2" out &&
888 git format-patch -1 --stdout --no-notes >out &&
889 ! grep "this is note 1" out &&
890 ! grep "this is note 2" out
893 test_expect_success
'format-patch with multiple notes refs in config' '
894 test_when_finished "test_unconfig format.notes" &&
896 test_when_finished "git notes --ref note1 remove HEAD;
897 git notes --ref note2 remove HEAD || :" &&
898 git notes --ref note1 add -m "this is note 1" HEAD &&
899 git notes --ref note2 add -m "this is note 2" HEAD &&
901 git config format.notes note1 &&
902 git format-patch -1 --stdout >out &&
903 grep "this is note 1" out &&
904 ! grep "this is note 2" out &&
905 git config format.notes note2 &&
906 git format-patch -1 --stdout >out &&
907 ! grep "this is note 1" out &&
908 grep "this is note 2" out &&
909 git config --add format.notes note1 &&
910 git format-patch -1 --stdout >out &&
911 grep "this is note 1" out &&
912 grep "this is note 2" out &&
914 git config --replace-all format.notes note1 &&
915 git config --add format.notes false &&
916 git format-patch -1 --stdout >out &&
917 ! grep "this is note 1" out &&
918 ! grep "this is note 2" out &&
919 git config --add format.notes note2 &&
920 git format-patch -1 --stdout >out &&
921 ! grep "this is note 1" out &&
922 grep "this is note 2" out
925 echo "fatal: --name-only does not make sense" >expect.name-only
926 echo "fatal: --name-status does not make sense" >expect.name-status
927 echo "fatal: --check does not make sense" >expect.check
929 test_expect_success
'options no longer allowed for format-patch' '
930 test_must_fail git format-patch --name-only 2>output &&
931 test_cmp expect.name-only output &&
932 test_must_fail git format-patch --name-status 2>output &&
933 test_cmp expect.name-status output &&
934 test_must_fail git format-patch --check 2>output &&
935 test_cmp expect.check output
938 test_expect_success
'format-patch --numstat should produce a patch' '
939 git format-patch --numstat --stdout main..side >output &&
940 grep "^diff --git a/" output >diff &&
941 test_line_count = 5 diff
944 test_expect_success
'format-patch -- <path>' '
946 git checkout -b pathspec main &&
948 echo file_a 1 >file_a &&
949 echo file_b 1 >file_b &&
950 git add file_a file_b &&
951 git commit -m pathspec_initial &&
953 echo file_a 2 >>file_a &&
955 git commit -m pathspec_a &&
957 echo file_b 2 >>file_b &&
959 git commit -m pathspec_b &&
961 echo file_a 3 >>file_a &&
962 echo file_b 3 >>file_b &&
963 git add file_a file_b &&
964 git commit -m pathspec_ab &&
966 cat >expect <<-\EOF &&
967 0001-pathspec_initial.patch
968 0002-pathspec_a.patch
969 0003-pathspec_ab.patch
972 git format-patch main..pathspec -- file_a >output &&
973 test_cmp expect output &&
974 ! grep file_b *.patch
977 test_expect_success
'format-patch --ignore-if-in-upstream HEAD' '
979 git format-patch --ignore-if-in-upstream HEAD
982 test_expect_success
'get git version' '
983 git_version=$(git --version) &&
984 git_version=${git_version##* }
988 printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
991 test_expect_success
'format-patch default signature' '
992 git format-patch --stdout -1 >patch &&
993 tail -n 3 patch >output &&
995 test_cmp expect output
998 test_expect_success
'format-patch --signature' '
999 git format-patch --stdout --signature="my sig" -1 >patch &&
1000 tail -n 3 patch >output &&
1001 signature "my sig" >expect &&
1002 test_cmp expect output
1005 test_expect_success
'format-patch with format.signature config' '
1006 git config format.signature "config sig" &&
1007 git format-patch --stdout -1 >output &&
1008 grep "config sig" output
1011 test_expect_success
'format-patch --signature overrides format.signature' '
1012 git config format.signature "config sig" &&
1013 git format-patch --stdout --signature="overrides" -1 >output &&
1014 ! grep "config sig" output &&
1015 grep "overrides" output
1018 test_expect_success
'format-patch --no-signature ignores format.signature' '
1019 git config format.signature "config sig" &&
1020 git format-patch --stdout --signature="my sig" --no-signature \
1022 check_patch output &&
1023 ! grep "config sig" output &&
1024 ! grep "my sig" output &&
1025 ! grep "^-- \$" output
1028 test_expect_success
'format-patch --signature --cover-letter' '
1029 git config --unset-all format.signature &&
1030 git format-patch --stdout --signature="my sig" --cover-letter \
1032 grep "my sig" output >sig &&
1033 test_line_count = 2 sig
1036 test_expect_success
'format.signature="" suppresses signatures' '
1037 git config format.signature "" &&
1038 git format-patch --stdout -1 >output &&
1039 check_patch output &&
1040 ! grep "^-- \$" output
1043 test_expect_success
'format-patch --no-signature suppresses signatures' '
1044 git config --unset-all format.signature &&
1045 git format-patch --stdout --no-signature -1 >output &&
1046 check_patch output &&
1047 ! grep "^-- \$" output
1050 test_expect_success
'format-patch --signature="" suppresses signatures' '
1051 git format-patch --stdout --signature="" -1 >output &&
1052 check_patch output &&
1053 ! grep "^-- \$" output
1056 test_expect_success
'prepare mail-signature input' '
1057 cat >mail-signature <<-\EOF
1059 Test User <test.email@kernel.org>
1060 http://git.kernel.org/cgit/git/git.git
1062 git.kernel.org/?p=git/git.git;a=summary
1067 test_expect_success
'--signature-file=file works' '
1068 git format-patch --stdout --signature-file=mail-signature -1 >output &&
1069 check_patch output &&
1070 sed -e "1,/^-- \$/d" output >actual &&
1072 cat mail-signature && echo
1074 test_cmp expect actual
1077 test_expect_success
'format.signaturefile works' '
1078 test_config format.signaturefile mail-signature &&
1079 git format-patch --stdout -1 >output &&
1080 check_patch output &&
1081 sed -e "1,/^-- \$/d" output >actual &&
1083 cat mail-signature && echo
1085 test_cmp expect actual
1088 test_expect_success
'--no-signature suppresses format.signaturefile ' '
1089 test_config format.signaturefile mail-signature &&
1090 git format-patch --stdout --no-signature -1 >output &&
1091 check_patch output &&
1092 ! grep "^-- \$" output
1095 test_expect_success
'--signature-file overrides format.signaturefile' '
1096 cat >other-mail-signature <<-\EOF &&
1097 Use this other signature instead of mail-signature.
1099 test_config format.signaturefile mail-signature &&
1100 git format-patch --stdout \
1101 --signature-file=other-mail-signature -1 >output &&
1102 check_patch output &&
1103 sed -e "1,/^-- \$/d" output >actual &&
1105 cat other-mail-signature && echo
1107 test_cmp expect actual
1110 test_expect_success
'--signature overrides format.signaturefile' '
1111 test_config format.signaturefile mail-signature &&
1112 git format-patch --stdout --signature="my sig" -1 >output &&
1113 check_patch output &&
1114 grep "my sig" output
1117 test_expect_success TTY
'format-patch --stdout paginates' '
1119 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
1120 test_path_is_file pager_used
1123 test_expect_success TTY
'format-patch --stdout pagination can be disabled' '
1125 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
1126 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
1127 test_path_is_missing pager_used &&
1128 test_path_is_missing .git/pager_used
1131 test_expect_success
'format-patch handles multi-line subjects' '
1133 echo content >>file &&
1134 test_write_lines one two three >msg &&
1136 git commit -F msg &&
1137 git format-patch -o patches -1 &&
1138 grep ^Subject: patches/0001-one.patch >actual &&
1139 echo "Subject: [PATCH] one two three" >expect &&
1140 test_cmp expect actual
1143 test_expect_success
'format-patch handles multi-line encoded subjects' '
1145 echo content >>file &&
1146 test_write_lines en två tre >msg &&
1148 git commit -F msg &&
1149 git format-patch -o patches -1 &&
1150 grep ^Subject: patches/0001-en.patch >actual &&
1151 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
1152 test_cmp expect actual
1156 M64
=$M8$M8$M8$M8$M8$M8$M8$M8
1157 M512
=$M64$M64$M64$M64$M64$M64$M64$M64
1159 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1160 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1161 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1162 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1163 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1164 bar foo 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
1167 test_expect_success
'format-patch wraps extremely long subject (ascii)' '
1168 echo content >>file &&
1170 git commit -m "$M512" &&
1171 git format-patch --stdout -1 >patch &&
1172 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1173 test_cmp expect subject
1177 M64
=$M8$M8$M8$M8$M8$M8$M8$M8
1178 M512
=$M64$M64$M64$M64$M64$M64$M64$M64
1180 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1181 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1182 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1183 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1184 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1185 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1186 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1187 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1188 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1189 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1190 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1191 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1192 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1193 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1194 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1195 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1196 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1197 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1198 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1199 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1200 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1201 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1202 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1205 test_expect_success
'format-patch wraps extremely long subject (rfc2047)' '
1207 echo content >>file &&
1209 git commit -m "$M512" &&
1210 git format-patch --stdout -1 >patch &&
1211 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1212 test_cmp expect subject
1216 echo content
>>file &&
1218 GIT_AUTHOR_NAME
=$1 git commit
-m author-check
&&
1219 git format-patch
--stdout -1 >patch &&
1220 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual
&&
1221 test_cmp expect actual
1225 From: "Foo B. Bar" <author@example.com>
1227 test_expect_success
'format-patch quotes dot in from-headers' '
1228 check_author "Foo B. Bar"
1232 From: "Foo \"The Baz\" Bar" <author@example.com>
1234 test_expect_success
'format-patch quotes double-quote in from-headers' '
1235 check_author "Foo \"The Baz\" Bar"
1239 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1241 test_expect_success
'format-patch uses rfc2047-encoded from-headers when necessary' '
1242 check_author "Föo Bar"
1246 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1248 test_expect_success
'rfc2047-encoded from-headers leave no rfc822 specials' '
1249 check_author "Föo B. Bar"
1253 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1254 <author@example.com>
1256 test_expect_success
'format-patch wraps moderately long from-header (ascii)' '
1257 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1261 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1262 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1263 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1265 test_expect_success
'format-patch wraps extremely long from-header (ascii)' '
1266 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"
1270 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1271 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1272 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1274 test_expect_success
'format-patch wraps extremely long from-header (rfc822)' '
1275 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"
1279 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1280 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1281 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1282 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1283 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1285 test_expect_success
'format-patch wraps extremely long from-header (rfc2047)' '
1286 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"
1290 From: Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1291 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1292 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1294 test_expect_success
'format-patch wraps extremely long from-header (non-ASCII without Q-encoding)' '
1295 echo content >>file &&
1297 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" \
1298 git commit -m author-check &&
1299 git format-patch --no-encode-email-headers --stdout -1 >patch &&
1300 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1301 test_cmp expect actual
1305 Subject: [PATCH] Foö
1307 test_expect_success
'subject lines are unencoded with --no-encode-email-headers' '
1308 echo content >>file &&
1310 git commit -m "Foö" &&
1311 git format-patch --no-encode-email-headers -1 --stdout >patch &&
1312 grep ^Subject: patch >actual &&
1313 test_cmp expect actual
1317 Subject: [PATCH] Foö
1319 test_expect_success
'subject lines are unencoded with format.encodeEmailHeaders=false' '
1320 echo content >>file &&
1322 git commit -m "Foö" &&
1323 git config format.encodeEmailHeaders false &&
1324 git format-patch -1 --stdout >patch &&
1325 grep ^Subject: patch >actual &&
1326 test_cmp expect actual
1330 Subject: [PATCH] =?UTF-8?q?Fo=C3=B6?=
1332 test_expect_success
'--encode-email-headers overrides format.encodeEmailHeaders' '
1333 echo content >>file &&
1335 git commit -m "Foö" &&
1336 git config format.encodeEmailHeaders false &&
1337 git format-patch --encode-email-headers -1 --stdout >patch &&
1338 grep ^Subject: patch >actual &&
1339 test_cmp expect actual
1343 Subject: header with . in it
1345 test_expect_success
'subject lines do not have 822 atom-quoting' '
1346 echo content >>file &&
1348 git commit -m "header with . in it" &&
1349 git format-patch -k -1 --stdout >patch &&
1350 grep ^Subject: patch >actual &&
1351 test_cmp expect actual
1355 Subject: [PREFIX 1/1] header with . in it
1357 test_expect_success
'subject prefixes have space prepended' '
1358 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1359 grep ^Subject: patch >actual &&
1360 test_cmp expect actual
1364 Subject: [1/1] header with . in it
1366 test_expect_success
'empty subject prefix does not have extra space' '
1367 git format-patch -n -1 --stdout --subject-prefix= >patch &&
1368 grep ^Subject: patch >actual &&
1369 test_cmp expect actual
1372 test_expect_success
'--rfc and --no-rfc' '
1373 cat >expect <<-\EOF &&
1374 Subject: [RFC PATCH 1/1] header with . in it
1376 git format-patch -n -1 --stdout --rfc >patch &&
1377 grep "^Subject:" patch >actual &&
1378 test_cmp expect actual &&
1379 git format-patch -n -1 --stdout --rfc --no-rfc >patch &&
1380 sed -e "s/RFC //" expect >expect-raw &&
1381 grep "^Subject:" patch >actual &&
1382 test_cmp expect-raw actual
1385 test_expect_success
'--rfc=WIP and --rfc=' '
1386 cat >expect <<-\EOF &&
1387 Subject: [WIP PATCH 1/1] header with . in it
1389 git format-patch -n -1 --stdout --rfc=WIP >patch &&
1390 grep "^Subject:" patch >actual &&
1391 test_cmp expect actual &&
1392 git format-patch -n -1 --stdout --rfc --rfc= >patch &&
1393 sed -e "s/WIP //" expect >expect-raw &&
1394 grep "^Subject:" patch >actual &&
1395 test_cmp expect-raw actual
1398 test_expect_success
'--rfc=-(WIP) appends' '
1399 cat >expect <<-\EOF &&
1400 Subject: [PATCH (WIP) 1/1] header with . in it
1402 git format-patch -n -1 --stdout --rfc="-(WIP)" >patch &&
1403 grep "^Subject:" patch >actual &&
1404 test_cmp expect actual
1407 test_expect_success
'--rfc does not overwrite prefix' '
1408 cat >expect <<-\EOF &&
1409 Subject: [RFC PATCH foobar 1/1] header with . in it
1411 git -c format.subjectPrefix="PATCH foobar" \
1412 format-patch -n -1 --stdout --rfc >patch &&
1413 grep "^Subject:" patch >actual &&
1414 test_cmp expect actual
1417 test_expect_success
'--rfc is argument order independent' '
1418 cat >expect <<-\EOF &&
1419 Subject: [RFC PATCH foobar 1/1] header with . in it
1421 git format-patch -n -1 --stdout --rfc \
1422 --subject-prefix="PATCH foobar" >patch &&
1423 grep "^Subject:" patch >actual &&
1424 test_cmp expect actual
1427 test_expect_success
'--subject-prefix="<non-empty>" and -k cannot be used together' '
1428 echo "fatal: options '\''--subject-prefix/--rfc'\'' and '\''-k'\'' cannot be used together" >expect.err &&
1429 test_must_fail git format-patch -1 --stdout --subject-prefix="MYPREFIX" -k >actual.out 2>actual.err &&
1430 test_must_be_empty actual.out &&
1431 test_cmp expect.err actual.err
1434 test_expect_success
'--subject-prefix="" and -k cannot be used together' '
1435 echo "fatal: options '\''--subject-prefix/--rfc'\'' and '\''-k'\'' cannot be used together" >expect.err &&
1436 test_must_fail git format-patch -1 --stdout --subject-prefix="" -k >actual.out 2>actual.err &&
1437 test_must_be_empty actual.out &&
1438 test_cmp expect.err actual.err
1441 test_expect_success
'--rfc and -k cannot be used together' '
1442 echo "fatal: options '\''--subject-prefix/--rfc'\'' and '\''-k'\'' cannot be used together" >expect.err &&
1443 test_must_fail git format-patch -1 --stdout --rfc -k >actual.out 2>actual.err &&
1444 test_must_be_empty actual.out &&
1445 test_cmp expect.err actual.err
1448 test_expect_success
'--from=ident notices bogus ident' '
1449 test_must_fail git format-patch -1 --stdout --from=foo >patch
1452 test_expect_success
'--from=ident replaces author' '
1453 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1454 cat >expect <<-\EOF &&
1455 From: Me <me@example.com>
1457 From: A U Thor <author@example.com>
1460 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1461 test_cmp expect patch.head
1464 test_expect_success
'--from uses committer ident' '
1465 git format-patch -1 --stdout --from >patch &&
1466 cat >expect <<-\EOF &&
1467 From: C O Mitter <committer@example.com>
1469 From: A U Thor <author@example.com>
1472 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1473 test_cmp expect patch.head
1476 test_expect_success
'--from omits redundant in-body header' '
1477 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1478 cat >expect <<-\EOF &&
1479 From: A U Thor <author@example.com>
1482 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1483 test_cmp expect patch.head
1486 test_expect_success
'with --force-in-body-from, redundant in-body from is kept' '
1487 git format-patch --force-in-body-from \
1488 -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1489 cat >expect <<-\EOF &&
1490 From: A U Thor <author@example.com>
1492 From: A U Thor <author@example.com>
1495 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1496 test_cmp expect patch.head
1499 test_expect_success
'format.forceInBodyFrom, equivalent to --force-in-body-from' '
1500 git -c format.forceInBodyFrom=yes format-patch \
1501 -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1502 cat >expect <<-\EOF &&
1503 From: A U Thor <author@example.com>
1505 From: A U Thor <author@example.com>
1508 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1509 test_cmp expect patch.head
1512 test_expect_success
'format.forceInBodyFrom, equivalent to --force-in-body-from' '
1513 git -c format.forceInBodyFrom=yes format-patch --no-force-in-body-from \
1514 -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1515 cat >expect <<-\EOF &&
1516 From: A U Thor <author@example.com>
1519 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1520 test_cmp expect patch.head
1523 test_expect_success
'in-body headers trigger content encoding' '
1524 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1525 test_when_finished "git reset --hard HEAD^" &&
1526 git format-patch -1 --stdout --from >patch &&
1527 cat >expect <<-\EOF &&
1528 From: C O Mitter <committer@example.com>
1529 Content-Type: text/plain; charset=UTF-8
1531 From: éxötìc <author@example.com>
1534 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" patch >patch.head &&
1535 test_cmp expect patch.head
1540 C
=$
(git commit-tree HEAD^^
{tree
} -p HEAD
) &&
1541 git format-patch
--stdout --signoff $C^..
$C >append_signoff.
patch &&
1542 sed -n -e "1,/^---$/p" append_signoff.
patch |
1543 grep -E -n "^Subject|Sign|^$"
1546 test_expect_success
'signoff: commit with no body' '
1547 append_signoff </dev/null >actual &&
1548 cat <<-\EOF | sed "s/EOL$//" >expect &&
1549 4:Subject: [PATCH] EOL
1551 9:Signed-off-by: C O Mitter <committer@example.com>
1553 test_cmp expect actual
1556 test_expect_success
'signoff: commit with only subject' '
1557 echo subject | append_signoff >actual &&
1558 cat >expect <<-\EOF &&
1559 4:Subject: [PATCH] subject
1561 9:Signed-off-by: C O Mitter <committer@example.com>
1563 test_cmp expect actual
1566 test_expect_success
'signoff: commit with only subject that does not end with NL' '
1567 printf subject | append_signoff >actual &&
1568 cat >expect <<-\EOF &&
1569 4:Subject: [PATCH] subject
1571 9:Signed-off-by: C O Mitter <committer@example.com>
1573 test_cmp expect actual
1576 test_expect_success
'signoff: no existing signoffs' '
1577 append_signoff <<-\EOF >actual &&
1582 cat >expect <<-\EOF &&
1583 4:Subject: [PATCH] subject
1586 11:Signed-off-by: C O Mitter <committer@example.com>
1588 test_cmp expect actual
1591 test_expect_success
'signoff: no existing signoffs and no trailing NL' '
1592 printf "subject\n\nbody" | append_signoff >actual &&
1593 cat >expect <<-\EOF &&
1594 4:Subject: [PATCH] subject
1597 11:Signed-off-by: C O Mitter <committer@example.com>
1599 test_cmp expect actual
1602 test_expect_success
'signoff: some random signoff' '
1603 append_signoff <<-\EOF >actual &&
1608 Signed-off-by: my@house
1610 cat >expect <<-\EOF &&
1611 4:Subject: [PATCH] subject
1614 11:Signed-off-by: my@house
1615 12:Signed-off-by: C O Mitter <committer@example.com>
1617 test_cmp expect actual
1620 test_expect_success
'signoff: misc conforming footer elements' '
1621 append_signoff <<-\EOF >actual &&
1626 Signed-off-by: my@house
1627 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1628 Tested-by: Some One <someone@example.com>
1631 cat >expect <<-\EOF &&
1632 4:Subject: [PATCH] subject
1635 11:Signed-off-by: my@house
1636 15:Signed-off-by: C O Mitter <committer@example.com>
1638 test_cmp expect actual
1641 test_expect_success
'signoff: some random signoff-alike' '
1642 append_signoff <<-\EOF >actual &&
1646 Fooled-by-me: my@house
1648 cat >expect <<-\EOF &&
1649 4:Subject: [PATCH] subject
1652 12:Signed-off-by: C O Mitter <committer@example.com>
1654 test_cmp expect actual
1657 test_expect_success
'signoff: not really a signoff' '
1658 append_signoff <<-\EOF >actual &&
1661 I want to mention about Signed-off-by: here.
1663 cat >expect <<-\EOF &&
1664 4:Subject: [PATCH] subject
1666 9:I want to mention about Signed-off-by: here.
1668 11:Signed-off-by: C O Mitter <committer@example.com>
1670 test_cmp expect actual
1673 test_expect_success
'signoff: not really a signoff (2)' '
1674 append_signoff <<-\EOF >actual &&
1678 Signed-off-by: example happens to be wrapped here.
1680 cat >expect <<-\EOF &&
1681 4:Subject: [PATCH] subject
1683 10:Signed-off-by: example happens to be wrapped here.
1684 11:Signed-off-by: C O Mitter <committer@example.com>
1686 test_cmp expect actual
1689 test_expect_success
'signoff: valid S-o-b paragraph in the middle' '
1690 append_signoff <<-\EOF >actual &&
1693 Signed-off-by: my@house
1694 Signed-off-by: your@house
1698 cat >expect <<-\EOF &&
1699 4:Subject: [PATCH] subject
1701 9:Signed-off-by: my@house
1702 10:Signed-off-by: your@house
1705 14:Signed-off-by: C O Mitter <committer@example.com>
1707 test_cmp expect actual
1710 test_expect_success
'signoff: the same signoff at the end' '
1711 append_signoff <<-\EOF >actual &&
1716 Signed-off-by: C O Mitter <committer@example.com>
1718 cat >expect <<-\EOF &&
1719 4:Subject: [PATCH] subject
1722 11:Signed-off-by: C O Mitter <committer@example.com>
1724 test_cmp expect actual
1727 test_expect_success
'signoff: the same signoff at the end, no trailing NL' '
1728 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1729 append_signoff >actual &&
1730 cat >expect <<-\EOF &&
1731 4:Subject: [PATCH] subject
1733 9:Signed-off-by: C O Mitter <committer@example.com>
1735 test_cmp expect actual
1738 test_expect_success
'signoff: the same signoff NOT at the end' '
1739 append_signoff <<-\EOF >actual &&
1744 Signed-off-by: C O Mitter <committer@example.com>
1745 Signed-off-by: my@house
1747 cat >expect <<-\EOF &&
1748 4:Subject: [PATCH] subject
1751 11:Signed-off-by: C O Mitter <committer@example.com>
1752 12:Signed-off-by: my@house
1754 test_cmp expect actual
1757 test_expect_success
'signoff: tolerate garbage in conforming footer' '
1758 append_signoff <<-\EOF >actual &&
1765 Signed-off-by: C O Mitter <committer@example.com>
1767 cat >expect <<-\EOF &&
1768 4:Subject: [PATCH] subject
1771 13:Signed-off-by: C O Mitter <committer@example.com>
1773 test_cmp expect actual
1776 test_expect_success
'signoff: respect trailer config' '
1777 append_signoff <<-\EOF >actual &&
1783 cat >expect <<-\EOF &&
1784 4:Subject: [PATCH] subject
1787 12:Signed-off-by: C O Mitter <committer@example.com>
1789 test_cmp expect actual &&
1791 test_config trailer.Myfooter.ifexists add &&
1792 append_signoff <<-\EOF >actual &&
1798 cat >expect <<-\EOF &&
1799 4:Subject: [PATCH] subject
1801 11:Signed-off-by: C O Mitter <committer@example.com>
1803 test_cmp expect actual
1806 test_expect_success
'signoff: footer begins with non-signoff without @ sign' '
1807 append_signoff <<-\EOF >actual &&
1814 Change-id: Ideadbeef
1815 Signed-off-by: C O Mitter <committer@example.com>
1818 cat >expect <<-\EOF &&
1819 4:Subject: [PATCH] subject
1822 14:Signed-off-by: C O Mitter <committer@example.com>
1824 test_cmp expect actual
1827 test_expect_success
'format patch ignores color.ui' '
1828 test_unconfig color.ui &&
1829 git format-patch --stdout -1 >expect &&
1830 test_config color.ui always &&
1831 git format-patch --stdout -1 >actual &&
1832 test_cmp expect actual
1835 test_expect_success
'format patch respects diff.relative' '
1838 echo other content >subdir/file2 &&
1839 git add subdir/file2 &&
1840 git commit -F msg &&
1841 test_unconfig diff.relative &&
1842 git format-patch --relative=subdir --stdout -1 >expect &&
1843 test_config diff.relative true &&
1844 git -C subdir format-patch --stdout -1 >actual &&
1845 test_cmp expect actual
1848 test_expect_success
'cover letter with invalid --cover-from-description and config' '
1849 test_config branch.rebuild-1.description "config subject
1852 test_must_fail git format-patch --cover-letter --cover-from-description garbage main &&
1853 test_config format.coverFromDescription garbage &&
1854 test_must_fail git format-patch --cover-letter main
1857 test_expect_success
'cover letter with format.coverFromDescription = default' '
1858 test_config branch.rebuild-1.description "config subject
1861 test_config format.coverFromDescription default &&
1862 git checkout rebuild-1 &&
1863 git format-patch --stdout --cover-letter main >actual &&
1864 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1865 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1866 grep "^config subject$" actual &&
1867 grep "^body$" actual
1870 test_expect_success
'cover letter with --cover-from-description default' '
1871 test_config branch.rebuild-1.description "config subject
1874 git checkout rebuild-1 &&
1875 git format-patch --stdout --cover-letter --cover-from-description default main >actual &&
1876 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1877 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1878 grep "^config subject$" actual &&
1879 grep "^body$" actual
1882 test_expect_success
'cover letter with format.coverFromDescription = none' '
1883 test_config branch.rebuild-1.description "config subject
1886 test_config format.coverFromDescription none &&
1887 git checkout rebuild-1 &&
1888 git format-patch --stdout --cover-letter main >actual &&
1889 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1890 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1891 ! grep "^config subject$" actual &&
1892 ! grep "^body$" actual
1895 test_expect_success
'cover letter with --cover-from-description none' '
1896 test_config branch.rebuild-1.description "config subject
1899 git checkout rebuild-1 &&
1900 git format-patch --stdout --cover-letter --cover-from-description none main >actual &&
1901 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1902 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1903 ! grep "^config subject$" actual &&
1904 ! grep "^body$" actual
1907 test_expect_success
'cover letter with format.coverFromDescription = message' '
1908 test_config branch.rebuild-1.description "config subject
1911 test_config format.coverFromDescription message &&
1912 git checkout rebuild-1 &&
1913 git format-patch --stdout --cover-letter main >actual &&
1914 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1915 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1916 grep "^config subject$" actual &&
1917 grep "^body$" actual
1920 test_expect_success
'cover letter with --cover-from-description message' '
1921 test_config branch.rebuild-1.description "config subject
1924 git checkout rebuild-1 &&
1925 git format-patch --stdout --cover-letter --cover-from-description message main >actual &&
1926 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1927 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1928 grep "^config subject$" actual &&
1929 grep "^body$" actual
1932 test_expect_success
'cover letter with format.coverFromDescription = subject' '
1933 test_config branch.rebuild-1.description "config subject
1936 test_config format.coverFromDescription subject &&
1937 git checkout rebuild-1 &&
1938 git format-patch --stdout --cover-letter main >actual &&
1939 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1940 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1941 ! grep "^config subject$" actual &&
1942 grep "^body$" actual
1945 test_expect_success
'cover letter with --cover-from-description subject' '
1946 test_config branch.rebuild-1.description "config subject
1949 git checkout rebuild-1 &&
1950 git format-patch --stdout --cover-letter --cover-from-description subject main >actual &&
1951 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1952 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1953 ! grep "^config subject$" actual &&
1954 grep "^body$" actual
1957 test_expect_success
'cover letter with --cover-from-description subject (UTF-8 subject line)' '
1958 test_config branch.rebuild-1.description "Café?
1961 git checkout rebuild-1 &&
1962 git format-patch --stdout --cover-letter --cover-from-description subject --encode-email-headers main >actual &&
1963 grep "^Subject: \[PATCH 0/2\] =?UTF-8?q?Caf=C3=A9=3F?=$" actual &&
1964 ! grep "Café" actual
1967 test_expect_success
'cover letter with format.coverFromDescription = auto (short subject line)' '
1968 test_config branch.rebuild-1.description "config subject
1971 test_config format.coverFromDescription auto &&
1972 git checkout rebuild-1 &&
1973 git format-patch --stdout --cover-letter main >actual &&
1974 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1975 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1976 ! grep "^config subject$" actual &&
1977 grep "^body$" actual
1980 test_expect_success
'cover letter with --cover-from-description auto (short subject line)' '
1981 test_config branch.rebuild-1.description "config subject
1984 git checkout rebuild-1 &&
1985 git format-patch --stdout --cover-letter --cover-from-description auto main >actual &&
1986 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1987 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1988 ! grep "^config subject$" actual &&
1989 grep "^body$" actual
1992 test_expect_success
'cover letter with format.coverFromDescription = auto (long subject line)' '
1993 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
1996 test_config format.coverFromDescription auto &&
1997 git checkout rebuild-1 &&
1998 git format-patch --stdout --cover-letter main >actual &&
1999 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
2000 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
2001 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
2002 grep "^body$" actual
2005 test_expect_success
'cover letter with --cover-from-description auto (long subject line)' '
2006 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
2009 git checkout rebuild-1 &&
2010 git format-patch --stdout --cover-letter --cover-from-description auto main >actual &&
2011 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
2012 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
2013 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
2014 grep "^body$" actual
2017 test_expect_success
'cover letter with command-line --cover-from-description overrides config' '
2018 test_config branch.rebuild-1.description "config subject
2021 test_config format.coverFromDescription none &&
2022 git checkout rebuild-1 &&
2023 git format-patch --stdout --cover-letter --cover-from-description subject main >actual &&
2024 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
2025 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
2026 ! grep "^config subject$" actual &&
2027 grep "^body$" actual
2030 test_expect_success
'cover letter using branch description (1)' '
2031 git checkout rebuild-1 &&
2032 test_config branch.rebuild-1.description hello &&
2033 git format-patch --stdout --cover-letter main >actual &&
2037 test_expect_success
'cover letter using branch description (2)' '
2038 git checkout rebuild-1 &&
2039 test_config branch.rebuild-1.description hello &&
2040 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
2044 test_expect_success
'cover letter using branch description (3)' '
2045 git checkout rebuild-1 &&
2046 test_config branch.rebuild-1.description hello &&
2047 git format-patch --stdout --cover-letter ^main rebuild-1 >actual &&
2051 test_expect_success
'cover letter using branch description (4)' '
2052 git checkout rebuild-1 &&
2053 test_config branch.rebuild-1.description hello &&
2054 git format-patch --stdout --cover-letter main.. >actual &&
2058 test_expect_success
'cover letter using branch description (5)' '
2059 git checkout rebuild-1 &&
2060 test_config branch.rebuild-1.description hello &&
2061 git format-patch --stdout --cover-letter -2 HEAD >actual &&
2065 test_expect_success
'cover letter using branch description (6)' '
2066 git checkout rebuild-1 &&
2067 test_config branch.rebuild-1.description hello &&
2068 git format-patch --stdout --cover-letter -2 >actual &&
2072 test_expect_success
'cover letter with --description-file' '
2073 test_when_finished "rm -f description.txt" &&
2074 cat >description.txt <<-\EOF &&
2079 git checkout rebuild-1 &&
2080 git format-patch --stdout --cover-letter --cover-from-description auto \
2081 --description-file description.txt main >actual &&
2082 grep "^Subject: \[PATCH 0/2\] subject from file$" actual &&
2083 grep "^body from file$" actual
2086 test_expect_success
'cover letter with nothing' '
2087 git format-patch --stdout --cover-letter >actual &&
2088 test_line_count = 0 actual
2091 test_expect_success
'cover letter auto' '
2093 test_when_finished "rm -rf tmp;
2094 git config --unset format.coverletter" &&
2096 git config format.coverletter auto &&
2097 git format-patch -o tmp -1 >list &&
2098 test_line_count = 1 list &&
2099 git format-patch -o tmp -2 >list &&
2100 test_line_count = 3 list
2103 test_expect_success
'cover letter auto user override' '
2105 test_when_finished "rm -rf tmp;
2106 git config --unset format.coverletter" &&
2108 git config format.coverletter auto &&
2109 git format-patch -o tmp --cover-letter -1 >list &&
2110 test_line_count = 2 list &&
2111 git format-patch -o tmp --cover-letter -2 >list &&
2112 test_line_count = 3 list &&
2113 git format-patch -o tmp --no-cover-letter -1 >list &&
2114 test_line_count = 1 list &&
2115 git format-patch -o tmp --no-cover-letter -2 >list &&
2116 test_line_count = 2 list
2119 test_expect_success
'format-patch --zero-commit' '
2120 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
2121 grep "^From " patch2 | sort | uniq >actual &&
2122 echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
2123 test_cmp expect actual
2126 test_expect_success
'From line has expected format' '
2127 git format-patch --stdout v2..v1 >patch2 &&
2128 grep "^From " patch2 >from &&
2129 grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
2130 test_cmp from filtered
2133 test_expect_success
'format-patch -o with no leading directories' '
2135 git format-patch -o patches main..side &&
2136 count=$(git rev-list --count main..side) &&
2138 test_line_count = $count list
2141 test_expect_success
'format-patch -o with leading existing directories' '
2142 rm -rf existing-dir &&
2143 mkdir existing-dir &&
2144 git format-patch -o existing-dir/patches main..side &&
2145 count=$(git rev-list --count main..side) &&
2146 ls existing-dir/patches >list &&
2147 test_line_count = $count list
2150 test_expect_success
'format-patch -o with leading non-existing directories' '
2151 rm -rf non-existing-dir &&
2152 git format-patch -o non-existing-dir/patches main..side &&
2153 count=$(git rev-list --count main..side) &&
2154 test_path_is_dir non-existing-dir &&
2155 ls non-existing-dir/patches >list &&
2156 test_line_count = $count list
2159 test_expect_success
'format-patch format.outputDirectory option' '
2160 test_config format.outputDirectory patches &&
2162 git format-patch main..side &&
2163 count=$(git rev-list --count main..side) &&
2165 test_line_count = $count list
2168 test_expect_success
'format-patch -o overrides format.outputDirectory' '
2169 test_config format.outputDirectory patches &&
2170 rm -fr patches patchset &&
2171 git format-patch main..side -o patchset &&
2172 test_path_is_missing patches &&
2173 test_path_is_dir patchset
2176 test_expect_success
'format-patch forbids multiple outputs' '
2177 rm -fr outfile outdir &&
2179 git format-patch --stdout --output-directory=outdir &&
2181 git format-patch --stdout --output=outfile &&
2183 git format-patch --output=outfile --output-directory=outdir
2186 test_expect_success
'configured outdir does not conflict with output options' '
2187 rm -fr outfile outdir &&
2188 test_config format.outputDirectory outdir &&
2189 git format-patch --stdout &&
2190 test_path_is_missing outdir &&
2191 git format-patch --output=outfile &&
2192 test_path_is_missing outdir
2195 test_expect_success
'format-patch --output' '
2197 git format-patch -3 --stdout HEAD >expect &&
2198 git format-patch -3 --output=outfile HEAD &&
2199 test_cmp expect outfile
2202 test_expect_success
'format-patch --cover-letter --output' '
2204 git format-patch --cover-letter -3 --stdout HEAD >expect &&
2205 git format-patch --cover-letter -3 --output=outfile HEAD &&
2206 test_cmp expect outfile
2209 test_expect_success
'format-patch --base' '
2210 git checkout patchid &&
2212 git format-patch --stdout --base=HEAD~3 -1 >patch &&
2213 tail -n 7 patch >actual1 &&
2215 git format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&
2216 tail -n 7 patch >actual2 &&
2219 git rev-parse HEAD~3 >commit-id-base &&
2220 echo "base-commit: $(cat commit-id-base)" >>expect &&
2222 git show --patch HEAD~2 >patch &&
2223 git patch-id --stable <patch >patch.id.raw &&
2224 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2226 git show --patch HEAD~1 >patch &&
2227 git patch-id --stable <patch >patch.id.raw &&
2228 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2230 signature >>expect &&
2231 test_cmp expect actual1 &&
2232 test_cmp expect actual2 &&
2235 echo "base-commit: $(cat commit-id-base)" >>fail &&
2237 git show --patch HEAD~2 >patch &&
2238 git patch-id --unstable <patch >patch.id.raw &&
2239 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2241 git show --patch HEAD~1 >patch &&
2242 git patch-id --unstable <patch >patch.id.raw &&
2243 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2246 ! test_cmp fail actual1 &&
2247 ! test_cmp fail actual2
2250 test_expect_success
'format-patch --base errors out when base commit is in revision list' '
2251 test_must_fail git format-patch --base=HEAD -2 &&
2252 test_must_fail git format-patch --base=HEAD~1 -2 &&
2253 git format-patch --stdout --base=HEAD~2 -2 >patch &&
2254 grep "^base-commit:" patch >actual &&
2255 git rev-parse HEAD~2 >commit-id-base &&
2256 echo "base-commit: $(cat commit-id-base)" >expect &&
2257 test_cmp expect actual
2260 test_expect_success
'format-patch --base errors out when base commit is not ancestor of revision list' '
2261 # For history as below:
2263 # ---Q---P---Z---Y---*---X
2267 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
2268 git checkout -b topic1 main &&
2269 git rev-parse HEAD >commit-id-base &&
2271 git rev-parse HEAD >commit-id-P &&
2273 git rev-parse HEAD >commit-id-Z &&
2275 git checkout -b topic2 main &&
2279 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
2280 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
2281 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
2282 grep "^base-commit:" patch >actual &&
2283 echo "base-commit: $(cat commit-id-base)" >expect &&
2284 test_cmp expect actual
2287 test_expect_success
'format-patch --base=auto' '
2288 git checkout -b upstream main &&
2289 git checkout -b local upstream &&
2290 git branch --set-upstream-to=upstream &&
2293 git format-patch --stdout --base=auto -2 >patch &&
2294 grep "^base-commit:" patch >actual &&
2295 git rev-parse upstream >commit-id-base &&
2296 echo "base-commit: $(cat commit-id-base)" >expect &&
2297 test_cmp expect actual
2300 test_expect_success
'format-patch errors out when history involves criss-cross' '
2301 # setup criss-cross history
2309 git checkout main &&
2311 git checkout -b xb main &&
2313 git checkout -b xc main &&
2315 git checkout -b xbc xb -- &&
2317 git checkout -b xcb xc -- &&
2318 git branch --set-upstream-to=xbc &&
2324 test_must_fail git format-patch --base=auto -1
2327 test_expect_success
'format-patch format.useAutoBase whenAble history involves criss-cross' '
2328 test_config format.useAutoBase whenAble &&
2329 git format-patch -1 >patch &&
2330 ! grep "^base-commit:" patch
2333 test_expect_success
'format-patch format.useAutoBase option' '
2334 git checkout local &&
2335 test_config format.useAutoBase true &&
2336 git format-patch --stdout -1 >patch &&
2337 grep "^base-commit:" patch >actual &&
2338 git rev-parse upstream >commit-id-base &&
2339 echo "base-commit: $(cat commit-id-base)" >expect &&
2340 test_cmp expect actual
2343 test_expect_success
'format-patch format.useAutoBase option with whenAble' '
2344 git checkout local &&
2345 test_config format.useAutoBase whenAble &&
2346 git format-patch --stdout -1 >patch &&
2347 grep "^base-commit:" patch >actual &&
2348 git rev-parse upstream >commit-id-base &&
2349 echo "base-commit: $(cat commit-id-base)" >expect &&
2350 test_cmp expect actual
2353 test_expect_success
'format-patch --base overrides format.useAutoBase' '
2354 test_config format.useAutoBase true &&
2355 git format-patch --stdout --base=HEAD~1 -1 >patch &&
2356 grep "^base-commit:" patch >actual &&
2357 git rev-parse HEAD~1 >commit-id-base &&
2358 echo "base-commit: $(cat commit-id-base)" >expect &&
2359 test_cmp expect actual
2362 test_expect_success
'format-patch --no-base overrides format.useAutoBase' '
2363 test_config format.useAutoBase true &&
2364 git format-patch --stdout --no-base -1 >patch &&
2365 ! grep "^base-commit:" patch
2368 test_expect_success
'format-patch --no-base overrides format.useAutoBase whenAble' '
2369 test_config format.useAutoBase whenAble &&
2370 git format-patch --stdout --no-base -1 >patch &&
2371 ! grep "^base-commit:" patch
2374 test_expect_success
'format-patch --base with --attach' '
2375 git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
2376 sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
2378 test_write_lines 1 2 >expect &&
2379 test_cmp expect actual
2381 test_expect_success
'format-patch --attach cover-letter only is non-multipart' '
2382 test_when_finished "rm -fr patches" &&
2383 git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
2384 ! grep -E "^--+mimemime" patches/0000*.patch &&
2385 grep -E "^--+mimemime$" patches/0001*.patch >output &&
2386 test_line_count = 2 output &&
2387 grep -E "^--+mimemime--$" patches/0001*.patch >output &&
2388 test_line_count = 1 output
2391 test_expect_success
'format-patch with format.attach' '
2392 test_when_finished "rm -fr patches" &&
2393 separator=attachment-separator &&
2394 test_config format.attach "$separator" &&
2395 filename=$(git format-patch -o patches -1) &&
2396 grep "^Content-Type: multipart/.*$separator" "$filename"
2399 test_expect_success
'format-patch with format.attach=disabled' '
2400 test_when_finished "rm -fr patches" &&
2401 separator=attachment-separator &&
2402 test_config_global format.attach "$separator" &&
2403 test_config format.attach "" &&
2404 filename=$(git format-patch -o patches -1) &&
2405 # The output should not even declare content type for text/plain.
2406 ! grep "^Content-Type: multipart/" "$filename"
2409 test_expect_success
'-c format.mboxrd format-patch' '
2411 cat >msg <<-INPUT_END &&
2412 mboxrd should escape the body
2414 From could trip up a loose mbox parser
2415 >From extra escape for reversibility
2416 >>From extra escape for reversibility 2
2417 from lower case not escaped
2418 Fromm bad speling not escaped
2419 From with leading space not escaped
2428 cat >expect <<-INPUT_END &&
2429 >From could trip up a loose mbox parser
2430 >>From extra escape for reversibility
2431 >>>From extra escape for reversibility 2
2432 from lower case not escaped
2433 Fromm bad speling not escaped
2434 From with leading space not escaped
2443 C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
2444 git -c format.mboxrd format-patch --stdout -1 $C~1..$C >patch &&
2445 git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >compat &&
2446 test_cmp patch compat &&
2447 git grep -h --no-index -A11 \
2448 "^>From could trip up a loose mbox parser" patch >actual &&
2449 test_cmp expect actual
2452 test_expect_success
'interdiff: setup' '
2453 git checkout -b boop main &&
2454 test_commit fnorp blorp &&
2455 test_commit fleep blorp
2458 test_expect_success
'interdiff: cover-letter' '
2459 sed "y/q/ /" >expect <<-\EOF &&
2463 git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
2464 test_grep "^Interdiff:$" 0000-cover-letter.patch &&
2465 test_grep ! "^Interdiff:$" 0001-fleep.patch &&
2466 sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual &&
2467 test_cmp expect actual
2470 test_expect_success
'interdiff: reroll-count' '
2471 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2472 test_grep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2475 test_expect_success
'interdiff: reroll-count with a non-integer' '
2476 git format-patch --cover-letter --interdiff=boop~2 -v2.2 -1 boop &&
2477 test_grep "^Interdiff:$" v2.2-0000-cover-letter.patch
2480 test_expect_success
'interdiff: reroll-count with a integer' '
2481 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2482 test_grep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2485 test_expect_success
'interdiff: solo-patch' '
2486 git format-patch --interdiff=boop~2 -1 boop &&
2488 # remove up to the last "patch" output line,
2489 # and remove everything below the signature mark.
2490 sed -e "1,/^+fleep\$/d" -e "/^-- /,\$d" 0001-fleep.patch >actual &&
2492 # fabricate Interdiff output.
2493 git diff boop~2 boop >inter &&
2496 echo "Interdiff:" &&
2497 sed -e "s/^/ /" inter
2499 test_cmp expect actual
2502 test_expect_success
'range-diff: solo-patch' '
2503 git format-patch --creation-factor=999 \
2504 --range-diff=boop~2..boop~1 -1 boop &&
2506 # remove up to the last "patch" output line,
2507 # and remove everything below the signature mark.
2508 sed -e "1,/^+fleep\$/d" -e "/^-- /,\$d" 0001-fleep.patch >actual &&
2510 # fabricate range-diff output.
2513 echo "Range-diff:" &&
2514 git range-diff --creation-factor=999 \
2515 boop~2..boop~1 boop~1..boop
2517 test_cmp expect actual
2520 test_expect_success
'interdiff: multi-patch, implicit --cover-letter' '
2521 test_when_finished "rm -f v23-0*.patch" &&
2522 git format-patch --interdiff=boop~2 -2 -v23 &&
2523 test_grep "^Interdiff against v22:$" v23-0000-cover-letter.patch &&
2524 test_cmp expect actual
2527 test_expect_success
'interdiff: explicit --no-cover-letter defeats implied --cover-letter' '
2528 test_when_finished "rm -f v23-0*.patch" &&
2529 test_must_fail git format-patch --no-cover-letter \
2530 --interdiff=boop~2 -2 -v23 &&
2531 test_must_fail git -c format.coverLetter=no format-patch \
2532 --interdiff=boop~2 -2 -v23
2535 test_expect_success
'format-patch does not respect diff.noprefix' '
2536 git -c diff.noprefix format-patch -1 --stdout >actual &&
2537 grep "^--- a/blorp" actual
2540 test_expect_success
'format-patch respects format.noprefix' '
2541 git -c format.noprefix format-patch -1 --stdout >actual &&
2542 grep "^--- blorp" actual
2545 test_expect_success
'format-patch --default-prefix overrides format.noprefix' '
2546 git -c format.noprefix \
2547 format-patch -1 --default-prefix --stdout >actual &&
2548 grep "^--- a/blorp" actual