treewide: be explicit about dependence on oid-array.h
[alt-git.git] / t / t4014-format-patch.sh
blobffc7c60680aeb97bae656c1cbece3db8381c7c17
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 cat >expect.in-reply-to <<EOF
475 Message-Id: <0>
476 In-Reply-To: <1>
477 References: <1>
479 Message-Id: <2>
480 In-Reply-To: <1>
481 References: <1>
483 Message-Id: <3>
484 In-Reply-To: <1>
485 References: <1>
488 test_expect_success 'thread in-reply-to' '
489 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
490 --thread main
493 cat >expect.cover-letter <<EOF
495 Message-Id: <0>
497 Message-Id: <1>
498 In-Reply-To: <0>
499 References: <0>
501 Message-Id: <2>
502 In-Reply-To: <0>
503 References: <0>
505 Message-Id: <3>
506 In-Reply-To: <0>
507 References: <0>
510 test_expect_success 'thread cover-letter' '
511 check_threading expect.cover-letter --cover-letter --thread main
514 cat >expect.cl-irt <<EOF
516 Message-Id: <0>
517 In-Reply-To: <1>
518 References: <1>
520 Message-Id: <2>
521 In-Reply-To: <0>
522 References: <1>
525 Message-Id: <3>
526 In-Reply-To: <0>
527 References: <1>
530 Message-Id: <4>
531 In-Reply-To: <0>
532 References: <1>
536 test_expect_success 'thread cover-letter in-reply-to' '
537 check_threading expect.cl-irt --cover-letter \
538 --in-reply-to="<test.message>" --thread main
541 test_expect_success 'thread explicit shallow' '
542 check_threading expect.cl-irt --cover-letter \
543 --in-reply-to="<test.message>" --thread=shallow main
546 cat >expect.deep <<EOF
548 Message-Id: <0>
550 Message-Id: <1>
551 In-Reply-To: <0>
552 References: <0>
554 Message-Id: <2>
555 In-Reply-To: <1>
556 References: <0>
560 test_expect_success 'thread deep' '
561 check_threading expect.deep --thread=deep main
564 cat >expect.deep-irt <<EOF
566 Message-Id: <0>
567 In-Reply-To: <1>
568 References: <1>
570 Message-Id: <2>
571 In-Reply-To: <0>
572 References: <1>
575 Message-Id: <3>
576 In-Reply-To: <2>
577 References: <1>
582 test_expect_success 'thread deep in-reply-to' '
583 check_threading expect.deep-irt --thread=deep \
584 --in-reply-to="<test.message>" main
587 cat >expect.deep-cl <<EOF
589 Message-Id: <0>
591 Message-Id: <1>
592 In-Reply-To: <0>
593 References: <0>
595 Message-Id: <2>
596 In-Reply-To: <1>
597 References: <0>
600 Message-Id: <3>
601 In-Reply-To: <2>
602 References: <0>
607 test_expect_success 'thread deep cover-letter' '
608 check_threading expect.deep-cl --cover-letter --thread=deep main
611 cat >expect.deep-cl-irt <<EOF
613 Message-Id: <0>
614 In-Reply-To: <1>
615 References: <1>
617 Message-Id: <2>
618 In-Reply-To: <0>
619 References: <1>
622 Message-Id: <3>
623 In-Reply-To: <2>
624 References: <1>
628 Message-Id: <4>
629 In-Reply-To: <3>
630 References: <1>
636 test_expect_success 'thread deep cover-letter in-reply-to' '
637 check_threading expect.deep-cl-irt --cover-letter \
638 --in-reply-to="<test.message>" --thread=deep main
641 test_expect_success 'thread via config' '
642 test_config format.thread true &&
643 check_threading expect.thread main
646 test_expect_success 'thread deep via config' '
647 test_config format.thread deep &&
648 check_threading expect.deep main
651 test_expect_success 'thread config + override' '
652 test_config format.thread deep &&
653 check_threading expect.thread --thread main
656 test_expect_success 'thread config + --no-thread' '
657 test_config format.thread deep &&
658 check_threading expect.no-threading --no-thread main
661 test_expect_success 'excessive subject' '
662 rm -rf patches/ &&
663 git checkout side &&
664 before=$(git hash-object file) &&
665 before=$(git rev-parse --short $before) &&
666 test_write_lines 5 6 1 2 3 A 4 B C 7 8 9 10 D E F >>file &&
667 after=$(git hash-object file) &&
668 after=$(git rev-parse --short $after) &&
669 git update-index file &&
670 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." &&
671 git format-patch -o patches/ main..side &&
672 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
675 test_expect_success 'failure to write cover-letter aborts gracefully' '
676 test_when_finished "rmdir 0000-cover-letter.patch" &&
677 mkdir 0000-cover-letter.patch &&
678 test_must_fail git format-patch --no-renames --cover-letter -1
681 test_expect_success 'cover-letter inherits diff options' '
682 git mv file foo &&
683 git commit -m foo &&
684 git format-patch --no-renames --cover-letter -1 &&
685 check_patch 0000-cover-letter.patch &&
686 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
687 git format-patch --cover-letter -1 -M &&
688 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
691 cat >expect <<EOF
692 This is an excessively long subject line for a message due to the
693 habit some projects have of not having a short, one-line subject at
694 the start of the commit message, but rather sticking a whole
695 paragraph right at the start as the only thing in the commit
696 message. It had better not become the filename for the patch.
701 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
702 git format-patch --cover-letter -2 &&
703 sed -e "1,/A U Thor/d" -e "/^\$/q" 0000-cover-letter.patch >output &&
704 test_cmp expect output
707 cat >expect <<EOF
708 index $before..$after 100644
709 --- a/file
710 +++ b/file
711 @@ -13,4 +13,20 @@ C
719 test_expect_success 'format-patch respects -U' '
720 git format-patch -U4 -2 &&
721 sed -e "1,/^diff/d" -e "/^+5/q" \
722 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
723 >output &&
724 test_cmp expect output
727 cat >expect <<EOF
729 diff --git a/file b/file
730 index $before..$after 100644
731 --- a/file
732 +++ b/file
733 @@ -14,3 +14,19 @@ C
740 test_expect_success 'format-patch -p suppresses stat' '
741 git format-patch -p -2 &&
742 sed -e "1,/^\$/d" -e "/^+5/q" 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&
743 test_cmp expect output
746 test_expect_success 'format-patch from a subdirectory (1)' '
747 filename=$(
748 rm -rf sub &&
749 mkdir -p sub/dir &&
750 cd sub/dir &&
751 git format-patch -1
752 ) &&
753 case "$filename" in
755 ;; # ok
757 echo "Oops? $filename"
758 false
760 esac &&
761 test -f "$filename"
764 test_expect_success 'format-patch from a subdirectory (2)' '
765 filename=$(
766 rm -rf sub &&
767 mkdir -p sub/dir &&
768 cd sub/dir &&
769 git format-patch -1 -o ..
770 ) &&
771 case "$filename" in
772 ../0*)
773 ;; # ok
775 echo "Oops? $filename"
776 false
778 esac &&
779 basename=$(expr "$filename" : ".*/\(.*\)") &&
780 test -f "sub/$basename"
783 test_expect_success 'format-patch from a subdirectory (3)' '
784 rm -f 0* &&
785 filename=$(
786 rm -rf sub &&
787 mkdir -p sub/dir &&
788 cd sub/dir &&
789 git format-patch -1 -o "$TRASH_DIRECTORY"
790 ) &&
791 basename=$(expr "$filename" : ".*/\(.*\)") &&
792 test -f "$basename"
795 test_expect_success 'format-patch --in-reply-to' '
796 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" >patch8 &&
797 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
798 grep "^References: <baz@foo.bar>" patch8
801 test_expect_success 'format-patch --signoff' '
802 git format-patch -1 --signoff --stdout >out &&
803 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
806 test_expect_success 'format-patch --notes --signoff' '
807 git notes --ref test add -m "test message" HEAD &&
808 git format-patch -1 --signoff --stdout --notes=test >out &&
809 # Three dashes must come after S-o-b
810 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
811 sed "1,/^Signed-off-by: /d" out | grep "test message" &&
812 # Notes message must come after three dashes
813 ! sed "/^---$/q" out | grep "test message" &&
814 sed "1,/^---$/d" out | grep "test message"
817 test_expect_success 'format-patch notes output control' '
818 git notes add -m "notes config message" HEAD &&
819 test_when_finished git notes remove HEAD &&
821 git format-patch -1 --stdout >out &&
822 ! grep "notes config message" out &&
823 git format-patch -1 --stdout --notes >out &&
824 grep "notes config message" out &&
825 git format-patch -1 --stdout --no-notes >out &&
826 ! grep "notes config message" out &&
827 git format-patch -1 --stdout --notes --no-notes >out &&
828 ! grep "notes config message" out &&
829 git format-patch -1 --stdout --no-notes --notes >out &&
830 grep "notes config message" out &&
832 test_config format.notes true &&
833 git format-patch -1 --stdout >out &&
834 grep "notes config message" out &&
835 git format-patch -1 --stdout --notes >out &&
836 grep "notes config message" out &&
837 git format-patch -1 --stdout --no-notes >out &&
838 ! grep "notes config message" out &&
839 git format-patch -1 --stdout --notes --no-notes >out &&
840 ! grep "notes config message" out &&
841 git format-patch -1 --stdout --no-notes --notes >out &&
842 grep "notes config message" out
845 test_expect_success 'format-patch with multiple notes refs' '
846 git notes --ref note1 add -m "this is note 1" HEAD &&
847 test_when_finished git notes --ref note1 remove HEAD &&
848 git notes --ref note2 add -m "this is note 2" HEAD &&
849 test_when_finished git notes --ref note2 remove HEAD &&
851 git format-patch -1 --stdout >out &&
852 ! grep "this is note 1" out &&
853 ! grep "this is note 2" out &&
854 git format-patch -1 --stdout --notes=note1 >out &&
855 grep "this is note 1" out &&
856 ! grep "this is note 2" out &&
857 git format-patch -1 --stdout --notes=note2 >out &&
858 ! grep "this is note 1" out &&
859 grep "this is note 2" out &&
860 git format-patch -1 --stdout --notes=note1 --notes=note2 >out &&
861 grep "this is note 1" out &&
862 grep "this is note 2" out &&
864 test_config format.notes note1 &&
865 git format-patch -1 --stdout >out &&
866 grep "this is note 1" out &&
867 ! grep "this is note 2" out &&
868 git format-patch -1 --stdout --no-notes >out &&
869 ! grep "this is note 1" out &&
870 ! grep "this is note 2" out &&
871 git format-patch -1 --stdout --notes=note2 >out &&
872 grep "this is note 1" out &&
873 grep "this is note 2" out &&
874 git format-patch -1 --stdout --no-notes --notes=note2 >out &&
875 ! grep "this is note 1" out &&
876 grep "this is note 2" out &&
878 git config --add format.notes note2 &&
879 git format-patch -1 --stdout >out &&
880 grep "this is note 1" out &&
881 grep "this is note 2" out &&
882 git format-patch -1 --stdout --no-notes >out &&
883 ! grep "this is note 1" out &&
884 ! grep "this is note 2" out
887 test_expect_success 'format-patch with multiple notes refs in config' '
888 test_when_finished "test_unconfig format.notes" &&
890 git notes --ref note1 add -m "this is note 1" HEAD &&
891 test_when_finished git notes --ref note1 remove HEAD &&
892 git notes --ref note2 add -m "this is note 2" HEAD &&
893 test_when_finished git notes --ref note2 remove HEAD &&
895 git config format.notes note1 &&
896 git format-patch -1 --stdout >out &&
897 grep "this is note 1" out &&
898 ! grep "this is note 2" out &&
899 git config format.notes note2 &&
900 git format-patch -1 --stdout >out &&
901 ! grep "this is note 1" out &&
902 grep "this is note 2" out &&
903 git config --add format.notes note1 &&
904 git format-patch -1 --stdout >out &&
905 grep "this is note 1" out &&
906 grep "this is note 2" out &&
908 git config --replace-all format.notes note1 &&
909 git config --add format.notes false &&
910 git format-patch -1 --stdout >out &&
911 ! grep "this is note 1" out &&
912 ! grep "this is note 2" out &&
913 git config --add format.notes note2 &&
914 git format-patch -1 --stdout >out &&
915 ! grep "this is note 1" out &&
916 grep "this is note 2" out
919 echo "fatal: --name-only does not make sense" >expect.name-only
920 echo "fatal: --name-status does not make sense" >expect.name-status
921 echo "fatal: --check does not make sense" >expect.check
923 test_expect_success 'options no longer allowed for format-patch' '
924 test_must_fail git format-patch --name-only 2>output &&
925 test_cmp expect.name-only output &&
926 test_must_fail git format-patch --name-status 2>output &&
927 test_cmp expect.name-status output &&
928 test_must_fail git format-patch --check 2>output &&
929 test_cmp expect.check output
932 test_expect_success 'format-patch --numstat should produce a patch' '
933 git format-patch --numstat --stdout main..side >output &&
934 grep "^diff --git a/" output >diff &&
935 test_line_count = 5 diff
938 test_expect_success 'format-patch -- <path>' '
939 rm -f *.patch &&
940 git checkout -b pathspec main &&
942 echo file_a 1 >file_a &&
943 echo file_b 1 >file_b &&
944 git add file_a file_b &&
945 git commit -m pathspec_initial &&
947 echo file_a 2 >>file_a &&
948 git add file_a &&
949 git commit -m pathspec_a &&
951 echo file_b 2 >>file_b &&
952 git add file_b &&
953 git commit -m pathspec_b &&
955 echo file_a 3 >>file_a &&
956 echo file_b 3 >>file_b &&
957 git add file_a file_b &&
958 git commit -m pathspec_ab &&
960 cat >expect <<-\EOF &&
961 0001-pathspec_initial.patch
962 0002-pathspec_a.patch
963 0003-pathspec_ab.patch
966 git format-patch main..pathspec -- file_a >output &&
967 test_cmp expect output &&
968 ! grep file_b *.patch
971 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
972 git checkout side &&
973 git format-patch --ignore-if-in-upstream HEAD
976 test_expect_success 'get git version' '
977 git_version=$(git --version) &&
978 git_version=${git_version##* }
981 signature() {
982 printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
985 test_expect_success 'format-patch default signature' '
986 git format-patch --stdout -1 >patch &&
987 tail -n 3 patch >output &&
988 signature >expect &&
989 test_cmp expect output
992 test_expect_success 'format-patch --signature' '
993 git format-patch --stdout --signature="my sig" -1 >patch &&
994 tail -n 3 patch >output &&
995 signature "my sig" >expect &&
996 test_cmp expect output
999 test_expect_success 'format-patch with format.signature config' '
1000 git config format.signature "config sig" &&
1001 git format-patch --stdout -1 >output &&
1002 grep "config sig" output
1005 test_expect_success 'format-patch --signature overrides format.signature' '
1006 git config format.signature "config sig" &&
1007 git format-patch --stdout --signature="overrides" -1 >output &&
1008 ! grep "config sig" output &&
1009 grep "overrides" output
1012 test_expect_success 'format-patch --no-signature ignores format.signature' '
1013 git config format.signature "config sig" &&
1014 git format-patch --stdout --signature="my sig" --no-signature \
1015 -1 >output &&
1016 check_patch output &&
1017 ! grep "config sig" output &&
1018 ! grep "my sig" output &&
1019 ! grep "^-- \$" output
1022 test_expect_success 'format-patch --signature --cover-letter' '
1023 git config --unset-all format.signature &&
1024 git format-patch --stdout --signature="my sig" --cover-letter \
1025 -1 >output &&
1026 grep "my sig" output >sig &&
1027 test_line_count = 2 sig
1030 test_expect_success 'format.signature="" suppresses signatures' '
1031 git config format.signature "" &&
1032 git format-patch --stdout -1 >output &&
1033 check_patch output &&
1034 ! grep "^-- \$" output
1037 test_expect_success 'format-patch --no-signature suppresses signatures' '
1038 git config --unset-all format.signature &&
1039 git format-patch --stdout --no-signature -1 >output &&
1040 check_patch output &&
1041 ! grep "^-- \$" output
1044 test_expect_success 'format-patch --signature="" suppresses signatures' '
1045 git format-patch --stdout --signature="" -1 >output &&
1046 check_patch output &&
1047 ! grep "^-- \$" output
1050 test_expect_success 'prepare mail-signature input' '
1051 cat >mail-signature <<-\EOF
1053 Test User <test.email@kernel.org>
1054 http://git.kernel.org/cgit/git/git.git
1056 git.kernel.org/?p=git/git.git;a=summary
1061 test_expect_success '--signature-file=file works' '
1062 git format-patch --stdout --signature-file=mail-signature -1 >output &&
1063 check_patch output &&
1064 sed -e "1,/^-- \$/d" output >actual &&
1066 cat mail-signature && echo
1067 } >expect &&
1068 test_cmp expect actual
1071 test_expect_success 'format.signaturefile works' '
1072 test_config format.signaturefile mail-signature &&
1073 git format-patch --stdout -1 >output &&
1074 check_patch output &&
1075 sed -e "1,/^-- \$/d" output >actual &&
1077 cat mail-signature && echo
1078 } >expect &&
1079 test_cmp expect actual
1082 test_expect_success '--no-signature suppresses format.signaturefile ' '
1083 test_config format.signaturefile mail-signature &&
1084 git format-patch --stdout --no-signature -1 >output &&
1085 check_patch output &&
1086 ! grep "^-- \$" output
1089 test_expect_success '--signature-file overrides format.signaturefile' '
1090 cat >other-mail-signature <<-\EOF &&
1091 Use this other signature instead of mail-signature.
1093 test_config format.signaturefile mail-signature &&
1094 git format-patch --stdout \
1095 --signature-file=other-mail-signature -1 >output &&
1096 check_patch output &&
1097 sed -e "1,/^-- \$/d" output >actual &&
1099 cat other-mail-signature && echo
1100 } >expect &&
1101 test_cmp expect actual
1104 test_expect_success '--signature overrides format.signaturefile' '
1105 test_config format.signaturefile mail-signature &&
1106 git format-patch --stdout --signature="my sig" -1 >output &&
1107 check_patch output &&
1108 grep "my sig" output
1111 test_expect_success TTY 'format-patch --stdout paginates' '
1112 rm -f pager_used &&
1113 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
1114 test_path_is_file pager_used
1117 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
1118 rm -f pager_used &&
1119 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
1120 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
1121 test_path_is_missing pager_used &&
1122 test_path_is_missing .git/pager_used
1125 test_expect_success 'format-patch handles multi-line subjects' '
1126 rm -rf patches/ &&
1127 echo content >>file &&
1128 test_write_lines one two three >msg &&
1129 git add file &&
1130 git commit -F msg &&
1131 git format-patch -o patches -1 &&
1132 grep ^Subject: patches/0001-one.patch >actual &&
1133 echo "Subject: [PATCH] one two three" >expect &&
1134 test_cmp expect actual
1137 test_expect_success 'format-patch handles multi-line encoded subjects' '
1138 rm -rf patches/ &&
1139 echo content >>file &&
1140 test_write_lines en två tre >msg &&
1141 git add file &&
1142 git commit -F msg &&
1143 git format-patch -o patches -1 &&
1144 grep ^Subject: patches/0001-en.patch >actual &&
1145 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
1146 test_cmp expect actual
1149 M8="foo bar "
1150 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1151 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1152 cat >expect <<'EOF'
1153 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1154 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1155 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1156 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1157 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1158 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1159 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1161 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
1162 echo content >>file &&
1163 git add file &&
1164 git commit -m "$M512" &&
1165 git format-patch --stdout -1 >patch &&
1166 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1167 test_cmp expect subject
1170 M8="föö bar "
1171 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1172 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1173 cat >expect <<'EOF'
1174 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1175 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1176 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1177 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1178 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1179 =?UTF-8?q?=C3=B6=20bar=20f=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?=
1199 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
1200 rm -rf patches/ &&
1201 echo content >>file &&
1202 git add file &&
1203 git commit -m "$M512" &&
1204 git format-patch --stdout -1 >patch &&
1205 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1206 test_cmp expect subject
1209 check_author() {
1210 echo content >>file &&
1211 git add file &&
1212 GIT_AUTHOR_NAME=$1 git commit -m author-check &&
1213 git format-patch --stdout -1 >patch &&
1214 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1215 test_cmp expect actual
1218 cat >expect <<'EOF'
1219 From: "Foo B. Bar" <author@example.com>
1221 test_expect_success 'format-patch quotes dot in from-headers' '
1222 check_author "Foo B. Bar"
1225 cat >expect <<'EOF'
1226 From: "Foo \"The Baz\" Bar" <author@example.com>
1228 test_expect_success 'format-patch quotes double-quote in from-headers' '
1229 check_author "Foo \"The Baz\" Bar"
1232 cat >expect <<'EOF'
1233 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1235 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1236 check_author "Föo Bar"
1239 cat >expect <<'EOF'
1240 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1242 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1243 check_author "Föo B. Bar"
1246 cat >expect <<EOF
1247 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1248 <author@example.com>
1250 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1251 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1254 cat >expect <<'EOF'
1255 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1256 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1257 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1259 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1260 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"
1263 cat >expect <<'EOF'
1264 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1265 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1266 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1268 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1269 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"
1272 cat >expect <<'EOF'
1273 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1274 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1275 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1276 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1277 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1279 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1280 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"
1283 cat >expect <<'EOF'
1284 From: Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1285 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1286 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1288 test_expect_success 'format-patch wraps extremely long from-header (non-ASCII without Q-encoding)' '
1289 echo content >>file &&
1290 git add file &&
1291 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" \
1292 git commit -m author-check &&
1293 git format-patch --no-encode-email-headers --stdout -1 >patch &&
1294 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1295 test_cmp expect actual
1298 cat >expect <<'EOF'
1299 Subject: [PATCH] Foö
1301 test_expect_success 'subject lines are unencoded with --no-encode-email-headers' '
1302 echo content >>file &&
1303 git add file &&
1304 git commit -m "Foö" &&
1305 git format-patch --no-encode-email-headers -1 --stdout >patch &&
1306 grep ^Subject: patch >actual &&
1307 test_cmp expect actual
1310 cat >expect <<'EOF'
1311 Subject: [PATCH] Foö
1313 test_expect_success 'subject lines are unencoded with format.encodeEmailHeaders=false' '
1314 echo content >>file &&
1315 git add file &&
1316 git commit -m "Foö" &&
1317 git config format.encodeEmailHeaders false &&
1318 git format-patch -1 --stdout >patch &&
1319 grep ^Subject: patch >actual &&
1320 test_cmp expect actual
1323 cat >expect <<'EOF'
1324 Subject: [PATCH] =?UTF-8?q?Fo=C3=B6?=
1326 test_expect_success '--encode-email-headers overrides format.encodeEmailHeaders' '
1327 echo content >>file &&
1328 git add file &&
1329 git commit -m "Foö" &&
1330 git config format.encodeEmailHeaders false &&
1331 git format-patch --encode-email-headers -1 --stdout >patch &&
1332 grep ^Subject: patch >actual &&
1333 test_cmp expect actual
1336 cat >expect <<'EOF'
1337 Subject: header with . in it
1339 test_expect_success 'subject lines do not have 822 atom-quoting' '
1340 echo content >>file &&
1341 git add file &&
1342 git commit -m "header with . in it" &&
1343 git format-patch -k -1 --stdout >patch &&
1344 grep ^Subject: patch >actual &&
1345 test_cmp expect actual
1348 cat >expect <<'EOF'
1349 Subject: [PREFIX 1/1] header with . in it
1351 test_expect_success 'subject prefixes have space prepended' '
1352 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1353 grep ^Subject: patch >actual &&
1354 test_cmp expect actual
1357 cat >expect <<'EOF'
1358 Subject: [1/1] header with . in it
1360 test_expect_success 'empty subject prefix does not have extra space' '
1361 git format-patch -n -1 --stdout --subject-prefix= >patch &&
1362 grep ^Subject: patch >actual &&
1363 test_cmp expect actual
1366 test_expect_success '--rfc' '
1367 cat >expect <<-\EOF &&
1368 Subject: [RFC PATCH 1/1] header with . in it
1370 git format-patch -n -1 --stdout --rfc >patch &&
1371 grep ^Subject: patch >actual &&
1372 test_cmp expect actual
1375 test_expect_success '--from=ident notices bogus ident' '
1376 test_must_fail git format-patch -1 --stdout --from=foo >patch
1379 test_expect_success '--from=ident replaces author' '
1380 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1381 cat >expect <<-\EOF &&
1382 From: Me <me@example.com>
1384 From: A U Thor <author@example.com>
1387 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1388 test_cmp expect patch.head
1391 test_expect_success '--from uses committer ident' '
1392 git format-patch -1 --stdout --from >patch &&
1393 cat >expect <<-\EOF &&
1394 From: C O Mitter <committer@example.com>
1396 From: A U Thor <author@example.com>
1399 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1400 test_cmp expect patch.head
1403 test_expect_success '--from omits redundant in-body header' '
1404 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1405 cat >expect <<-\EOF &&
1406 From: A U Thor <author@example.com>
1409 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1410 test_cmp expect patch.head
1413 test_expect_success 'with --force-in-body-from, redundant in-body from is kept' '
1414 git format-patch --force-in-body-from \
1415 -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1416 cat >expect <<-\EOF &&
1417 From: A U Thor <author@example.com>
1419 From: A U Thor <author@example.com>
1422 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1423 test_cmp expect patch.head
1426 test_expect_success 'format.forceInBodyFrom, equivalent to --force-in-body-from' '
1427 git -c format.forceInBodyFrom=yes format-patch \
1428 -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1429 cat >expect <<-\EOF &&
1430 From: A U Thor <author@example.com>
1432 From: A U Thor <author@example.com>
1435 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1436 test_cmp expect patch.head
1439 test_expect_success 'format.forceInBodyFrom, equivalent to --force-in-body-from' '
1440 git -c format.forceInBodyFrom=yes format-patch --no-force-in-body-from \
1441 -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1442 cat >expect <<-\EOF &&
1443 From: A U Thor <author@example.com>
1446 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1447 test_cmp expect patch.head
1450 test_expect_success 'in-body headers trigger content encoding' '
1451 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1452 test_when_finished "git reset --hard HEAD^" &&
1453 git format-patch -1 --stdout --from >patch &&
1454 cat >expect <<-\EOF &&
1455 From: C O Mitter <committer@example.com>
1456 Content-Type: text/plain; charset=UTF-8
1458 From: éxötìc <author@example.com>
1461 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" patch >patch.head &&
1462 test_cmp expect patch.head
1465 append_signoff()
1467 C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1468 git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1469 sed -n -e "1,/^---$/p" append_signoff.patch |
1470 grep -E -n "^Subject|Sign|^$"
1473 test_expect_success 'signoff: commit with no body' '
1474 append_signoff </dev/null >actual &&
1475 cat <<-\EOF | sed "s/EOL$//" >expect &&
1476 4:Subject: [PATCH] EOL
1478 9:Signed-off-by: C O Mitter <committer@example.com>
1480 test_cmp expect actual
1483 test_expect_success 'signoff: commit with only subject' '
1484 echo subject | append_signoff >actual &&
1485 cat >expect <<-\EOF &&
1486 4:Subject: [PATCH] subject
1488 9:Signed-off-by: C O Mitter <committer@example.com>
1490 test_cmp expect actual
1493 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1494 printf subject | append_signoff >actual &&
1495 cat >expect <<-\EOF &&
1496 4:Subject: [PATCH] subject
1498 9:Signed-off-by: C O Mitter <committer@example.com>
1500 test_cmp expect actual
1503 test_expect_success 'signoff: no existing signoffs' '
1504 append_signoff <<-\EOF >actual &&
1505 subject
1507 body
1509 cat >expect <<-\EOF &&
1510 4:Subject: [PATCH] subject
1513 11:Signed-off-by: C O Mitter <committer@example.com>
1515 test_cmp expect actual
1518 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1519 printf "subject\n\nbody" | append_signoff >actual &&
1520 cat >expect <<-\EOF &&
1521 4:Subject: [PATCH] subject
1524 11:Signed-off-by: C O Mitter <committer@example.com>
1526 test_cmp expect actual
1529 test_expect_success 'signoff: some random signoff' '
1530 append_signoff <<-\EOF >actual &&
1531 subject
1533 body
1535 Signed-off-by: my@house
1537 cat >expect <<-\EOF &&
1538 4:Subject: [PATCH] subject
1541 11:Signed-off-by: my@house
1542 12:Signed-off-by: C O Mitter <committer@example.com>
1544 test_cmp expect actual
1547 test_expect_success 'signoff: misc conforming footer elements' '
1548 append_signoff <<-\EOF >actual &&
1549 subject
1551 body
1553 Signed-off-by: my@house
1554 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1555 Tested-by: Some One <someone@example.com>
1556 Bug: 1234
1558 cat >expect <<-\EOF &&
1559 4:Subject: [PATCH] subject
1562 11:Signed-off-by: my@house
1563 15:Signed-off-by: C O Mitter <committer@example.com>
1565 test_cmp expect actual
1568 test_expect_success 'signoff: some random signoff-alike' '
1569 append_signoff <<-\EOF >actual &&
1570 subject
1572 body
1573 Fooled-by-me: my@house
1575 cat >expect <<-\EOF &&
1576 4:Subject: [PATCH] subject
1579 12:Signed-off-by: C O Mitter <committer@example.com>
1581 test_cmp expect actual
1584 test_expect_success 'signoff: not really a signoff' '
1585 append_signoff <<-\EOF >actual &&
1586 subject
1588 I want to mention about Signed-off-by: here.
1590 cat >expect <<-\EOF &&
1591 4:Subject: [PATCH] subject
1593 9:I want to mention about Signed-off-by: here.
1595 11:Signed-off-by: C O Mitter <committer@example.com>
1597 test_cmp expect actual
1600 test_expect_success 'signoff: not really a signoff (2)' '
1601 append_signoff <<-\EOF >actual &&
1602 subject
1604 My unfortunate
1605 Signed-off-by: example happens to be wrapped here.
1607 cat >expect <<-\EOF &&
1608 4:Subject: [PATCH] subject
1610 10:Signed-off-by: example happens to be wrapped here.
1611 11:Signed-off-by: C O Mitter <committer@example.com>
1613 test_cmp expect actual
1616 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1617 append_signoff <<-\EOF >actual &&
1618 subject
1620 Signed-off-by: my@house
1621 Signed-off-by: your@house
1623 A lot of houses.
1625 cat >expect <<-\EOF &&
1626 4:Subject: [PATCH] subject
1628 9:Signed-off-by: my@house
1629 10:Signed-off-by: your@house
1632 14:Signed-off-by: C O Mitter <committer@example.com>
1634 test_cmp expect actual
1637 test_expect_success 'signoff: the same signoff at the end' '
1638 append_signoff <<-\EOF >actual &&
1639 subject
1641 body
1643 Signed-off-by: C O Mitter <committer@example.com>
1645 cat >expect <<-\EOF &&
1646 4:Subject: [PATCH] subject
1649 11:Signed-off-by: C O Mitter <committer@example.com>
1651 test_cmp expect actual
1654 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1655 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1656 append_signoff >actual &&
1657 cat >expect <<-\EOF &&
1658 4:Subject: [PATCH] subject
1660 9:Signed-off-by: C O Mitter <committer@example.com>
1662 test_cmp expect actual
1665 test_expect_success 'signoff: the same signoff NOT at the end' '
1666 append_signoff <<-\EOF >actual &&
1667 subject
1669 body
1671 Signed-off-by: C O Mitter <committer@example.com>
1672 Signed-off-by: my@house
1674 cat >expect <<-\EOF &&
1675 4:Subject: [PATCH] subject
1678 11:Signed-off-by: C O Mitter <committer@example.com>
1679 12:Signed-off-by: my@house
1681 test_cmp expect actual
1684 test_expect_success 'signoff: tolerate garbage in conforming footer' '
1685 append_signoff <<-\EOF >actual &&
1686 subject
1688 body
1690 Tested-by: my@house
1691 Some Trash
1692 Signed-off-by: C O Mitter <committer@example.com>
1694 cat >expect <<-\EOF &&
1695 4:Subject: [PATCH] subject
1698 13:Signed-off-by: C O Mitter <committer@example.com>
1700 test_cmp expect actual
1703 test_expect_success 'signoff: respect trailer config' '
1704 append_signoff <<-\EOF >actual &&
1705 subject
1707 Myfooter: x
1708 Some Trash
1710 cat >expect <<-\EOF &&
1711 4:Subject: [PATCH] subject
1714 12:Signed-off-by: C O Mitter <committer@example.com>
1716 test_cmp expect actual &&
1718 test_config trailer.Myfooter.ifexists add &&
1719 append_signoff <<-\EOF >actual &&
1720 subject
1722 Myfooter: x
1723 Some Trash
1725 cat >expect <<-\EOF &&
1726 4:Subject: [PATCH] subject
1728 11:Signed-off-by: C O Mitter <committer@example.com>
1730 test_cmp expect actual
1733 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1734 append_signoff <<-\EOF >actual &&
1735 subject
1737 body
1739 Reviewed-id: Noone
1740 Tested-by: my@house
1741 Change-id: Ideadbeef
1742 Signed-off-by: C O Mitter <committer@example.com>
1743 Bug: 1234
1745 cat >expect <<-\EOF &&
1746 4:Subject: [PATCH] subject
1749 14:Signed-off-by: C O Mitter <committer@example.com>
1751 test_cmp expect actual
1754 test_expect_success 'format patch ignores color.ui' '
1755 test_unconfig color.ui &&
1756 git format-patch --stdout -1 >expect &&
1757 test_config color.ui always &&
1758 git format-patch --stdout -1 >actual &&
1759 test_cmp expect actual
1762 test_expect_success 'format patch respects diff.relative' '
1763 rm -rf subdir &&
1764 mkdir subdir &&
1765 echo other content >subdir/file2 &&
1766 git add subdir/file2 &&
1767 git commit -F msg &&
1768 test_unconfig diff.relative &&
1769 git format-patch --relative=subdir --stdout -1 >expect &&
1770 test_config diff.relative true &&
1771 git -C subdir format-patch --stdout -1 >actual &&
1772 test_cmp expect actual
1775 test_expect_success 'cover letter with invalid --cover-from-description and config' '
1776 test_config branch.rebuild-1.description "config subject
1778 body" &&
1779 test_must_fail git format-patch --cover-letter --cover-from-description garbage main &&
1780 test_config format.coverFromDescription garbage &&
1781 test_must_fail git format-patch --cover-letter main
1784 test_expect_success 'cover letter with format.coverFromDescription = default' '
1785 test_config branch.rebuild-1.description "config subject
1787 body" &&
1788 test_config format.coverFromDescription default &&
1789 git checkout rebuild-1 &&
1790 git format-patch --stdout --cover-letter main >actual &&
1791 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1792 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1793 grep "^config subject$" actual &&
1794 grep "^body$" actual
1797 test_expect_success 'cover letter with --cover-from-description default' '
1798 test_config branch.rebuild-1.description "config subject
1800 body" &&
1801 git checkout rebuild-1 &&
1802 git format-patch --stdout --cover-letter --cover-from-description default main >actual &&
1803 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1804 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1805 grep "^config subject$" actual &&
1806 grep "^body$" actual
1809 test_expect_success 'cover letter with format.coverFromDescription = none' '
1810 test_config branch.rebuild-1.description "config subject
1812 body" &&
1813 test_config format.coverFromDescription none &&
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 none' '
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 none 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 = message' '
1835 test_config branch.rebuild-1.description "config subject
1837 body" &&
1838 test_config format.coverFromDescription message &&
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 message' '
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 message 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 = subject' '
1860 test_config branch.rebuild-1.description "config subject
1862 body" &&
1863 test_config format.coverFromDescription subject &&
1864 git checkout rebuild-1 &&
1865 git format-patch --stdout --cover-letter main >actual &&
1866 grep "^Subject: \[PATCH 0/2\] config subject$" 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 subject' '
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 subject main >actual &&
1878 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1879 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1880 ! grep "^config subject$" actual &&
1881 grep "^body$" actual
1884 test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' '
1885 test_config branch.rebuild-1.description "config subject
1887 body" &&
1888 test_config format.coverFromDescription auto &&
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 auto (short subject line)' '
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 auto 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 format.coverFromDescription = auto (long subject line)' '
1910 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
1912 body" &&
1913 test_config format.coverFromDescription auto &&
1914 git checkout rebuild-1 &&
1915 git format-patch --stdout --cover-letter main >actual &&
1916 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1917 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1918 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1919 grep "^body$" actual
1922 test_expect_success 'cover letter with --cover-from-description auto (long subject line)' '
1923 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
1925 body" &&
1926 git checkout rebuild-1 &&
1927 git format-patch --stdout --cover-letter --cover-from-description auto main >actual &&
1928 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1929 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1930 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1931 grep "^body$" actual
1934 test_expect_success 'cover letter with command-line --cover-from-description overrides config' '
1935 test_config branch.rebuild-1.description "config subject
1937 body" &&
1938 test_config format.coverFromDescription none &&
1939 git checkout rebuild-1 &&
1940 git format-patch --stdout --cover-letter --cover-from-description subject main >actual &&
1941 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1942 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1943 ! grep "^config subject$" actual &&
1944 grep "^body$" actual
1947 test_expect_success 'cover letter using branch description (1)' '
1948 git checkout rebuild-1 &&
1949 test_config branch.rebuild-1.description hello &&
1950 git format-patch --stdout --cover-letter main >actual &&
1951 grep hello actual
1954 test_expect_success 'cover letter using branch description (2)' '
1955 git checkout rebuild-1 &&
1956 test_config branch.rebuild-1.description hello &&
1957 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1958 grep hello actual
1961 test_expect_success 'cover letter using branch description (3)' '
1962 git checkout rebuild-1 &&
1963 test_config branch.rebuild-1.description hello &&
1964 git format-patch --stdout --cover-letter ^main rebuild-1 >actual &&
1965 grep hello actual
1968 test_expect_success 'cover letter using branch description (4)' '
1969 git checkout rebuild-1 &&
1970 test_config branch.rebuild-1.description hello &&
1971 git format-patch --stdout --cover-letter main.. >actual &&
1972 grep hello actual
1975 test_expect_success 'cover letter using branch description (5)' '
1976 git checkout rebuild-1 &&
1977 test_config branch.rebuild-1.description hello &&
1978 git format-patch --stdout --cover-letter -2 HEAD >actual &&
1979 grep hello actual
1982 test_expect_success 'cover letter using branch description (6)' '
1983 git checkout rebuild-1 &&
1984 test_config branch.rebuild-1.description hello &&
1985 git format-patch --stdout --cover-letter -2 >actual &&
1986 grep hello actual
1989 test_expect_success 'cover letter with nothing' '
1990 git format-patch --stdout --cover-letter >actual &&
1991 test_line_count = 0 actual
1994 test_expect_success 'cover letter auto' '
1995 mkdir -p tmp &&
1996 test_when_finished "rm -rf tmp;
1997 git config --unset format.coverletter" &&
1999 git config format.coverletter auto &&
2000 git format-patch -o tmp -1 >list &&
2001 test_line_count = 1 list &&
2002 git format-patch -o tmp -2 >list &&
2003 test_line_count = 3 list
2006 test_expect_success 'cover letter auto user override' '
2007 mkdir -p tmp &&
2008 test_when_finished "rm -rf tmp;
2009 git config --unset format.coverletter" &&
2011 git config format.coverletter auto &&
2012 git format-patch -o tmp --cover-letter -1 >list &&
2013 test_line_count = 2 list &&
2014 git format-patch -o tmp --cover-letter -2 >list &&
2015 test_line_count = 3 list &&
2016 git format-patch -o tmp --no-cover-letter -1 >list &&
2017 test_line_count = 1 list &&
2018 git format-patch -o tmp --no-cover-letter -2 >list &&
2019 test_line_count = 2 list
2022 test_expect_success 'format-patch --zero-commit' '
2023 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
2024 grep "^From " patch2 | sort | uniq >actual &&
2025 echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
2026 test_cmp expect actual
2029 test_expect_success 'From line has expected format' '
2030 git format-patch --stdout v2..v1 >patch2 &&
2031 grep "^From " patch2 >from &&
2032 grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
2033 test_cmp from filtered
2036 test_expect_success 'format-patch -o with no leading directories' '
2037 rm -fr patches &&
2038 git format-patch -o patches main..side &&
2039 count=$(git rev-list --count main..side) &&
2040 ls patches >list &&
2041 test_line_count = $count list
2044 test_expect_success 'format-patch -o with leading existing directories' '
2045 rm -rf existing-dir &&
2046 mkdir existing-dir &&
2047 git format-patch -o existing-dir/patches main..side &&
2048 count=$(git rev-list --count main..side) &&
2049 ls existing-dir/patches >list &&
2050 test_line_count = $count list
2053 test_expect_success 'format-patch -o with leading non-existing directories' '
2054 rm -rf non-existing-dir &&
2055 git format-patch -o non-existing-dir/patches main..side &&
2056 count=$(git rev-list --count main..side) &&
2057 test_path_is_dir non-existing-dir &&
2058 ls non-existing-dir/patches >list &&
2059 test_line_count = $count list
2062 test_expect_success 'format-patch format.outputDirectory option' '
2063 test_config format.outputDirectory patches &&
2064 rm -fr patches &&
2065 git format-patch main..side &&
2066 count=$(git rev-list --count main..side) &&
2067 ls patches >list &&
2068 test_line_count = $count list
2071 test_expect_success 'format-patch -o overrides format.outputDirectory' '
2072 test_config format.outputDirectory patches &&
2073 rm -fr patches patchset &&
2074 git format-patch main..side -o patchset &&
2075 test_path_is_missing patches &&
2076 test_path_is_dir patchset
2079 test_expect_success 'format-patch forbids multiple outputs' '
2080 rm -fr outfile outdir &&
2081 test_must_fail \
2082 git format-patch --stdout --output-directory=outdir &&
2083 test_must_fail \
2084 git format-patch --stdout --output=outfile &&
2085 test_must_fail \
2086 git format-patch --output=outfile --output-directory=outdir
2089 test_expect_success 'configured outdir does not conflict with output options' '
2090 rm -fr outfile outdir &&
2091 test_config format.outputDirectory outdir &&
2092 git format-patch --stdout &&
2093 test_path_is_missing outdir &&
2094 git format-patch --output=outfile &&
2095 test_path_is_missing outdir
2098 test_expect_success 'format-patch --output' '
2099 rm -fr outfile &&
2100 git format-patch -3 --stdout HEAD >expect &&
2101 git format-patch -3 --output=outfile HEAD &&
2102 test_cmp expect outfile
2105 test_expect_success 'format-patch --cover-letter --output' '
2106 rm -fr outfile &&
2107 git format-patch --cover-letter -3 --stdout HEAD >expect &&
2108 git format-patch --cover-letter -3 --output=outfile HEAD &&
2109 test_cmp expect outfile
2112 test_expect_success 'format-patch --base' '
2113 git checkout patchid &&
2115 git format-patch --stdout --base=HEAD~3 -1 >patch &&
2116 tail -n 7 patch >actual1 &&
2118 git format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&
2119 tail -n 7 patch >actual2 &&
2121 echo >expect &&
2122 git rev-parse HEAD~3 >commit-id-base &&
2123 echo "base-commit: $(cat commit-id-base)" >>expect &&
2125 git show --patch HEAD~2 >patch &&
2126 git patch-id --stable <patch >patch.id.raw &&
2127 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2129 git show --patch HEAD~1 >patch &&
2130 git patch-id --stable <patch >patch.id.raw &&
2131 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2133 signature >>expect &&
2134 test_cmp expect actual1 &&
2135 test_cmp expect actual2 &&
2137 echo >fail &&
2138 echo "base-commit: $(cat commit-id-base)" >>fail &&
2140 git show --patch HEAD~2 >patch &&
2141 git patch-id --unstable <patch >patch.id.raw &&
2142 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2144 git show --patch HEAD~1 >patch &&
2145 git patch-id --unstable <patch >patch.id.raw &&
2146 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2148 signature >>fail &&
2149 ! test_cmp fail actual1 &&
2150 ! test_cmp fail actual2
2153 test_expect_success 'format-patch --base errors out when base commit is in revision list' '
2154 test_must_fail git format-patch --base=HEAD -2 &&
2155 test_must_fail git format-patch --base=HEAD~1 -2 &&
2156 git format-patch --stdout --base=HEAD~2 -2 >patch &&
2157 grep "^base-commit:" patch >actual &&
2158 git rev-parse HEAD~2 >commit-id-base &&
2159 echo "base-commit: $(cat commit-id-base)" >expect &&
2160 test_cmp expect actual
2163 test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
2164 # For history as below:
2166 # ---Q---P---Z---Y---*---X
2167 # \ /
2168 # ------------W
2170 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
2171 git checkout -b topic1 main &&
2172 git rev-parse HEAD >commit-id-base &&
2173 test_commit P &&
2174 git rev-parse HEAD >commit-id-P &&
2175 test_commit Z &&
2176 git rev-parse HEAD >commit-id-Z &&
2177 test_commit Y &&
2178 git checkout -b topic2 main &&
2179 test_commit W &&
2180 git merge topic1 &&
2181 test_commit X &&
2182 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
2183 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
2184 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
2185 grep "^base-commit:" patch >actual &&
2186 echo "base-commit: $(cat commit-id-base)" >expect &&
2187 test_cmp expect actual
2190 test_expect_success 'format-patch --base=auto' '
2191 git checkout -b upstream main &&
2192 git checkout -b local upstream &&
2193 git branch --set-upstream-to=upstream &&
2194 test_commit N1 &&
2195 test_commit N2 &&
2196 git format-patch --stdout --base=auto -2 >patch &&
2197 grep "^base-commit:" patch >actual &&
2198 git rev-parse upstream >commit-id-base &&
2199 echo "base-commit: $(cat commit-id-base)" >expect &&
2200 test_cmp expect actual
2203 test_expect_success 'format-patch errors out when history involves criss-cross' '
2204 # setup criss-cross history
2206 # B---M1---D
2207 # / \ /
2208 # A X
2209 # \ / \
2210 # C---M2---E
2212 git checkout main &&
2213 test_commit A &&
2214 git checkout -b xb main &&
2215 test_commit B &&
2216 git checkout -b xc main &&
2217 test_commit C &&
2218 git checkout -b xbc xb -- &&
2219 git merge xc &&
2220 git checkout -b xcb xc -- &&
2221 git branch --set-upstream-to=xbc &&
2222 git merge xb &&
2223 git checkout xbc &&
2224 test_commit D &&
2225 git checkout xcb &&
2226 test_commit E &&
2227 test_must_fail git format-patch --base=auto -1
2230 test_expect_success 'format-patch format.useAutoBase whenAble history involves criss-cross' '
2231 test_config format.useAutoBase whenAble &&
2232 git format-patch -1 >patch &&
2233 ! grep "^base-commit:" patch
2236 test_expect_success 'format-patch format.useAutoBase option' '
2237 git checkout local &&
2238 test_config format.useAutoBase true &&
2239 git format-patch --stdout -1 >patch &&
2240 grep "^base-commit:" patch >actual &&
2241 git rev-parse upstream >commit-id-base &&
2242 echo "base-commit: $(cat commit-id-base)" >expect &&
2243 test_cmp expect actual
2246 test_expect_success 'format-patch format.useAutoBase option with whenAble' '
2247 git checkout local &&
2248 test_config format.useAutoBase whenAble &&
2249 git format-patch --stdout -1 >patch &&
2250 grep "^base-commit:" patch >actual &&
2251 git rev-parse upstream >commit-id-base &&
2252 echo "base-commit: $(cat commit-id-base)" >expect &&
2253 test_cmp expect actual
2256 test_expect_success 'format-patch --base overrides format.useAutoBase' '
2257 test_config format.useAutoBase true &&
2258 git format-patch --stdout --base=HEAD~1 -1 >patch &&
2259 grep "^base-commit:" patch >actual &&
2260 git rev-parse HEAD~1 >commit-id-base &&
2261 echo "base-commit: $(cat commit-id-base)" >expect &&
2262 test_cmp expect actual
2265 test_expect_success 'format-patch --no-base overrides format.useAutoBase' '
2266 test_config format.useAutoBase true &&
2267 git format-patch --stdout --no-base -1 >patch &&
2268 ! grep "^base-commit:" patch
2271 test_expect_success 'format-patch --no-base overrides format.useAutoBase whenAble' '
2272 test_config format.useAutoBase whenAble &&
2273 git format-patch --stdout --no-base -1 >patch &&
2274 ! grep "^base-commit:" patch
2277 test_expect_success 'format-patch --base with --attach' '
2278 git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
2279 sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
2280 patch >actual &&
2281 test_write_lines 1 2 >expect &&
2282 test_cmp expect actual
2284 test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
2285 test_when_finished "rm -fr patches" &&
2286 git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
2287 ! grep -E "^--+mimemime" patches/0000*.patch &&
2288 grep -E "^--+mimemime$" patches/0001*.patch >output &&
2289 test_line_count = 2 output &&
2290 grep -E "^--+mimemime--$" patches/0001*.patch >output &&
2291 test_line_count = 1 output
2294 test_expect_success 'format-patch with format.attach' '
2295 test_when_finished "rm -fr patches" &&
2296 separator=attachment-separator &&
2297 test_config format.attach "$separator" &&
2298 filename=$(git format-patch -o patches -1) &&
2299 grep "^Content-Type: multipart/.*$separator" "$filename"
2302 test_expect_success 'format-patch with format.attach=disabled' '
2303 test_when_finished "rm -fr patches" &&
2304 separator=attachment-separator &&
2305 test_config_global format.attach "$separator" &&
2306 test_config format.attach "" &&
2307 filename=$(git format-patch -o patches -1) &&
2308 # The output should not even declare content type for text/plain.
2309 ! grep "^Content-Type: multipart/" "$filename"
2312 test_expect_success '-c format.mboxrd format-patch' '
2313 sp=" " &&
2314 cat >msg <<-INPUT_END &&
2315 mboxrd should escape the body
2317 From could trip up a loose mbox parser
2318 >From extra escape for reversibility
2319 >>From extra escape for reversibility 2
2320 from lower case not escaped
2321 Fromm bad speling not escaped
2322 From with leading space not escaped
2325 From
2326 From$sp
2327 From $sp
2328 From $sp
2329 INPUT_END
2331 cat >expect <<-INPUT_END &&
2332 >From could trip up a loose mbox parser
2333 >>From extra escape for reversibility
2334 >>>From extra escape for reversibility 2
2335 from lower case not escaped
2336 Fromm bad speling not escaped
2337 From with leading space not escaped
2340 From
2341 From
2342 From
2343 From
2344 INPUT_END
2346 C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
2347 git -c format.mboxrd format-patch --stdout -1 $C~1..$C >patch &&
2348 git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >compat &&
2349 test_cmp patch compat &&
2350 git grep -h --no-index -A11 \
2351 "^>From could trip up a loose mbox parser" patch >actual &&
2352 test_cmp expect actual
2355 test_expect_success 'interdiff: setup' '
2356 git checkout -b boop main &&
2357 test_commit fnorp blorp &&
2358 test_commit fleep blorp
2361 test_expect_success 'interdiff: cover-letter' '
2362 sed "y/q/ /" >expect <<-\EOF &&
2363 +fleep
2366 git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
2367 test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch &&
2368 test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch &&
2369 sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual &&
2370 test_cmp expect actual
2373 test_expect_success 'interdiff: reroll-count' '
2374 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2375 test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2378 test_expect_success 'interdiff: reroll-count with a non-integer' '
2379 git format-patch --cover-letter --interdiff=boop~2 -v2.2 -1 boop &&
2380 test_i18ngrep "^Interdiff:$" v2.2-0000-cover-letter.patch
2383 test_expect_success 'interdiff: reroll-count with a integer' '
2384 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2385 test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2388 test_expect_success 'interdiff: solo-patch' '
2389 cat >expect <<-\EOF &&
2390 +fleep
2393 git format-patch --interdiff=boop~2 -1 boop &&
2394 test_i18ngrep "^Interdiff:$" 0001-fleep.patch &&
2395 sed "1,/^ @@ /d; /^$/q" 0001-fleep.patch >actual &&
2396 test_cmp expect actual
2399 test_done