Git 2.45
[git/gitster.git] / t / t4014-format-patch.sh
blobe37a1411ee247cc76083367870e0e0c2e16fbb84
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-lib.sh
12 . "$TEST_DIRECTORY"/lib-terminal.sh
14 test_expect_success setup '
15 test_write_lines 1 2 3 4 5 6 7 8 9 10 >file &&
16 cat file >elif &&
17 git add file elif &&
18 test_tick &&
19 git commit -m Initial &&
20 git checkout -b side &&
22 test_write_lines 1 2 5 6 A B C 7 8 9 10 >file &&
23 test_chmod +x elif &&
24 test_tick &&
25 git commit -m "Side changes #1" &&
27 test_write_lines D E F >>file &&
28 git update-index file &&
29 test_tick &&
30 git commit -m "Side changes #2" &&
31 git tag C2 &&
33 test_write_lines 5 6 1 2 3 A 4 B C 7 8 9 10 D E F >file &&
34 git update-index file &&
35 test_tick &&
36 git commit -m "Side changes #3 with \\n backslash-n in it." &&
38 git checkout main &&
39 git diff-tree -p C2 >patch &&
40 git apply --index <patch &&
41 test_tick &&
42 git commit -m "Main accepts moral equivalent of #2" &&
44 git checkout side &&
45 git checkout -b patchid &&
46 test_write_lines 5 6 1 2 3 A 4 B C 7 8 9 10 D E F >file2 &&
47 test_write_lines 1 2 3 A 4 B C 7 8 9 10 D E F 5 6 >file3 &&
48 test_write_lines 8 9 10 >file &&
49 git add file file2 file3 &&
50 test_tick &&
51 git commit -m "patchid 1" &&
52 test_write_lines 4 A B 7 8 9 10 >file2 &&
53 test_write_lines 8 9 10 5 6 >file3 &&
54 git add file2 file3 &&
55 test_tick &&
56 git commit -m "patchid 2" &&
57 test_write_lines 10 5 6 >file &&
58 git add file &&
59 test_tick &&
60 git commit -m "patchid 3" &&
62 git checkout -b empty main &&
63 test_tick &&
64 git commit --allow-empty -m "empty commit" &&
66 git checkout main
69 test_expect_success 'format-patch --ignore-if-in-upstream' '
70 git format-patch --stdout main..side >patch0 &&
71 grep "^From " patch0 >from0 &&
72 test_line_count = 3 from0
75 test_expect_success 'format-patch --ignore-if-in-upstream' '
76 git format-patch --stdout \
77 --ignore-if-in-upstream main..side >patch1 &&
78 grep "^From " patch1 >from1 &&
79 test_line_count = 2 from1
82 test_expect_success 'format-patch --ignore-if-in-upstream handles tags' '
83 git tag -a v1 -m tag side &&
84 git tag -a v2 -m tag main &&
85 git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
86 grep "^From " patch1 >from1 &&
87 test_line_count = 2 from1
90 test_expect_success "format-patch doesn't consider merge commits" '
91 git checkout -b feature main &&
92 echo "Another line" >>file &&
93 test_tick &&
94 git commit -am "Feature branch change #1" &&
95 echo "Yet another line" >>file &&
96 test_tick &&
97 git commit -am "Feature branch change #2" &&
98 git checkout -b merger main &&
99 test_tick &&
100 git merge --no-ff feature &&
101 git format-patch -3 --stdout >patch &&
102 grep "^From " patch >from &&
103 test_line_count = 3 from
106 test_expect_success 'format-patch result applies' '
107 git checkout -b rebuild-0 main &&
108 git am -3 patch0 &&
109 git rev-list main.. >list &&
110 test_line_count = 2 list
113 test_expect_success 'format-patch --ignore-if-in-upstream result applies' '
114 git checkout -b rebuild-1 main &&
115 git am -3 patch1 &&
116 git rev-list main.. >list &&
117 test_line_count = 2 list
120 test_expect_success 'commit did not screw up the log message' '
121 git cat-file commit side >actual &&
122 grep "^Side .* with .* backslash-n" actual
125 test_expect_success 'format-patch did not screw up the log message' '
126 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
127 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
130 test_expect_success 'replay did not screw up the log message' '
131 git cat-file commit rebuild-1 >actual &&
132 grep "^Side .* with .* backslash-n" actual
135 test_expect_success 'format-patch empty commit' '
136 git format-patch --stdout main..empty >empty &&
137 grep "^From " empty >from &&
138 test_line_count = 1 from
141 test_expect_success 'extra headers' '
142 git config format.headers "To: R E Cipient <rcipient@example.com>
143 " &&
144 git config --add format.headers "Cc: S E Cipient <scipient@example.com>
145 " &&
146 git format-patch --stdout main..side >patch2 &&
147 sed -e "/^\$/q" patch2 >hdrs2 &&
148 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
149 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
152 test_expect_success 'extra headers without newlines' '
153 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
154 git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
155 git format-patch --stdout main..side >patch3 &&
156 sed -e "/^\$/q" patch3 >hdrs3 &&
157 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
158 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
161 test_expect_success 'extra headers with multiple To:s' '
162 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
163 git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
164 git format-patch --stdout main..side >patch4 &&
165 sed -e "/^\$/q" patch4 >hdrs4 &&
166 grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
167 grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
170 test_expect_success 'additional command line cc (ascii)' '
171 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
172 git format-patch --cc="S E Cipient <scipient@example.com>" --stdout main..side >patch5 &&
173 sed -e "/^\$/q" patch5 >hdrs5 &&
174 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
175 grep "^ *S E Cipient <scipient@example.com>\$" hdrs5
178 test_expect_failure 'additional command line cc (rfc822)' '
179 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
180 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout main..side >patch5 &&
181 sed -e "/^\$/q" patch5 >hdrs5 &&
182 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
183 grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" hdrs5
186 test_expect_success 'command line headers' '
187 git config --unset-all format.headers &&
188 git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout main..side >patch6 &&
189 sed -e "/^\$/q" patch6 >hdrs6 &&
190 grep "^Cc: R E Cipient <rcipient@example.com>\$" hdrs6
193 test_expect_success 'configuration headers and command line headers' '
194 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
195 git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout main..side >patch7 &&
196 sed -e "/^\$/q" patch7 >hdrs7 &&
197 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs7 &&
198 grep "^ *S E Cipient <scipient@example.com>\$" hdrs7
201 test_expect_success 'command line To: header (ascii)' '
202 git config --unset-all format.headers &&
203 git format-patch --to="R E Cipient <rcipient@example.com>" --stdout main..side >patch8 &&
204 sed -e "/^\$/q" patch8 >hdrs8 &&
205 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs8
208 test_expect_failure 'command line To: header (rfc822)' '
209 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout main..side >patch8 &&
210 sed -e "/^\$/q" patch8 >hdrs8 &&
211 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs8
214 test_expect_failure 'command line To: header (rfc2047)' '
215 git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout main..side >patch8 &&
216 sed -e "/^\$/q" patch8 >hdrs8 &&
217 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs8
220 test_expect_success 'configuration To: header (ascii)' '
221 git config format.to "R E Cipient <rcipient@example.com>" &&
222 git format-patch --stdout main..side >patch9 &&
223 sed -e "/^\$/q" patch9 >hdrs9 &&
224 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs9
227 test_expect_failure 'configuration To: header (rfc822)' '
228 git config format.to "R. E. Cipient <rcipient@example.com>" &&
229 git format-patch --stdout main..side >patch9 &&
230 sed -e "/^\$/q" patch9 >hdrs9 &&
231 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs9
234 test_expect_failure 'configuration To: header (rfc2047)' '
235 git config format.to "R Ä Cipient <rcipient@example.com>" &&
236 git format-patch --stdout main..side >patch9 &&
237 sed -e "/^\$/q" patch9 >hdrs9 &&
238 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs9
241 # check_patch <patch>: Verify that <patch> looks like a half-sane
242 # patch email to avoid a false positive with !grep
243 check_patch () {
244 grep -e "^From:" "$1" &&
245 grep -e "^Date:" "$1" &&
246 grep -e "^Subject:" "$1"
249 test_expect_success 'format.from=false' '
250 git -c format.from=false format-patch --stdout main..side >patch &&
251 sed -e "/^\$/q" patch >hdrs &&
252 check_patch patch &&
253 ! grep "^From: C O Mitter <committer@example.com>\$" hdrs
256 test_expect_success 'format.from=true' '
257 git -c format.from=true format-patch --stdout main..side >patch &&
258 sed -e "/^\$/q" patch >hdrs &&
259 check_patch hdrs &&
260 grep "^From: C O Mitter <committer@example.com>\$" hdrs
263 test_expect_success 'format.from with address' '
264 git -c format.from="F R Om <from@example.com>" format-patch --stdout main..side >patch &&
265 sed -e "/^\$/q" patch >hdrs &&
266 check_patch hdrs &&
267 grep "^From: F R Om <from@example.com>\$" hdrs
270 test_expect_success '--no-from overrides format.from' '
271 git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout main..side >patch &&
272 sed -e "/^\$/q" patch >hdrs &&
273 check_patch hdrs &&
274 ! grep "^From: F R Om <from@example.com>\$" hdrs
277 test_expect_success '--from overrides format.from' '
278 git -c format.from="F R Om <from@example.com>" format-patch --from --stdout main..side >patch &&
279 sed -e "/^\$/q" patch >hdrs &&
280 check_patch hdrs &&
281 ! grep "^From: F R Om <from@example.com>\$" hdrs
284 test_expect_success '--no-to overrides config.to' '
285 git config --replace-all format.to \
286 "R E Cipient <rcipient@example.com>" &&
287 git format-patch --no-to --stdout main..side >patch10 &&
288 sed -e "/^\$/q" patch10 >hdrs10 &&
289 check_patch hdrs10 &&
290 ! grep "^To: R E Cipient <rcipient@example.com>\$" hdrs10
293 test_expect_success '--no-to and --to replaces config.to' '
294 git config --replace-all format.to \
295 "Someone <someone@out.there>" &&
296 git format-patch --no-to --to="Someone Else <else@out.there>" \
297 --stdout main..side >patch11 &&
298 sed -e "/^\$/q" patch11 >hdrs11 &&
299 check_patch hdrs11 &&
300 ! grep "^To: Someone <someone@out.there>\$" hdrs11 &&
301 grep "^To: Someone Else <else@out.there>\$" hdrs11
304 test_expect_success '--no-cc overrides config.cc' '
305 git config --replace-all format.cc \
306 "C E Cipient <rcipient@example.com>" &&
307 git format-patch --no-cc --stdout main..side >patch12 &&
308 sed -e "/^\$/q" patch12 >hdrs12 &&
309 check_patch hdrs12 &&
310 ! grep "^Cc: C E Cipient <rcipient@example.com>\$" hdrs12
313 test_expect_success '--no-add-header overrides config.headers' '
314 git config --replace-all format.headers \
315 "Header1: B E Cipient <rcipient@example.com>" &&
316 git format-patch --no-add-header --stdout main..side >patch13 &&
317 sed -e "/^\$/q" patch13 >hdrs13 &&
318 check_patch hdrs13 &&
319 ! grep "^Header1: B E Cipient <rcipient@example.com>\$" hdrs13
322 test_expect_success 'multiple files' '
323 rm -rf patches/ &&
324 git checkout side &&
325 git format-patch -o patches/ main &&
326 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
329 test_expect_success 'filename length limit' '
330 test_when_finished "rm -f 000*" &&
331 rm -rf 000[1-9]-*.patch &&
332 for len in 15 25 35
334 git format-patch --filename-max-length=$len -3 side &&
335 max=$(
336 for patch in 000[1-9]-*.patch
338 echo "$patch" | wc -c || exit 1
339 done |
340 sort -nr |
341 head -n 1
342 ) &&
343 test $max -le $len || return 1
344 done
347 test_expect_success 'filename length limit from config' '
348 test_when_finished "rm -f 000*" &&
349 rm -rf 000[1-9]-*.patch &&
350 for len in 15 25 35
352 git -c format.filenameMaxLength=$len format-patch -3 side &&
353 max=$(
354 for patch in 000[1-9]-*.patch
356 echo "$patch" | wc -c || exit 1
357 done |
358 sort -nr |
359 head -n 1
360 ) &&
361 test $max -le $len || return 1
362 done
365 test_expect_success 'filename limit applies only to basename' '
366 test_when_finished "rm -rf patches/" &&
367 rm -rf patches/ &&
368 for len in 15 25 35
370 git format-patch -o patches --filename-max-length=$len -3 side &&
371 max=$(
372 for patch in patches/000[1-9]-*.patch
374 echo "${patch#patches/}" | wc -c || exit 1
375 done |
376 sort -nr |
377 head -n 1
378 ) &&
379 test $max -le $len || return 1
380 done
383 test_expect_success 'reroll count' '
384 rm -fr patches &&
385 git format-patch -o patches --cover-letter --reroll-count 4 main..side >list &&
386 ! grep -v "^patches/v4-000[0-3]-" list &&
387 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
388 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
391 test_expect_success 'reroll count (-v)' '
392 rm -fr patches &&
393 git format-patch -o patches --cover-letter -v4 main..side >list &&
394 ! grep -v "^patches/v4-000[0-3]-" list &&
395 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
396 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
399 test_expect_success 'reroll count (-v) with a fractional number' '
400 rm -fr patches &&
401 git format-patch -o patches --cover-letter -v4.4 main..side >list &&
402 ! grep -v "^patches/v4.4-000[0-3]-" list &&
403 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
404 ! grep -v "^Subject: \[PATCH v4.4 [0-3]/3\] " subjects
407 test_expect_success 'reroll (-v) count with a non number' '
408 rm -fr patches &&
409 git format-patch -o patches --cover-letter -v4rev2 main..side >list &&
410 ! grep -v "^patches/v4rev2-000[0-3]-" list &&
411 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
412 ! grep -v "^Subject: \[PATCH v4rev2 [0-3]/3\] " subjects
415 test_expect_success 'reroll (-v) count with a non-pathname character' '
416 rm -fr patches &&
417 git format-patch -o patches --cover-letter -v4---..././../--1/.2// main..side >list &&
418 ! grep -v "patches/v4-\.-\.-\.-1-\.2-000[0-3]-" list &&
419 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
420 ! grep -v "^Subject: \[PATCH v4---\.\.\./\./\.\./--1/\.2// [0-3]/3\] " subjects
423 check_threading () {
424 expect="$1" &&
425 shift &&
426 git format-patch --stdout "$@" >patch &&
427 # Prints everything between the Message-ID and In-Reply-To,
428 # and replaces all Message-ID-lookalikes by a sequence number
429 perl -ne '
430 if (/^(message-id|references|in-reply-to)/i) {
431 $printing = 1;
432 } elsif (/^\S/) {
433 $printing = 0;
435 if ($printing) {
436 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
437 for $k (keys %h) {s/$k/$h{$k}/};
438 print;
440 print "---\n" if /^From /i;
441 ' <patch >actual &&
442 test_cmp "$expect" actual
445 cat >>expect.no-threading <<EOF
451 test_expect_success 'no threading' '
452 git checkout side &&
453 check_threading expect.no-threading main
456 cat >expect.thread <<EOF
458 Message-ID: <0>
460 Message-ID: <1>
461 In-Reply-To: <0>
462 References: <0>
464 Message-ID: <2>
465 In-Reply-To: <0>
466 References: <0>
469 test_expect_success 'thread' '
470 check_threading expect.thread --thread main
473 test_expect_success '--thread overrides format.thread=deep' '
474 test_config format.thread deep &&
475 check_threading expect.thread --thread main
478 cat >expect.in-reply-to <<EOF
480 Message-ID: <0>
481 In-Reply-To: <1>
482 References: <1>
484 Message-ID: <2>
485 In-Reply-To: <1>
486 References: <1>
488 Message-ID: <3>
489 In-Reply-To: <1>
490 References: <1>
493 test_expect_success 'thread in-reply-to' '
494 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
495 --thread main
498 cat >expect.cover-letter <<EOF
500 Message-ID: <0>
502 Message-ID: <1>
503 In-Reply-To: <0>
504 References: <0>
506 Message-ID: <2>
507 In-Reply-To: <0>
508 References: <0>
510 Message-ID: <3>
511 In-Reply-To: <0>
512 References: <0>
515 test_expect_success 'thread cover-letter' '
516 check_threading expect.cover-letter --cover-letter --thread main
519 cat >expect.cl-irt <<EOF
521 Message-ID: <0>
522 In-Reply-To: <1>
523 References: <1>
525 Message-ID: <2>
526 In-Reply-To: <0>
527 References: <1>
530 Message-ID: <3>
531 In-Reply-To: <0>
532 References: <1>
535 Message-ID: <4>
536 In-Reply-To: <0>
537 References: <1>
541 test_expect_success 'thread cover-letter in-reply-to' '
542 check_threading expect.cl-irt --cover-letter \
543 --in-reply-to="<test.message>" --thread main
546 test_expect_success 'thread explicit shallow' '
547 check_threading expect.cl-irt --cover-letter \
548 --in-reply-to="<test.message>" --thread=shallow main
551 cat >expect.deep <<EOF
553 Message-ID: <0>
555 Message-ID: <1>
556 In-Reply-To: <0>
557 References: <0>
559 Message-ID: <2>
560 In-Reply-To: <1>
561 References: <0>
565 test_expect_success 'thread deep' '
566 check_threading expect.deep --thread=deep main
569 cat >expect.deep-irt <<EOF
571 Message-ID: <0>
572 In-Reply-To: <1>
573 References: <1>
575 Message-ID: <2>
576 In-Reply-To: <0>
577 References: <1>
580 Message-ID: <3>
581 In-Reply-To: <2>
582 References: <1>
587 test_expect_success 'thread deep in-reply-to' '
588 check_threading expect.deep-irt --thread=deep \
589 --in-reply-to="<test.message>" main
592 cat >expect.deep-cl <<EOF
594 Message-ID: <0>
596 Message-ID: <1>
597 In-Reply-To: <0>
598 References: <0>
600 Message-ID: <2>
601 In-Reply-To: <1>
602 References: <0>
605 Message-ID: <3>
606 In-Reply-To: <2>
607 References: <0>
612 test_expect_success 'thread deep cover-letter' '
613 check_threading expect.deep-cl --cover-letter --thread=deep main
616 cat >expect.deep-cl-irt <<EOF
618 Message-ID: <0>
619 In-Reply-To: <1>
620 References: <1>
622 Message-ID: <2>
623 In-Reply-To: <0>
624 References: <1>
627 Message-ID: <3>
628 In-Reply-To: <2>
629 References: <1>
633 Message-ID: <4>
634 In-Reply-To: <3>
635 References: <1>
641 test_expect_success 'thread deep cover-letter in-reply-to' '
642 check_threading expect.deep-cl-irt --cover-letter \
643 --in-reply-to="<test.message>" --thread=deep main
646 test_expect_success 'thread via config' '
647 test_config format.thread true &&
648 check_threading expect.thread main
651 test_expect_success 'thread deep via config' '
652 test_config format.thread deep &&
653 check_threading expect.deep main
656 test_expect_success 'thread config + override' '
657 test_config format.thread deep &&
658 check_threading expect.thread --thread main
661 test_expect_success 'thread config + --no-thread' '
662 test_config format.thread deep &&
663 check_threading expect.no-threading --no-thread main
666 test_expect_success 'excessive subject' '
667 rm -rf patches/ &&
668 git checkout side &&
669 before=$(git hash-object file) &&
670 before=$(git rev-parse --short $before) &&
671 test_write_lines 5 6 1 2 3 A 4 B C 7 8 9 10 D E F >>file &&
672 after=$(git hash-object file) &&
673 after=$(git rev-parse --short $after) &&
674 git update-index file &&
675 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." &&
676 git format-patch -o patches/ main..side &&
677 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
680 test_expect_success 'failure to write cover-letter aborts gracefully' '
681 test_when_finished "rmdir 0000-cover-letter.patch" &&
682 mkdir 0000-cover-letter.patch &&
683 test_must_fail git format-patch --no-renames --cover-letter -1
686 test_expect_success 'cover-letter inherits diff options' '
687 git mv file foo &&
688 git commit -m foo &&
689 git format-patch --no-renames --cover-letter -1 &&
690 check_patch 0000-cover-letter.patch &&
691 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
692 git format-patch --cover-letter -1 -M &&
693 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
696 cat >expect <<EOF
697 This is an excessively long subject line for a message due to the
698 habit some projects have of not having a short, one-line subject at
699 the start of the commit message, but rather sticking a whole
700 paragraph right at the start as the only thing in the commit
701 message. It had better not become the filename for the patch.
706 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
707 git format-patch --cover-letter -2 &&
708 sed -e "1,/A U Thor/d" -e "/^\$/q" 0000-cover-letter.patch >output &&
709 test_cmp expect output
712 cat >expect <<EOF
713 index $before..$after 100644
714 --- a/file
715 +++ b/file
716 @@ -13,4 +13,20 @@ C
724 test_expect_success 'format-patch respects -U' '
725 git format-patch -U4 -2 &&
726 sed -e "1,/^diff/d" -e "/^+5/q" \
727 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
728 >output &&
729 test_cmp expect output
732 cat >expect <<EOF
734 diff --git a/file b/file
735 index $before..$after 100644
736 --- a/file
737 +++ b/file
738 @@ -14,3 +14,19 @@ C
745 test_expect_success 'format-patch -p suppresses stat' '
746 git format-patch -p -2 &&
747 sed -e "1,/^\$/d" -e "/^+5/q" 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&
748 test_cmp expect output
751 test_expect_success 'format-patch from a subdirectory (1)' '
752 filename=$(
753 rm -rf sub &&
754 mkdir -p sub/dir &&
755 cd sub/dir &&
756 git format-patch -1
757 ) &&
758 case "$filename" in
760 ;; # ok
762 echo "Oops? $filename"
763 false
765 esac &&
766 test -f "$filename"
769 test_expect_success 'format-patch from a subdirectory (2)' '
770 filename=$(
771 rm -rf sub &&
772 mkdir -p sub/dir &&
773 cd sub/dir &&
774 git format-patch -1 -o ..
775 ) &&
776 case "$filename" in
777 ../0*)
778 ;; # ok
780 echo "Oops? $filename"
781 false
783 esac &&
784 basename=$(expr "$filename" : ".*/\(.*\)") &&
785 test -f "sub/$basename"
788 test_expect_success 'format-patch from a subdirectory (3)' '
789 rm -f 0* &&
790 filename=$(
791 rm -rf sub &&
792 mkdir -p sub/dir &&
793 cd sub/dir &&
794 git format-patch -1 -o "$TRASH_DIRECTORY"
795 ) &&
796 basename=$(expr "$filename" : ".*/\(.*\)") &&
797 test -f "$basename"
800 test_expect_success 'format-patch --in-reply-to' '
801 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" >patch8 &&
802 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
803 grep "^References: <baz@foo.bar>" patch8
806 test_expect_success 'format-patch --signoff' '
807 git format-patch -1 --signoff --stdout >out &&
808 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
811 test_expect_success 'format-patch --notes --signoff' '
812 git notes --ref test add -m "test message" HEAD &&
813 git format-patch -1 --signoff --stdout --notes=test >out &&
814 # Three dashes must come after S-o-b
815 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
816 sed "1,/^Signed-off-by: /d" out | grep "test message" &&
817 # Notes message must come after three dashes
818 ! sed "/^---$/q" out | grep "test message" &&
819 sed "1,/^---$/d" out | grep "test message"
822 test_expect_success 'format-patch notes output control' '
823 git notes add -m "notes config message" HEAD &&
824 test_when_finished git notes remove HEAD &&
826 git format-patch -1 --stdout >out &&
827 ! grep "notes config message" out &&
828 git format-patch -1 --stdout --notes >out &&
829 grep "notes config message" out &&
830 git format-patch -1 --stdout --no-notes >out &&
831 ! grep "notes config message" out &&
832 git format-patch -1 --stdout --notes --no-notes >out &&
833 ! grep "notes config message" out &&
834 git format-patch -1 --stdout --no-notes --notes >out &&
835 grep "notes config message" out &&
837 test_config format.notes true &&
838 git format-patch -1 --stdout >out &&
839 grep "notes config message" out &&
840 git format-patch -1 --stdout --notes >out &&
841 grep "notes config message" out &&
842 git format-patch -1 --stdout --no-notes >out &&
843 ! grep "notes config message" out &&
844 git format-patch -1 --stdout --notes --no-notes >out &&
845 ! grep "notes config message" out &&
846 git format-patch -1 --stdout --no-notes --notes >out &&
847 grep "notes config message" out
850 test_expect_success 'format-patch with multiple notes refs' '
851 git notes --ref note1 add -m "this is note 1" HEAD &&
852 test_when_finished git notes --ref note1 remove HEAD &&
853 git notes --ref note2 add -m "this is note 2" HEAD &&
854 test_when_finished git notes --ref note2 remove HEAD &&
856 git format-patch -1 --stdout >out &&
857 ! grep "this is note 1" out &&
858 ! grep "this is note 2" out &&
859 git format-patch -1 --stdout --notes=note1 >out &&
860 grep "this is note 1" out &&
861 ! grep "this is note 2" out &&
862 git format-patch -1 --stdout --notes=note2 >out &&
863 ! grep "this is note 1" out &&
864 grep "this is note 2" out &&
865 git format-patch -1 --stdout --notes=note1 --notes=note2 >out &&
866 grep "this is note 1" out &&
867 grep "this is note 2" out &&
869 test_config format.notes note1 &&
870 git format-patch -1 --stdout >out &&
871 grep "this is note 1" out &&
872 ! grep "this is note 2" out &&
873 git format-patch -1 --stdout --no-notes >out &&
874 ! grep "this is note 1" out &&
875 ! grep "this is note 2" out &&
876 git format-patch -1 --stdout --notes=note2 >out &&
877 grep "this is note 1" out &&
878 grep "this is note 2" out &&
879 git format-patch -1 --stdout --no-notes --notes=note2 >out &&
880 ! grep "this is note 1" out &&
881 grep "this is note 2" out &&
883 git config --add format.notes note2 &&
884 git format-patch -1 --stdout >out &&
885 grep "this is note 1" out &&
886 grep "this is note 2" out &&
887 git format-patch -1 --stdout --no-notes >out &&
888 ! grep "this is note 1" out &&
889 ! grep "this is note 2" out
892 test_expect_success 'format-patch with multiple notes refs in config' '
893 test_when_finished "test_unconfig format.notes" &&
895 git notes --ref note1 add -m "this is note 1" HEAD &&
896 test_when_finished git notes --ref note1 remove HEAD &&
897 git notes --ref note2 add -m "this is note 2" HEAD &&
898 test_when_finished git notes --ref note2 remove HEAD &&
900 git config format.notes note1 &&
901 git format-patch -1 --stdout >out &&
902 grep "this is note 1" out &&
903 ! grep "this is note 2" out &&
904 git config format.notes note2 &&
905 git format-patch -1 --stdout >out &&
906 ! grep "this is note 1" out &&
907 grep "this is note 2" out &&
908 git config --add format.notes note1 &&
909 git format-patch -1 --stdout >out &&
910 grep "this is note 1" out &&
911 grep "this is note 2" out &&
913 git config --replace-all format.notes note1 &&
914 git config --add format.notes false &&
915 git format-patch -1 --stdout >out &&
916 ! grep "this is note 1" out &&
917 ! grep "this is note 2" out &&
918 git config --add format.notes note2 &&
919 git format-patch -1 --stdout >out &&
920 ! grep "this is note 1" out &&
921 grep "this is note 2" out
924 echo "fatal: --name-only does not make sense" >expect.name-only
925 echo "fatal: --name-status does not make sense" >expect.name-status
926 echo "fatal: --check does not make sense" >expect.check
928 test_expect_success 'options no longer allowed for format-patch' '
929 test_must_fail git format-patch --name-only 2>output &&
930 test_cmp expect.name-only output &&
931 test_must_fail git format-patch --name-status 2>output &&
932 test_cmp expect.name-status output &&
933 test_must_fail git format-patch --check 2>output &&
934 test_cmp expect.check output
937 test_expect_success 'format-patch --numstat should produce a patch' '
938 git format-patch --numstat --stdout main..side >output &&
939 grep "^diff --git a/" output >diff &&
940 test_line_count = 5 diff
943 test_expect_success 'format-patch -- <path>' '
944 rm -f *.patch &&
945 git checkout -b pathspec main &&
947 echo file_a 1 >file_a &&
948 echo file_b 1 >file_b &&
949 git add file_a file_b &&
950 git commit -m pathspec_initial &&
952 echo file_a 2 >>file_a &&
953 git add file_a &&
954 git commit -m pathspec_a &&
956 echo file_b 2 >>file_b &&
957 git add file_b &&
958 git commit -m pathspec_b &&
960 echo file_a 3 >>file_a &&
961 echo file_b 3 >>file_b &&
962 git add file_a file_b &&
963 git commit -m pathspec_ab &&
965 cat >expect <<-\EOF &&
966 0001-pathspec_initial.patch
967 0002-pathspec_a.patch
968 0003-pathspec_ab.patch
971 git format-patch main..pathspec -- file_a >output &&
972 test_cmp expect output &&
973 ! grep file_b *.patch
976 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
977 git checkout side &&
978 git format-patch --ignore-if-in-upstream HEAD
981 test_expect_success 'get git version' '
982 git_version=$(git --version) &&
983 git_version=${git_version##* }
986 signature() {
987 printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
990 test_expect_success 'format-patch default signature' '
991 git format-patch --stdout -1 >patch &&
992 tail -n 3 patch >output &&
993 signature >expect &&
994 test_cmp expect output
997 test_expect_success 'format-patch --signature' '
998 git format-patch --stdout --signature="my sig" -1 >patch &&
999 tail -n 3 patch >output &&
1000 signature "my sig" >expect &&
1001 test_cmp expect output
1004 test_expect_success 'format-patch with format.signature config' '
1005 git config format.signature "config sig" &&
1006 git format-patch --stdout -1 >output &&
1007 grep "config sig" output
1010 test_expect_success 'format-patch --signature overrides format.signature' '
1011 git config format.signature "config sig" &&
1012 git format-patch --stdout --signature="overrides" -1 >output &&
1013 ! grep "config sig" output &&
1014 grep "overrides" output
1017 test_expect_success 'format-patch --no-signature ignores format.signature' '
1018 git config format.signature "config sig" &&
1019 git format-patch --stdout --signature="my sig" --no-signature \
1020 -1 >output &&
1021 check_patch output &&
1022 ! grep "config sig" output &&
1023 ! grep "my sig" output &&
1024 ! grep "^-- \$" output
1027 test_expect_success 'format-patch --signature --cover-letter' '
1028 git config --unset-all format.signature &&
1029 git format-patch --stdout --signature="my sig" --cover-letter \
1030 -1 >output &&
1031 grep "my sig" output >sig &&
1032 test_line_count = 2 sig
1035 test_expect_success 'format.signature="" suppresses signatures' '
1036 git config format.signature "" &&
1037 git format-patch --stdout -1 >output &&
1038 check_patch output &&
1039 ! grep "^-- \$" output
1042 test_expect_success 'format-patch --no-signature suppresses signatures' '
1043 git config --unset-all format.signature &&
1044 git format-patch --stdout --no-signature -1 >output &&
1045 check_patch output &&
1046 ! grep "^-- \$" output
1049 test_expect_success 'format-patch --signature="" suppresses signatures' '
1050 git format-patch --stdout --signature="" -1 >output &&
1051 check_patch output &&
1052 ! grep "^-- \$" output
1055 test_expect_success 'prepare mail-signature input' '
1056 cat >mail-signature <<-\EOF
1058 Test User <test.email@kernel.org>
1059 http://git.kernel.org/cgit/git/git.git
1061 git.kernel.org/?p=git/git.git;a=summary
1066 test_expect_success '--signature-file=file works' '
1067 git format-patch --stdout --signature-file=mail-signature -1 >output &&
1068 check_patch output &&
1069 sed -e "1,/^-- \$/d" output >actual &&
1071 cat mail-signature && echo
1072 } >expect &&
1073 test_cmp expect actual
1076 test_expect_success 'format.signaturefile works' '
1077 test_config format.signaturefile mail-signature &&
1078 git format-patch --stdout -1 >output &&
1079 check_patch output &&
1080 sed -e "1,/^-- \$/d" output >actual &&
1082 cat mail-signature && echo
1083 } >expect &&
1084 test_cmp expect actual
1087 test_expect_success '--no-signature suppresses format.signaturefile ' '
1088 test_config format.signaturefile mail-signature &&
1089 git format-patch --stdout --no-signature -1 >output &&
1090 check_patch output &&
1091 ! grep "^-- \$" output
1094 test_expect_success '--signature-file overrides format.signaturefile' '
1095 cat >other-mail-signature <<-\EOF &&
1096 Use this other signature instead of mail-signature.
1098 test_config format.signaturefile mail-signature &&
1099 git format-patch --stdout \
1100 --signature-file=other-mail-signature -1 >output &&
1101 check_patch output &&
1102 sed -e "1,/^-- \$/d" output >actual &&
1104 cat other-mail-signature && echo
1105 } >expect &&
1106 test_cmp expect actual
1109 test_expect_success '--signature overrides format.signaturefile' '
1110 test_config format.signaturefile mail-signature &&
1111 git format-patch --stdout --signature="my sig" -1 >output &&
1112 check_patch output &&
1113 grep "my sig" output
1116 test_expect_success TTY 'format-patch --stdout paginates' '
1117 rm -f pager_used &&
1118 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
1119 test_path_is_file pager_used
1122 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
1123 rm -f pager_used &&
1124 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
1125 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
1126 test_path_is_missing pager_used &&
1127 test_path_is_missing .git/pager_used
1130 test_expect_success 'format-patch handles multi-line subjects' '
1131 rm -rf patches/ &&
1132 echo content >>file &&
1133 test_write_lines one two three >msg &&
1134 git add file &&
1135 git commit -F msg &&
1136 git format-patch -o patches -1 &&
1137 grep ^Subject: patches/0001-one.patch >actual &&
1138 echo "Subject: [PATCH] one two three" >expect &&
1139 test_cmp expect actual
1142 test_expect_success 'format-patch handles multi-line encoded subjects' '
1143 rm -rf patches/ &&
1144 echo content >>file &&
1145 test_write_lines en två tre >msg &&
1146 git add file &&
1147 git commit -F msg &&
1148 git format-patch -o patches -1 &&
1149 grep ^Subject: patches/0001-en.patch >actual &&
1150 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
1151 test_cmp expect actual
1154 M8="foo bar "
1155 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1156 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1157 cat >expect <<'EOF'
1158 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1159 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1160 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1161 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1162 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1163 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1164 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1166 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
1167 echo content >>file &&
1168 git add file &&
1169 git commit -m "$M512" &&
1170 git format-patch --stdout -1 >patch &&
1171 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1172 test_cmp expect subject
1175 M8="föö bar "
1176 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1177 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1178 cat >expect <<'EOF'
1179 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1180 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1181 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1182 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1183 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1184 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1185 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1186 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1187 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1188 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1189 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1190 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1191 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1192 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1193 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1194 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1195 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1196 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1197 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1198 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1199 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1200 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1201 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1202 =?UTF-8?q?bar?=
1204 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
1205 rm -rf patches/ &&
1206 echo content >>file &&
1207 git add file &&
1208 git commit -m "$M512" &&
1209 git format-patch --stdout -1 >patch &&
1210 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1211 test_cmp expect subject
1214 check_author() {
1215 echo content >>file &&
1216 git add file &&
1217 GIT_AUTHOR_NAME=$1 git commit -m author-check &&
1218 git format-patch --stdout -1 >patch &&
1219 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1220 test_cmp expect actual
1223 cat >expect <<'EOF'
1224 From: "Foo B. Bar" <author@example.com>
1226 test_expect_success 'format-patch quotes dot in from-headers' '
1227 check_author "Foo B. Bar"
1230 cat >expect <<'EOF'
1231 From: "Foo \"The Baz\" Bar" <author@example.com>
1233 test_expect_success 'format-patch quotes double-quote in from-headers' '
1234 check_author "Foo \"The Baz\" Bar"
1237 cat >expect <<'EOF'
1238 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1240 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1241 check_author "Föo Bar"
1244 cat >expect <<'EOF'
1245 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1247 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1248 check_author "Föo B. Bar"
1251 cat >expect <<EOF
1252 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1253 <author@example.com>
1255 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1256 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1259 cat >expect <<'EOF'
1260 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1261 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1262 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1264 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1265 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"
1268 cat >expect <<'EOF'
1269 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1270 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1271 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1273 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1274 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"
1277 cat >expect <<'EOF'
1278 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1279 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1280 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1281 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1282 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1284 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1285 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"
1288 cat >expect <<'EOF'
1289 From: Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1290 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1291 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1293 test_expect_success 'format-patch wraps extremely long from-header (non-ASCII without Q-encoding)' '
1294 echo content >>file &&
1295 git add file &&
1296 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" \
1297 git commit -m author-check &&
1298 git format-patch --no-encode-email-headers --stdout -1 >patch &&
1299 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1300 test_cmp expect actual
1303 cat >expect <<'EOF'
1304 Subject: [PATCH] Foö
1306 test_expect_success 'subject lines are unencoded with --no-encode-email-headers' '
1307 echo content >>file &&
1308 git add file &&
1309 git commit -m "Foö" &&
1310 git format-patch --no-encode-email-headers -1 --stdout >patch &&
1311 grep ^Subject: patch >actual &&
1312 test_cmp expect actual
1315 cat >expect <<'EOF'
1316 Subject: [PATCH] Foö
1318 test_expect_success 'subject lines are unencoded with format.encodeEmailHeaders=false' '
1319 echo content >>file &&
1320 git add file &&
1321 git commit -m "Foö" &&
1322 git config format.encodeEmailHeaders false &&
1323 git format-patch -1 --stdout >patch &&
1324 grep ^Subject: patch >actual &&
1325 test_cmp expect actual
1328 cat >expect <<'EOF'
1329 Subject: [PATCH] =?UTF-8?q?Fo=C3=B6?=
1331 test_expect_success '--encode-email-headers overrides format.encodeEmailHeaders' '
1332 echo content >>file &&
1333 git add file &&
1334 git commit -m "Foö" &&
1335 git config format.encodeEmailHeaders false &&
1336 git format-patch --encode-email-headers -1 --stdout >patch &&
1337 grep ^Subject: patch >actual &&
1338 test_cmp expect actual
1341 cat >expect <<'EOF'
1342 Subject: header with . in it
1344 test_expect_success 'subject lines do not have 822 atom-quoting' '
1345 echo content >>file &&
1346 git add file &&
1347 git commit -m "header with . in it" &&
1348 git format-patch -k -1 --stdout >patch &&
1349 grep ^Subject: patch >actual &&
1350 test_cmp expect actual
1353 cat >expect <<'EOF'
1354 Subject: [PREFIX 1/1] header with . in it
1356 test_expect_success 'subject prefixes have space prepended' '
1357 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1358 grep ^Subject: patch >actual &&
1359 test_cmp expect actual
1362 cat >expect <<'EOF'
1363 Subject: [1/1] header with . in it
1365 test_expect_success 'empty subject prefix does not have extra space' '
1366 git format-patch -n -1 --stdout --subject-prefix= >patch &&
1367 grep ^Subject: patch >actual &&
1368 test_cmp expect actual
1371 test_expect_success '--rfc' '
1372 cat >expect <<-\EOF &&
1373 Subject: [RFC PATCH 1/1] header with . in it
1375 git format-patch -n -1 --stdout --rfc >patch &&
1376 grep "^Subject:" patch >actual &&
1377 test_cmp expect actual
1380 test_expect_success '--rfc does not overwrite prefix' '
1381 cat >expect <<-\EOF &&
1382 Subject: [RFC PATCH foobar 1/1] header with . in it
1384 git -c format.subjectPrefix="PATCH foobar" \
1385 format-patch -n -1 --stdout --rfc >patch &&
1386 grep "^Subject:" patch >actual &&
1387 test_cmp expect actual
1390 test_expect_success '--rfc is argument order independent' '
1391 cat >expect <<-\EOF &&
1392 Subject: [RFC PATCH foobar 1/1] header with . in it
1394 git format-patch -n -1 --stdout --rfc \
1395 --subject-prefix="PATCH foobar" >patch &&
1396 grep "^Subject:" patch >actual &&
1397 test_cmp expect actual
1400 test_expect_success '--from=ident notices bogus ident' '
1401 test_must_fail git format-patch -1 --stdout --from=foo >patch
1404 test_expect_success '--from=ident replaces author' '
1405 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1406 cat >expect <<-\EOF &&
1407 From: Me <me@example.com>
1409 From: A U Thor <author@example.com>
1412 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1413 test_cmp expect patch.head
1416 test_expect_success '--from uses committer ident' '
1417 git format-patch -1 --stdout --from >patch &&
1418 cat >expect <<-\EOF &&
1419 From: C O Mitter <committer@example.com>
1421 From: A U Thor <author@example.com>
1424 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1425 test_cmp expect patch.head
1428 test_expect_success '--from omits redundant in-body header' '
1429 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1430 cat >expect <<-\EOF &&
1431 From: A U Thor <author@example.com>
1434 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1435 test_cmp expect patch.head
1438 test_expect_success 'with --force-in-body-from, redundant in-body from is kept' '
1439 git format-patch --force-in-body-from \
1440 -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1441 cat >expect <<-\EOF &&
1442 From: A U Thor <author@example.com>
1444 From: A U Thor <author@example.com>
1447 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1448 test_cmp expect patch.head
1451 test_expect_success 'format.forceInBodyFrom, equivalent to --force-in-body-from' '
1452 git -c format.forceInBodyFrom=yes format-patch \
1453 -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1454 cat >expect <<-\EOF &&
1455 From: A U Thor <author@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 'format.forceInBodyFrom, equivalent to --force-in-body-from' '
1465 git -c format.forceInBodyFrom=yes format-patch --no-force-in-body-from \
1466 -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1467 cat >expect <<-\EOF &&
1468 From: A U Thor <author@example.com>
1471 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1472 test_cmp expect patch.head
1475 test_expect_success 'in-body headers trigger content encoding' '
1476 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1477 test_when_finished "git reset --hard HEAD^" &&
1478 git format-patch -1 --stdout --from >patch &&
1479 cat >expect <<-\EOF &&
1480 From: C O Mitter <committer@example.com>
1481 Content-Type: text/plain; charset=UTF-8
1483 From: éxötìc <author@example.com>
1486 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" patch >patch.head &&
1487 test_cmp expect patch.head
1490 append_signoff()
1492 C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1493 git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1494 sed -n -e "1,/^---$/p" append_signoff.patch |
1495 grep -E -n "^Subject|Sign|^$"
1498 test_expect_success 'signoff: commit with no body' '
1499 append_signoff </dev/null >actual &&
1500 cat <<-\EOF | sed "s/EOL$//" >expect &&
1501 4:Subject: [PATCH] EOL
1503 9:Signed-off-by: C O Mitter <committer@example.com>
1505 test_cmp expect actual
1508 test_expect_success 'signoff: commit with only subject' '
1509 echo subject | append_signoff >actual &&
1510 cat >expect <<-\EOF &&
1511 4:Subject: [PATCH] subject
1513 9:Signed-off-by: C O Mitter <committer@example.com>
1515 test_cmp expect actual
1518 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1519 printf subject | append_signoff >actual &&
1520 cat >expect <<-\EOF &&
1521 4:Subject: [PATCH] subject
1523 9:Signed-off-by: C O Mitter <committer@example.com>
1525 test_cmp expect actual
1528 test_expect_success 'signoff: no existing signoffs' '
1529 append_signoff <<-\EOF >actual &&
1530 subject
1532 body
1534 cat >expect <<-\EOF &&
1535 4:Subject: [PATCH] subject
1538 11:Signed-off-by: C O Mitter <committer@example.com>
1540 test_cmp expect actual
1543 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1544 printf "subject\n\nbody" | append_signoff >actual &&
1545 cat >expect <<-\EOF &&
1546 4:Subject: [PATCH] subject
1549 11:Signed-off-by: C O Mitter <committer@example.com>
1551 test_cmp expect actual
1554 test_expect_success 'signoff: some random signoff' '
1555 append_signoff <<-\EOF >actual &&
1556 subject
1558 body
1560 Signed-off-by: my@house
1562 cat >expect <<-\EOF &&
1563 4:Subject: [PATCH] subject
1566 11:Signed-off-by: my@house
1567 12:Signed-off-by: C O Mitter <committer@example.com>
1569 test_cmp expect actual
1572 test_expect_success 'signoff: misc conforming footer elements' '
1573 append_signoff <<-\EOF >actual &&
1574 subject
1576 body
1578 Signed-off-by: my@house
1579 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1580 Tested-by: Some One <someone@example.com>
1581 Bug: 1234
1583 cat >expect <<-\EOF &&
1584 4:Subject: [PATCH] subject
1587 11:Signed-off-by: my@house
1588 15:Signed-off-by: C O Mitter <committer@example.com>
1590 test_cmp expect actual
1593 test_expect_success 'signoff: some random signoff-alike' '
1594 append_signoff <<-\EOF >actual &&
1595 subject
1597 body
1598 Fooled-by-me: my@house
1600 cat >expect <<-\EOF &&
1601 4:Subject: [PATCH] subject
1604 12:Signed-off-by: C O Mitter <committer@example.com>
1606 test_cmp expect actual
1609 test_expect_success 'signoff: not really a signoff' '
1610 append_signoff <<-\EOF >actual &&
1611 subject
1613 I want to mention about Signed-off-by: here.
1615 cat >expect <<-\EOF &&
1616 4:Subject: [PATCH] subject
1618 9:I want to mention about Signed-off-by: here.
1620 11:Signed-off-by: C O Mitter <committer@example.com>
1622 test_cmp expect actual
1625 test_expect_success 'signoff: not really a signoff (2)' '
1626 append_signoff <<-\EOF >actual &&
1627 subject
1629 My unfortunate
1630 Signed-off-by: example happens to be wrapped here.
1632 cat >expect <<-\EOF &&
1633 4:Subject: [PATCH] subject
1635 10:Signed-off-by: example happens to be wrapped here.
1636 11:Signed-off-by: C O Mitter <committer@example.com>
1638 test_cmp expect actual
1641 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1642 append_signoff <<-\EOF >actual &&
1643 subject
1645 Signed-off-by: my@house
1646 Signed-off-by: your@house
1648 A lot of houses.
1650 cat >expect <<-\EOF &&
1651 4:Subject: [PATCH] subject
1653 9:Signed-off-by: my@house
1654 10:Signed-off-by: your@house
1657 14:Signed-off-by: C O Mitter <committer@example.com>
1659 test_cmp expect actual
1662 test_expect_success 'signoff: the same signoff at the end' '
1663 append_signoff <<-\EOF >actual &&
1664 subject
1666 body
1668 Signed-off-by: C O Mitter <committer@example.com>
1670 cat >expect <<-\EOF &&
1671 4:Subject: [PATCH] subject
1674 11:Signed-off-by: C O Mitter <committer@example.com>
1676 test_cmp expect actual
1679 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1680 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1681 append_signoff >actual &&
1682 cat >expect <<-\EOF &&
1683 4:Subject: [PATCH] subject
1685 9:Signed-off-by: C O Mitter <committer@example.com>
1687 test_cmp expect actual
1690 test_expect_success 'signoff: the same signoff NOT at the end' '
1691 append_signoff <<-\EOF >actual &&
1692 subject
1694 body
1696 Signed-off-by: C O Mitter <committer@example.com>
1697 Signed-off-by: my@house
1699 cat >expect <<-\EOF &&
1700 4:Subject: [PATCH] subject
1703 11:Signed-off-by: C O Mitter <committer@example.com>
1704 12:Signed-off-by: my@house
1706 test_cmp expect actual
1709 test_expect_success 'signoff: tolerate garbage in conforming footer' '
1710 append_signoff <<-\EOF >actual &&
1711 subject
1713 body
1715 Tested-by: my@house
1716 Some Trash
1717 Signed-off-by: C O Mitter <committer@example.com>
1719 cat >expect <<-\EOF &&
1720 4:Subject: [PATCH] subject
1723 13:Signed-off-by: C O Mitter <committer@example.com>
1725 test_cmp expect actual
1728 test_expect_success 'signoff: respect trailer config' '
1729 append_signoff <<-\EOF >actual &&
1730 subject
1732 Myfooter: x
1733 Some Trash
1735 cat >expect <<-\EOF &&
1736 4:Subject: [PATCH] subject
1739 12:Signed-off-by: C O Mitter <committer@example.com>
1741 test_cmp expect actual &&
1743 test_config trailer.Myfooter.ifexists add &&
1744 append_signoff <<-\EOF >actual &&
1745 subject
1747 Myfooter: x
1748 Some Trash
1750 cat >expect <<-\EOF &&
1751 4:Subject: [PATCH] subject
1753 11:Signed-off-by: C O Mitter <committer@example.com>
1755 test_cmp expect actual
1758 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1759 append_signoff <<-\EOF >actual &&
1760 subject
1762 body
1764 Reviewed-id: Noone
1765 Tested-by: my@house
1766 Change-id: Ideadbeef
1767 Signed-off-by: C O Mitter <committer@example.com>
1768 Bug: 1234
1770 cat >expect <<-\EOF &&
1771 4:Subject: [PATCH] subject
1774 14:Signed-off-by: C O Mitter <committer@example.com>
1776 test_cmp expect actual
1779 test_expect_success 'format patch ignores color.ui' '
1780 test_unconfig color.ui &&
1781 git format-patch --stdout -1 >expect &&
1782 test_config color.ui always &&
1783 git format-patch --stdout -1 >actual &&
1784 test_cmp expect actual
1787 test_expect_success 'format patch respects diff.relative' '
1788 rm -rf subdir &&
1789 mkdir subdir &&
1790 echo other content >subdir/file2 &&
1791 git add subdir/file2 &&
1792 git commit -F msg &&
1793 test_unconfig diff.relative &&
1794 git format-patch --relative=subdir --stdout -1 >expect &&
1795 test_config diff.relative true &&
1796 git -C subdir format-patch --stdout -1 >actual &&
1797 test_cmp expect actual
1800 test_expect_success 'cover letter with invalid --cover-from-description and config' '
1801 test_config branch.rebuild-1.description "config subject
1803 body" &&
1804 test_must_fail git format-patch --cover-letter --cover-from-description garbage main &&
1805 test_config format.coverFromDescription garbage &&
1806 test_must_fail git format-patch --cover-letter main
1809 test_expect_success 'cover letter with format.coverFromDescription = default' '
1810 test_config branch.rebuild-1.description "config subject
1812 body" &&
1813 test_config format.coverFromDescription default &&
1814 git checkout rebuild-1 &&
1815 git format-patch --stdout --cover-letter main >actual &&
1816 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1817 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1818 grep "^config subject$" actual &&
1819 grep "^body$" actual
1822 test_expect_success 'cover letter with --cover-from-description default' '
1823 test_config branch.rebuild-1.description "config subject
1825 body" &&
1826 git checkout rebuild-1 &&
1827 git format-patch --stdout --cover-letter --cover-from-description default main >actual &&
1828 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1829 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1830 grep "^config subject$" actual &&
1831 grep "^body$" actual
1834 test_expect_success 'cover letter with format.coverFromDescription = none' '
1835 test_config branch.rebuild-1.description "config subject
1837 body" &&
1838 test_config format.coverFromDescription none &&
1839 git checkout rebuild-1 &&
1840 git format-patch --stdout --cover-letter main >actual &&
1841 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1842 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1843 ! grep "^config subject$" actual &&
1844 ! grep "^body$" actual
1847 test_expect_success 'cover letter with --cover-from-description none' '
1848 test_config branch.rebuild-1.description "config subject
1850 body" &&
1851 git checkout rebuild-1 &&
1852 git format-patch --stdout --cover-letter --cover-from-description none main >actual &&
1853 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1854 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1855 ! grep "^config subject$" actual &&
1856 ! grep "^body$" actual
1859 test_expect_success 'cover letter with format.coverFromDescription = message' '
1860 test_config branch.rebuild-1.description "config subject
1862 body" &&
1863 test_config format.coverFromDescription message &&
1864 git checkout rebuild-1 &&
1865 git format-patch --stdout --cover-letter main >actual &&
1866 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1867 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1868 grep "^config subject$" actual &&
1869 grep "^body$" actual
1872 test_expect_success 'cover letter with --cover-from-description message' '
1873 test_config branch.rebuild-1.description "config subject
1875 body" &&
1876 git checkout rebuild-1 &&
1877 git format-patch --stdout --cover-letter --cover-from-description message main >actual &&
1878 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1879 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1880 grep "^config subject$" actual &&
1881 grep "^body$" actual
1884 test_expect_success 'cover letter with format.coverFromDescription = subject' '
1885 test_config branch.rebuild-1.description "config subject
1887 body" &&
1888 test_config format.coverFromDescription subject &&
1889 git checkout rebuild-1 &&
1890 git format-patch --stdout --cover-letter main >actual &&
1891 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1892 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1893 ! grep "^config subject$" actual &&
1894 grep "^body$" actual
1897 test_expect_success 'cover letter with --cover-from-description subject' '
1898 test_config branch.rebuild-1.description "config subject
1900 body" &&
1901 git checkout rebuild-1 &&
1902 git format-patch --stdout --cover-letter --cover-from-description subject main >actual &&
1903 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1904 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1905 ! grep "^config subject$" actual &&
1906 grep "^body$" actual
1909 test_expect_success 'cover letter with --cover-from-description subject (UTF-8 subject line)' '
1910 test_config branch.rebuild-1.description "Café?
1912 body" &&
1913 git checkout rebuild-1 &&
1914 git format-patch --stdout --cover-letter --cover-from-description subject --encode-email-headers main >actual &&
1915 grep "^Subject: \[PATCH 0/2\] =?UTF-8?q?Caf=C3=A9=3F?=$" actual &&
1916 ! grep "Café" actual
1919 test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' '
1920 test_config branch.rebuild-1.description "config subject
1922 body" &&
1923 test_config format.coverFromDescription auto &&
1924 git checkout rebuild-1 &&
1925 git format-patch --stdout --cover-letter main >actual &&
1926 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1927 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1928 ! grep "^config subject$" actual &&
1929 grep "^body$" actual
1932 test_expect_success 'cover letter with --cover-from-description auto (short subject line)' '
1933 test_config branch.rebuild-1.description "config subject
1935 body" &&
1936 git checkout rebuild-1 &&
1937 git format-patch --stdout --cover-letter --cover-from-description auto main >actual &&
1938 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1939 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1940 ! grep "^config subject$" actual &&
1941 grep "^body$" actual
1944 test_expect_success 'cover letter with format.coverFromDescription = auto (long subject line)' '
1945 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
1947 body" &&
1948 test_config format.coverFromDescription auto &&
1949 git checkout rebuild-1 &&
1950 git format-patch --stdout --cover-letter main >actual &&
1951 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1952 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1953 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1954 grep "^body$" actual
1957 test_expect_success 'cover letter with --cover-from-description auto (long subject line)' '
1958 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
1960 body" &&
1961 git checkout rebuild-1 &&
1962 git format-patch --stdout --cover-letter --cover-from-description auto main >actual &&
1963 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1964 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1965 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1966 grep "^body$" actual
1969 test_expect_success 'cover letter with command-line --cover-from-description overrides config' '
1970 test_config branch.rebuild-1.description "config subject
1972 body" &&
1973 test_config format.coverFromDescription none &&
1974 git checkout rebuild-1 &&
1975 git format-patch --stdout --cover-letter --cover-from-description subject main >actual &&
1976 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1977 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1978 ! grep "^config subject$" actual &&
1979 grep "^body$" actual
1982 test_expect_success 'cover letter using branch description (1)' '
1983 git checkout rebuild-1 &&
1984 test_config branch.rebuild-1.description hello &&
1985 git format-patch --stdout --cover-letter main >actual &&
1986 grep hello actual
1989 test_expect_success 'cover letter using branch description (2)' '
1990 git checkout rebuild-1 &&
1991 test_config branch.rebuild-1.description hello &&
1992 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1993 grep hello actual
1996 test_expect_success 'cover letter using branch description (3)' '
1997 git checkout rebuild-1 &&
1998 test_config branch.rebuild-1.description hello &&
1999 git format-patch --stdout --cover-letter ^main rebuild-1 >actual &&
2000 grep hello actual
2003 test_expect_success 'cover letter using branch description (4)' '
2004 git checkout rebuild-1 &&
2005 test_config branch.rebuild-1.description hello &&
2006 git format-patch --stdout --cover-letter main.. >actual &&
2007 grep hello actual
2010 test_expect_success 'cover letter using branch description (5)' '
2011 git checkout rebuild-1 &&
2012 test_config branch.rebuild-1.description hello &&
2013 git format-patch --stdout --cover-letter -2 HEAD >actual &&
2014 grep hello actual
2017 test_expect_success 'cover letter using branch description (6)' '
2018 git checkout rebuild-1 &&
2019 test_config branch.rebuild-1.description hello &&
2020 git format-patch --stdout --cover-letter -2 >actual &&
2021 grep hello actual
2024 test_expect_success 'cover letter with --description-file' '
2025 test_when_finished "rm -f description.txt" &&
2026 cat >description.txt <<-\EOF &&
2027 subject from file
2029 body from file
2031 git checkout rebuild-1 &&
2032 git format-patch --stdout --cover-letter --cover-from-description auto \
2033 --description-file description.txt main >actual &&
2034 grep "^Subject: \[PATCH 0/2\] subject from file$" actual &&
2035 grep "^body from file$" actual
2038 test_expect_success 'cover letter with nothing' '
2039 git format-patch --stdout --cover-letter >actual &&
2040 test_line_count = 0 actual
2043 test_expect_success 'cover letter auto' '
2044 mkdir -p tmp &&
2045 test_when_finished "rm -rf tmp;
2046 git config --unset format.coverletter" &&
2048 git config format.coverletter auto &&
2049 git format-patch -o tmp -1 >list &&
2050 test_line_count = 1 list &&
2051 git format-patch -o tmp -2 >list &&
2052 test_line_count = 3 list
2055 test_expect_success 'cover letter auto user override' '
2056 mkdir -p tmp &&
2057 test_when_finished "rm -rf tmp;
2058 git config --unset format.coverletter" &&
2060 git config format.coverletter auto &&
2061 git format-patch -o tmp --cover-letter -1 >list &&
2062 test_line_count = 2 list &&
2063 git format-patch -o tmp --cover-letter -2 >list &&
2064 test_line_count = 3 list &&
2065 git format-patch -o tmp --no-cover-letter -1 >list &&
2066 test_line_count = 1 list &&
2067 git format-patch -o tmp --no-cover-letter -2 >list &&
2068 test_line_count = 2 list
2071 test_expect_success 'format-patch --zero-commit' '
2072 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
2073 grep "^From " patch2 | sort | uniq >actual &&
2074 echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
2075 test_cmp expect actual
2078 test_expect_success 'From line has expected format' '
2079 git format-patch --stdout v2..v1 >patch2 &&
2080 grep "^From " patch2 >from &&
2081 grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
2082 test_cmp from filtered
2085 test_expect_success 'format-patch -o with no leading directories' '
2086 rm -fr patches &&
2087 git format-patch -o patches main..side &&
2088 count=$(git rev-list --count main..side) &&
2089 ls patches >list &&
2090 test_line_count = $count list
2093 test_expect_success 'format-patch -o with leading existing directories' '
2094 rm -rf existing-dir &&
2095 mkdir existing-dir &&
2096 git format-patch -o existing-dir/patches main..side &&
2097 count=$(git rev-list --count main..side) &&
2098 ls existing-dir/patches >list &&
2099 test_line_count = $count list
2102 test_expect_success 'format-patch -o with leading non-existing directories' '
2103 rm -rf non-existing-dir &&
2104 git format-patch -o non-existing-dir/patches main..side &&
2105 count=$(git rev-list --count main..side) &&
2106 test_path_is_dir non-existing-dir &&
2107 ls non-existing-dir/patches >list &&
2108 test_line_count = $count list
2111 test_expect_success 'format-patch format.outputDirectory option' '
2112 test_config format.outputDirectory patches &&
2113 rm -fr patches &&
2114 git format-patch main..side &&
2115 count=$(git rev-list --count main..side) &&
2116 ls patches >list &&
2117 test_line_count = $count list
2120 test_expect_success 'format-patch -o overrides format.outputDirectory' '
2121 test_config format.outputDirectory patches &&
2122 rm -fr patches patchset &&
2123 git format-patch main..side -o patchset &&
2124 test_path_is_missing patches &&
2125 test_path_is_dir patchset
2128 test_expect_success 'format-patch forbids multiple outputs' '
2129 rm -fr outfile outdir &&
2130 test_must_fail \
2131 git format-patch --stdout --output-directory=outdir &&
2132 test_must_fail \
2133 git format-patch --stdout --output=outfile &&
2134 test_must_fail \
2135 git format-patch --output=outfile --output-directory=outdir
2138 test_expect_success 'configured outdir does not conflict with output options' '
2139 rm -fr outfile outdir &&
2140 test_config format.outputDirectory outdir &&
2141 git format-patch --stdout &&
2142 test_path_is_missing outdir &&
2143 git format-patch --output=outfile &&
2144 test_path_is_missing outdir
2147 test_expect_success 'format-patch --output' '
2148 rm -fr outfile &&
2149 git format-patch -3 --stdout HEAD >expect &&
2150 git format-patch -3 --output=outfile HEAD &&
2151 test_cmp expect outfile
2154 test_expect_success 'format-patch --cover-letter --output' '
2155 rm -fr outfile &&
2156 git format-patch --cover-letter -3 --stdout HEAD >expect &&
2157 git format-patch --cover-letter -3 --output=outfile HEAD &&
2158 test_cmp expect outfile
2161 test_expect_success 'format-patch --base' '
2162 git checkout patchid &&
2164 git format-patch --stdout --base=HEAD~3 -1 >patch &&
2165 tail -n 7 patch >actual1 &&
2167 git format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&
2168 tail -n 7 patch >actual2 &&
2170 echo >expect &&
2171 git rev-parse HEAD~3 >commit-id-base &&
2172 echo "base-commit: $(cat commit-id-base)" >>expect &&
2174 git show --patch HEAD~2 >patch &&
2175 git patch-id --stable <patch >patch.id.raw &&
2176 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2178 git show --patch HEAD~1 >patch &&
2179 git patch-id --stable <patch >patch.id.raw &&
2180 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2182 signature >>expect &&
2183 test_cmp expect actual1 &&
2184 test_cmp expect actual2 &&
2186 echo >fail &&
2187 echo "base-commit: $(cat commit-id-base)" >>fail &&
2189 git show --patch HEAD~2 >patch &&
2190 git patch-id --unstable <patch >patch.id.raw &&
2191 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2193 git show --patch HEAD~1 >patch &&
2194 git patch-id --unstable <patch >patch.id.raw &&
2195 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2197 signature >>fail &&
2198 ! test_cmp fail actual1 &&
2199 ! test_cmp fail actual2
2202 test_expect_success 'format-patch --base errors out when base commit is in revision list' '
2203 test_must_fail git format-patch --base=HEAD -2 &&
2204 test_must_fail git format-patch --base=HEAD~1 -2 &&
2205 git format-patch --stdout --base=HEAD~2 -2 >patch &&
2206 grep "^base-commit:" patch >actual &&
2207 git rev-parse HEAD~2 >commit-id-base &&
2208 echo "base-commit: $(cat commit-id-base)" >expect &&
2209 test_cmp expect actual
2212 test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
2213 # For history as below:
2215 # ---Q---P---Z---Y---*---X
2216 # \ /
2217 # ------------W
2219 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
2220 git checkout -b topic1 main &&
2221 git rev-parse HEAD >commit-id-base &&
2222 test_commit P &&
2223 git rev-parse HEAD >commit-id-P &&
2224 test_commit Z &&
2225 git rev-parse HEAD >commit-id-Z &&
2226 test_commit Y &&
2227 git checkout -b topic2 main &&
2228 test_commit W &&
2229 git merge topic1 &&
2230 test_commit X &&
2231 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
2232 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
2233 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
2234 grep "^base-commit:" patch >actual &&
2235 echo "base-commit: $(cat commit-id-base)" >expect &&
2236 test_cmp expect actual
2239 test_expect_success 'format-patch --base=auto' '
2240 git checkout -b upstream main &&
2241 git checkout -b local upstream &&
2242 git branch --set-upstream-to=upstream &&
2243 test_commit N1 &&
2244 test_commit N2 &&
2245 git format-patch --stdout --base=auto -2 >patch &&
2246 grep "^base-commit:" patch >actual &&
2247 git rev-parse upstream >commit-id-base &&
2248 echo "base-commit: $(cat commit-id-base)" >expect &&
2249 test_cmp expect actual
2252 test_expect_success 'format-patch errors out when history involves criss-cross' '
2253 # setup criss-cross history
2255 # B---M1---D
2256 # / \ /
2257 # A X
2258 # \ / \
2259 # C---M2---E
2261 git checkout main &&
2262 test_commit A &&
2263 git checkout -b xb main &&
2264 test_commit B &&
2265 git checkout -b xc main &&
2266 test_commit C &&
2267 git checkout -b xbc xb -- &&
2268 git merge xc &&
2269 git checkout -b xcb xc -- &&
2270 git branch --set-upstream-to=xbc &&
2271 git merge xb &&
2272 git checkout xbc &&
2273 test_commit D &&
2274 git checkout xcb &&
2275 test_commit E &&
2276 test_must_fail git format-patch --base=auto -1
2279 test_expect_success 'format-patch format.useAutoBase whenAble history involves criss-cross' '
2280 test_config format.useAutoBase whenAble &&
2281 git format-patch -1 >patch &&
2282 ! grep "^base-commit:" patch
2285 test_expect_success 'format-patch format.useAutoBase option' '
2286 git checkout local &&
2287 test_config format.useAutoBase true &&
2288 git format-patch --stdout -1 >patch &&
2289 grep "^base-commit:" patch >actual &&
2290 git rev-parse upstream >commit-id-base &&
2291 echo "base-commit: $(cat commit-id-base)" >expect &&
2292 test_cmp expect actual
2295 test_expect_success 'format-patch format.useAutoBase option with whenAble' '
2296 git checkout local &&
2297 test_config format.useAutoBase whenAble &&
2298 git format-patch --stdout -1 >patch &&
2299 grep "^base-commit:" patch >actual &&
2300 git rev-parse upstream >commit-id-base &&
2301 echo "base-commit: $(cat commit-id-base)" >expect &&
2302 test_cmp expect actual
2305 test_expect_success 'format-patch --base overrides format.useAutoBase' '
2306 test_config format.useAutoBase true &&
2307 git format-patch --stdout --base=HEAD~1 -1 >patch &&
2308 grep "^base-commit:" patch >actual &&
2309 git rev-parse HEAD~1 >commit-id-base &&
2310 echo "base-commit: $(cat commit-id-base)" >expect &&
2311 test_cmp expect actual
2314 test_expect_success 'format-patch --no-base overrides format.useAutoBase' '
2315 test_config format.useAutoBase true &&
2316 git format-patch --stdout --no-base -1 >patch &&
2317 ! grep "^base-commit:" patch
2320 test_expect_success 'format-patch --no-base overrides format.useAutoBase whenAble' '
2321 test_config format.useAutoBase whenAble &&
2322 git format-patch --stdout --no-base -1 >patch &&
2323 ! grep "^base-commit:" patch
2326 test_expect_success 'format-patch --base with --attach' '
2327 git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
2328 sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
2329 patch >actual &&
2330 test_write_lines 1 2 >expect &&
2331 test_cmp expect actual
2333 test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
2334 test_when_finished "rm -fr patches" &&
2335 git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
2336 ! grep -E "^--+mimemime" patches/0000*.patch &&
2337 grep -E "^--+mimemime$" patches/0001*.patch >output &&
2338 test_line_count = 2 output &&
2339 grep -E "^--+mimemime--$" patches/0001*.patch >output &&
2340 test_line_count = 1 output
2343 test_expect_success 'format-patch with format.attach' '
2344 test_when_finished "rm -fr patches" &&
2345 separator=attachment-separator &&
2346 test_config format.attach "$separator" &&
2347 filename=$(git format-patch -o patches -1) &&
2348 grep "^Content-Type: multipart/.*$separator" "$filename"
2351 test_expect_success 'format-patch with format.attach=disabled' '
2352 test_when_finished "rm -fr patches" &&
2353 separator=attachment-separator &&
2354 test_config_global format.attach "$separator" &&
2355 test_config format.attach "" &&
2356 filename=$(git format-patch -o patches -1) &&
2357 # The output should not even declare content type for text/plain.
2358 ! grep "^Content-Type: multipart/" "$filename"
2361 test_expect_success '-c format.mboxrd format-patch' '
2362 sp=" " &&
2363 cat >msg <<-INPUT_END &&
2364 mboxrd should escape the body
2366 From could trip up a loose mbox parser
2367 >From extra escape for reversibility
2368 >>From extra escape for reversibility 2
2369 from lower case not escaped
2370 Fromm bad speling not escaped
2371 From with leading space not escaped
2374 From
2375 From$sp
2376 From $sp
2377 From $sp
2378 INPUT_END
2380 cat >expect <<-INPUT_END &&
2381 >From could trip up a loose mbox parser
2382 >>From extra escape for reversibility
2383 >>>From extra escape for reversibility 2
2384 from lower case not escaped
2385 Fromm bad speling not escaped
2386 From with leading space not escaped
2389 From
2390 From
2391 From
2392 From
2393 INPUT_END
2395 C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
2396 git -c format.mboxrd format-patch --stdout -1 $C~1..$C >patch &&
2397 git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >compat &&
2398 test_cmp patch compat &&
2399 git grep -h --no-index -A11 \
2400 "^>From could trip up a loose mbox parser" patch >actual &&
2401 test_cmp expect actual
2404 test_expect_success 'interdiff: setup' '
2405 git checkout -b boop main &&
2406 test_commit fnorp blorp &&
2407 test_commit fleep blorp
2410 test_expect_success 'interdiff: cover-letter' '
2411 sed "y/q/ /" >expect <<-\EOF &&
2412 +fleep
2415 git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
2416 test_grep "^Interdiff:$" 0000-cover-letter.patch &&
2417 test_grep ! "^Interdiff:$" 0001-fleep.patch &&
2418 sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual &&
2419 test_cmp expect actual
2422 test_expect_success 'interdiff: reroll-count' '
2423 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2424 test_grep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2427 test_expect_success 'interdiff: reroll-count with a non-integer' '
2428 git format-patch --cover-letter --interdiff=boop~2 -v2.2 -1 boop &&
2429 test_grep "^Interdiff:$" v2.2-0000-cover-letter.patch
2432 test_expect_success 'interdiff: reroll-count with a integer' '
2433 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2434 test_grep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2437 test_expect_success 'interdiff: solo-patch' '
2438 cat >expect <<-\EOF &&
2439 +fleep
2442 git format-patch --interdiff=boop~2 -1 boop &&
2443 test_grep "^Interdiff:$" 0001-fleep.patch &&
2444 sed "1,/^ @@ /d; /^$/q" 0001-fleep.patch >actual &&
2445 test_cmp expect actual
2448 test_expect_success 'format-patch does not respect diff.noprefix' '
2449 git -c diff.noprefix format-patch -1 --stdout >actual &&
2450 grep "^--- a/blorp" actual
2453 test_expect_success 'format-patch respects format.noprefix' '
2454 git -c format.noprefix format-patch -1 --stdout >actual &&
2455 grep "^--- blorp" actual
2458 test_expect_success 'format-patch --default-prefix overrides format.noprefix' '
2459 git -c format.noprefix \
2460 format-patch -1 --default-prefix --stdout >actual &&
2461 grep "^--- a/blorp" actual
2464 test_done