Merge branch 'ja/doc-synopsis-markup'
[git/gitster.git] / t / t4014-format-patch.sh
blob1c46e963e4326b281e7e5912d70d04c564774dde
1 #!/bin/sh
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
12 . ./test-lib.sh
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 &&
17 cat file >elif &&
18 git add file elif &&
19 test_tick &&
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 &&
24 test_chmod +x elif &&
25 test_tick &&
26 git commit -m "Side changes #1" &&
28 test_write_lines D E F >>file &&
29 git update-index file &&
30 test_tick &&
31 git commit -m "Side changes #2" &&
32 git tag C2 &&
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 &&
36 test_tick &&
37 git commit -m "Side changes #3 with \\n backslash-n in it." &&
39 git checkout main &&
40 git diff-tree -p C2 >patch &&
41 git apply --index <patch &&
42 test_tick &&
43 git commit -m "Main accepts moral equivalent of #2" &&
45 git checkout side &&
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 &&
51 test_tick &&
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 &&
56 test_tick &&
57 git commit -m "patchid 2" &&
58 test_write_lines 10 5 6 >file &&
59 git add file &&
60 test_tick &&
61 git commit -m "patchid 3" &&
63 git checkout -b empty main &&
64 test_tick &&
65 git commit --allow-empty -m "empty commit" &&
67 git checkout main
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 &&
94 test_tick &&
95 git commit -am "Feature branch change #1" &&
96 echo "Yet another line" >>file &&
97 test_tick &&
98 git commit -am "Feature branch change #2" &&
99 git checkout -b merger main &&
100 test_tick &&
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 &&
109 git am -3 patch0 &&
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 &&
116 git am -3 patch1 &&
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>
144 " &&
145 git config --add format.headers "Cc: S E Cipient <scipient@example.com>
146 " &&
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
244 check_patch () {
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 &&
253 check_patch patch &&
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 &&
260 check_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 &&
267 check_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 &&
274 check_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 &&
281 check_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' '
324 rm -rf patches/ &&
325 git checkout side &&
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 &&
333 for len in 15 25 35
335 git format-patch --filename-max-length=$len -3 side &&
336 max=$(
337 for patch in 000[1-9]-*.patch
339 echo "$patch" | wc -c || exit 1
340 done |
341 sort -nr |
342 head -n 1
343 ) &&
344 test $max -le $len || return 1
345 done
348 test_expect_success 'filename length limit from config' '
349 test_when_finished "rm -f 000*" &&
350 rm -rf 000[1-9]-*.patch &&
351 for len in 15 25 35
353 git -c format.filenameMaxLength=$len format-patch -3 side &&
354 max=$(
355 for patch in 000[1-9]-*.patch
357 echo "$patch" | wc -c || exit 1
358 done |
359 sort -nr |
360 head -n 1
361 ) &&
362 test $max -le $len || return 1
363 done
366 test_expect_success 'filename limit applies only to basename' '
367 test_when_finished "rm -rf patches/" &&
368 rm -rf patches/ &&
369 for len in 15 25 35
371 git format-patch -o patches --filename-max-length=$len -3 side &&
372 max=$(
373 for patch in patches/000[1-9]-*.patch
375 echo "${patch#patches/}" | wc -c || exit 1
376 done |
377 sort -nr |
378 head -n 1
379 ) &&
380 test $max -le $len || return 1
381 done
384 test_expect_success 'reroll count' '
385 rm -fr patches &&
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)' '
393 rm -fr patches &&
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' '
401 rm -fr patches &&
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' '
409 rm -fr patches &&
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' '
417 rm -fr patches &&
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
424 check_threading () {
425 expect="$1" &&
426 shift &&
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
430 perl -ne '
431 if (/^(message-id|references|in-reply-to)/i) {
432 $printing = 1;
433 } elsif (/^\S/) {
434 $printing = 0;
436 if ($printing) {
437 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
438 for $k (keys %h) {s/$k/$h{$k}/};
439 print;
441 print "---\n" if /^From /i;
442 ' <patch >actual &&
443 test_cmp "$expect" actual
446 cat >>expect.no-threading <<EOF
452 test_expect_success 'no threading' '
453 git checkout side &&
454 check_threading expect.no-threading main
457 cat >expect.thread <<EOF
459 Message-ID: <0>
461 Message-ID: <1>
462 In-Reply-To: <0>
463 References: <0>
465 Message-ID: <2>
466 In-Reply-To: <0>
467 References: <0>
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
481 Message-ID: <0>
482 In-Reply-To: <1>
483 References: <1>
485 Message-ID: <2>
486 In-Reply-To: <1>
487 References: <1>
489 Message-ID: <3>
490 In-Reply-To: <1>
491 References: <1>
494 test_expect_success 'thread in-reply-to' '
495 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
496 --thread main
499 cat >expect.cover-letter <<EOF
501 Message-ID: <0>
503 Message-ID: <1>
504 In-Reply-To: <0>
505 References: <0>
507 Message-ID: <2>
508 In-Reply-To: <0>
509 References: <0>
511 Message-ID: <3>
512 In-Reply-To: <0>
513 References: <0>
516 test_expect_success 'thread cover-letter' '
517 check_threading expect.cover-letter --cover-letter --thread main
520 cat >expect.cl-irt <<EOF
522 Message-ID: <0>
523 In-Reply-To: <1>
524 References: <1>
526 Message-ID: <2>
527 In-Reply-To: <0>
528 References: <1>
531 Message-ID: <3>
532 In-Reply-To: <0>
533 References: <1>
536 Message-ID: <4>
537 In-Reply-To: <0>
538 References: <1>
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
554 Message-ID: <0>
556 Message-ID: <1>
557 In-Reply-To: <0>
558 References: <0>
560 Message-ID: <2>
561 In-Reply-To: <1>
562 References: <0>
566 test_expect_success 'thread deep' '
567 check_threading expect.deep --thread=deep main
570 cat >expect.deep-irt <<EOF
572 Message-ID: <0>
573 In-Reply-To: <1>
574 References: <1>
576 Message-ID: <2>
577 In-Reply-To: <0>
578 References: <1>
581 Message-ID: <3>
582 In-Reply-To: <2>
583 References: <1>
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
595 Message-ID: <0>
597 Message-ID: <1>
598 In-Reply-To: <0>
599 References: <0>
601 Message-ID: <2>
602 In-Reply-To: <1>
603 References: <0>
606 Message-ID: <3>
607 In-Reply-To: <2>
608 References: <0>
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
619 Message-ID: <0>
620 In-Reply-To: <1>
621 References: <1>
623 Message-ID: <2>
624 In-Reply-To: <0>
625 References: <1>
628 Message-ID: <3>
629 In-Reply-To: <2>
630 References: <1>
634 Message-ID: <4>
635 In-Reply-To: <3>
636 References: <1>
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' '
668 rm -rf patches/ &&
669 git checkout side &&
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' '
688 git mv file foo &&
689 git commit -m foo &&
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
697 cat >expect <<EOF
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
713 cat >expect <<EOF
714 index $before..$after 100644
715 --- a/file
716 +++ b/file
717 @@ -13,4 +13,20 @@ C
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 \
729 >output &&
730 test_cmp expect output
733 cat >expect <<EOF
735 diff --git a/file b/file
736 index $before..$after 100644
737 --- a/file
738 +++ b/file
739 @@ -14,3 +14,19 @@ C
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)' '
753 filename=$(
754 rm -rf sub &&
755 mkdir -p sub/dir &&
756 cd sub/dir &&
757 git format-patch -1
758 ) &&
759 case "$filename" in
761 ;; # ok
763 echo "Oops? $filename"
764 false
766 esac &&
767 test -f "$filename"
770 test_expect_success 'format-patch from a subdirectory (2)' '
771 filename=$(
772 rm -rf sub &&
773 mkdir -p sub/dir &&
774 cd sub/dir &&
775 git format-patch -1 -o ..
776 ) &&
777 case "$filename" in
778 ../0*)
779 ;; # ok
781 echo "Oops? $filename"
782 false
784 esac &&
785 basename=$(expr "$filename" : ".*/\(.*\)") &&
786 test -f "sub/$basename"
789 test_expect_success 'format-patch from a subdirectory (3)' '
790 rm -f 0* &&
791 filename=$(
792 rm -rf sub &&
793 mkdir -p sub/dir &&
794 cd sub/dir &&
795 git format-patch -1 -o "$TRASH_DIRECTORY"
796 ) &&
797 basename=$(expr "$filename" : ".*/\(.*\)") &&
798 test -f "$basename"
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>' '
945 rm -f *.patch &&
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 &&
954 git add file_a &&
955 git commit -m pathspec_a &&
957 echo file_b 2 >>file_b &&
958 git add 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' '
978 git checkout side &&
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##* }
987 signature() {
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 &&
994 signature >expect &&
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 \
1021 -1 >output &&
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 \
1031 -1 >output &&
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
1073 } >expect &&
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
1084 } >expect &&
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
1106 } >expect &&
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' '
1118 rm -f pager_used &&
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' '
1124 rm -f pager_used &&
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' '
1132 rm -rf patches/ &&
1133 echo content >>file &&
1134 test_write_lines one two three >msg &&
1135 git add file &&
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' '
1144 rm -rf patches/ &&
1145 echo content >>file &&
1146 test_write_lines en två tre >msg &&
1147 git add file &&
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
1155 M8="foo bar "
1156 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1157 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1158 cat >expect <<'EOF'
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 &&
1169 git add 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
1176 M8="föö bar "
1177 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1178 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1179 cat >expect <<'EOF'
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?=
1203 =?UTF-8?q?bar?=
1205 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
1206 rm -rf patches/ &&
1207 echo content >>file &&
1208 git add 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
1215 check_author() {
1216 echo content >>file &&
1217 git add 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
1224 cat >expect <<'EOF'
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"
1231 cat >expect <<'EOF'
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"
1238 cat >expect <<'EOF'
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"
1245 cat >expect <<'EOF'
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"
1252 cat >expect <<EOF
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_"
1260 cat >expect <<'EOF'
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"
1269 cat >expect <<'EOF'
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"
1278 cat >expect <<'EOF'
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"
1289 cat >expect <<'EOF'
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 &&
1296 git add 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
1304 cat >expect <<'EOF'
1305 Subject: [PATCH] Foö
1307 test_expect_success 'subject lines are unencoded with --no-encode-email-headers' '
1308 echo content >>file &&
1309 git add 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
1316 cat >expect <<'EOF'
1317 Subject: [PATCH] Foö
1319 test_expect_success 'subject lines are unencoded with format.encodeEmailHeaders=false' '
1320 echo content >>file &&
1321 git add 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
1329 cat >expect <<'EOF'
1330 Subject: [PATCH] =?UTF-8?q?Fo=C3=B6?=
1332 test_expect_success '--encode-email-headers overrides format.encodeEmailHeaders' '
1333 echo content >>file &&
1334 git add 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
1342 cat >expect <<'EOF'
1343 Subject: header with . in it
1345 test_expect_success 'subject lines do not have 822 atom-quoting' '
1346 echo content >>file &&
1347 git add 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
1354 cat >expect <<'EOF'
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
1363 cat >expect <<'EOF'
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
1538 append_signoff()
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 &&
1578 subject
1580 body
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 &&
1604 subject
1606 body
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 &&
1622 subject
1624 body
1626 Signed-off-by: my@house
1627 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1628 Tested-by: Some One <someone@example.com>
1629 Bug: 1234
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 &&
1643 subject
1645 body
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 &&
1659 subject
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 &&
1675 subject
1677 My unfortunate
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 &&
1691 subject
1693 Signed-off-by: my@house
1694 Signed-off-by: your@house
1696 A lot of houses.
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 &&
1712 subject
1714 body
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 &&
1740 subject
1742 body
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 &&
1759 subject
1761 body
1763 Tested-by: my@house
1764 Some Trash
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 &&
1778 subject
1780 Myfooter: x
1781 Some Trash
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 &&
1793 subject
1795 Myfooter: x
1796 Some Trash
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 &&
1808 subject
1810 body
1812 Reviewed-id: Noone
1813 Tested-by: my@house
1814 Change-id: Ideadbeef
1815 Signed-off-by: C O Mitter <committer@example.com>
1816 Bug: 1234
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' '
1836 rm -rf subdir &&
1837 mkdir subdir &&
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
1851 body" &&
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
1860 body" &&
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
1873 body" &&
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
1885 body" &&
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
1898 body" &&
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
1910 body" &&
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
1923 body" &&
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
1935 body" &&
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
1948 body" &&
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é?
1960 body" &&
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
1970 body" &&
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
1983 body" &&
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
1995 body" &&
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
2008 body" &&
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
2020 body" &&
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 &&
2034 grep hello 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 &&
2041 grep hello 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 &&
2048 grep hello 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 &&
2055 grep hello 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 &&
2062 grep hello 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 &&
2069 grep hello actual
2072 test_expect_success 'cover letter with --description-file' '
2073 test_when_finished "rm -f description.txt" &&
2074 cat >description.txt <<-\EOF &&
2075 subject from file
2077 body from file
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' '
2092 mkdir -p tmp &&
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' '
2104 mkdir -p tmp &&
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' '
2134 rm -fr patches &&
2135 git format-patch -o patches main..side &&
2136 count=$(git rev-list --count main..side) &&
2137 ls patches >list &&
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 &&
2161 rm -fr patches &&
2162 git format-patch main..side &&
2163 count=$(git rev-list --count main..side) &&
2164 ls patches >list &&
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 &&
2178 test_must_fail \
2179 git format-patch --stdout --output-directory=outdir &&
2180 test_must_fail \
2181 git format-patch --stdout --output=outfile &&
2182 test_must_fail \
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' '
2196 rm -fr outfile &&
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' '
2203 rm -fr outfile &&
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 &&
2218 echo >expect &&
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 &&
2234 echo >fail &&
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 &&
2245 signature >>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
2264 # \ /
2265 # ------------W
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 &&
2270 test_commit P &&
2271 git rev-parse HEAD >commit-id-P &&
2272 test_commit Z &&
2273 git rev-parse HEAD >commit-id-Z &&
2274 test_commit Y &&
2275 git checkout -b topic2 main &&
2276 test_commit W &&
2277 git merge topic1 &&
2278 test_commit X &&
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 &&
2291 test_commit N1 &&
2292 test_commit N2 &&
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
2303 # B---M1---D
2304 # / \ /
2305 # A X
2306 # \ / \
2307 # C---M2---E
2309 git checkout main &&
2310 test_commit A &&
2311 git checkout -b xb main &&
2312 test_commit B &&
2313 git checkout -b xc main &&
2314 test_commit C &&
2315 git checkout -b xbc xb -- &&
2316 git merge xc &&
2317 git checkout -b xcb xc -- &&
2318 git branch --set-upstream-to=xbc &&
2319 git merge xb &&
2320 git checkout xbc &&
2321 test_commit D &&
2322 git checkout xcb &&
2323 test_commit E &&
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" \
2377 patch >actual &&
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' '
2410 sp=" " &&
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
2422 From
2423 From$sp
2424 From $sp
2425 From $sp
2426 INPUT_END
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
2437 From
2438 From
2439 From
2440 From
2441 INPUT_END
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 &&
2460 +fleep
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 &&
2495 echo &&
2496 echo "Interdiff:" &&
2497 sed -e "s/^/ /" inter
2498 } >expect &&
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.
2512 echo &&
2513 echo "Range-diff:" &&
2514 git range-diff --creation-factor=999 \
2515 boop~2..boop~1 boop~1..boop
2516 } >expect &&
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
2551 test_done