Merge branch 'es/maintenance-of-bare-repositories'
[git/debian.git] / t / t4014-format-patch.sh
blobcdd3154e702674007cef1e1a368cad0c5476c060
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 for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
16 cat file >elif &&
17 git add file elif &&
18 test_tick &&
19 git commit -m Initial &&
20 git checkout -b side &&
22 for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
23 test_chmod +x elif &&
24 test_tick &&
25 git commit -m "Side changes #1" &&
27 for i in D E F; do echo "$i"; done >>file &&
28 git update-index file &&
29 test_tick &&
30 git commit -m "Side changes #2" &&
31 git tag C2 &&
33 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >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 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file2 &&
47 for i in 1 2 3 A 4 B C 7 8 9 10 D E F 5 6; do echo "$i"; done >file3 &&
48 for i in 8 9 10; do echo "$i"; done >file &&
49 git add file file2 file3 &&
50 test_tick &&
51 git commit -m "patchid 1" &&
52 for i in 4 A B 7 8 9 10; do echo "$i"; done >file2 &&
53 for i in 8 9 10 5 6; do echo "$i"; done >file3 &&
54 git add file2 file3 &&
55 test_tick &&
56 git commit -m "patchid 2" &&
57 for i in 10 5 6; do echo "$i"; done >file &&
58 git add file &&
59 test_tick &&
60 git commit -m "patchid 3" &&
62 git checkout main
65 test_expect_success 'format-patch --ignore-if-in-upstream' '
66 git format-patch --stdout main..side >patch0 &&
67 grep "^From " patch0 >from0 &&
68 test_line_count = 3 from0
71 test_expect_success 'format-patch --ignore-if-in-upstream' '
72 git format-patch --stdout \
73 --ignore-if-in-upstream main..side >patch1 &&
74 grep "^From " patch1 >from1 &&
75 test_line_count = 2 from1
78 test_expect_success 'format-patch --ignore-if-in-upstream handles tags' '
79 git tag -a v1 -m tag side &&
80 git tag -a v2 -m tag main &&
81 git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
82 grep "^From " patch1 >from1 &&
83 test_line_count = 2 from1
86 test_expect_success "format-patch doesn't consider merge commits" '
87 git checkout -b feature main &&
88 echo "Another line" >>file &&
89 test_tick &&
90 git commit -am "Feature branch change #1" &&
91 echo "Yet another line" >>file &&
92 test_tick &&
93 git commit -am "Feature branch change #2" &&
94 git checkout -b merger main &&
95 test_tick &&
96 git merge --no-ff feature &&
97 git format-patch -3 --stdout >patch &&
98 grep "^From " patch >from &&
99 test_line_count = 3 from
102 test_expect_success 'format-patch result applies' '
103 git checkout -b rebuild-0 main &&
104 git am -3 patch0 &&
105 git rev-list main.. >list &&
106 test_line_count = 2 list
109 test_expect_success 'format-patch --ignore-if-in-upstream result applies' '
110 git checkout -b rebuild-1 main &&
111 git am -3 patch1 &&
112 git rev-list main.. >list &&
113 test_line_count = 2 list
116 test_expect_success 'commit did not screw up the log message' '
117 git cat-file commit side >actual &&
118 grep "^Side .* with .* backslash-n" actual
121 test_expect_success 'format-patch did not screw up the log message' '
122 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
123 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
126 test_expect_success 'replay did not screw up the log message' '
127 git cat-file commit rebuild-1 >actual &&
128 grep "^Side .* with .* backslash-n" actual
131 test_expect_success 'extra headers' '
132 git config format.headers "To: R E Cipient <rcipient@example.com>
133 " &&
134 git config --add format.headers "Cc: S E Cipient <scipient@example.com>
135 " &&
136 git format-patch --stdout main..side >patch2 &&
137 sed -e "/^\$/q" patch2 >hdrs2 &&
138 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
139 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
142 test_expect_success 'extra headers without newlines' '
143 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
144 git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
145 git format-patch --stdout main..side >patch3 &&
146 sed -e "/^\$/q" patch3 >hdrs3 &&
147 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
148 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
151 test_expect_success 'extra headers with multiple To:s' '
152 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
153 git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
154 git format-patch --stdout main..side >patch4 &&
155 sed -e "/^\$/q" patch4 >hdrs4 &&
156 grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
157 grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
160 test_expect_success 'additional command line cc (ascii)' '
161 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
162 git format-patch --cc="S E Cipient <scipient@example.com>" --stdout main..side >patch5 &&
163 sed -e "/^\$/q" patch5 >hdrs5 &&
164 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
165 grep "^ *S E Cipient <scipient@example.com>\$" hdrs5
168 test_expect_failure 'additional command line cc (rfc822)' '
169 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
170 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout main..side >patch5 &&
171 sed -e "/^\$/q" patch5 >hdrs5 &&
172 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
173 grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" hdrs5
176 test_expect_success 'command line headers' '
177 git config --unset-all format.headers &&
178 git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout main..side >patch6 &&
179 sed -e "/^\$/q" patch6 >hdrs6 &&
180 grep "^Cc: R E Cipient <rcipient@example.com>\$" hdrs6
183 test_expect_success 'configuration headers and command line headers' '
184 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
185 git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout main..side >patch7 &&
186 sed -e "/^\$/q" patch7 >hdrs7 &&
187 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs7 &&
188 grep "^ *S E Cipient <scipient@example.com>\$" hdrs7
191 test_expect_success 'command line To: header (ascii)' '
192 git config --unset-all format.headers &&
193 git format-patch --to="R E Cipient <rcipient@example.com>" --stdout main..side >patch8 &&
194 sed -e "/^\$/q" patch8 >hdrs8 &&
195 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs8
198 test_expect_failure 'command line To: header (rfc822)' '
199 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout main..side >patch8 &&
200 sed -e "/^\$/q" patch8 >hdrs8 &&
201 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs8
204 test_expect_failure 'command line To: header (rfc2047)' '
205 git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout main..side >patch8 &&
206 sed -e "/^\$/q" patch8 >hdrs8 &&
207 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs8
210 test_expect_success 'configuration To: header (ascii)' '
211 git config format.to "R E Cipient <rcipient@example.com>" &&
212 git format-patch --stdout main..side >patch9 &&
213 sed -e "/^\$/q" patch9 >hdrs9 &&
214 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs9
217 test_expect_failure 'configuration To: header (rfc822)' '
218 git config format.to "R. E. Cipient <rcipient@example.com>" &&
219 git format-patch --stdout main..side >patch9 &&
220 sed -e "/^\$/q" patch9 >hdrs9 &&
221 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs9
224 test_expect_failure 'configuration To: header (rfc2047)' '
225 git config format.to "R Ä Cipient <rcipient@example.com>" &&
226 git format-patch --stdout main..side >patch9 &&
227 sed -e "/^\$/q" patch9 >hdrs9 &&
228 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs9
231 # check_patch <patch>: Verify that <patch> looks like a half-sane
232 # patch email to avoid a false positive with !grep
233 check_patch () {
234 grep -e "^From:" "$1" &&
235 grep -e "^Date:" "$1" &&
236 grep -e "^Subject:" "$1"
239 test_expect_success 'format.from=false' '
240 git -c format.from=false format-patch --stdout main..side >patch &&
241 sed -e "/^\$/q" patch >hdrs &&
242 check_patch patch &&
243 ! grep "^From: C O Mitter <committer@example.com>\$" hdrs
246 test_expect_success 'format.from=true' '
247 git -c format.from=true format-patch --stdout main..side >patch &&
248 sed -e "/^\$/q" patch >hdrs &&
249 check_patch hdrs &&
250 grep "^From: C O Mitter <committer@example.com>\$" hdrs
253 test_expect_success 'format.from with address' '
254 git -c format.from="F R Om <from@example.com>" format-patch --stdout main..side >patch &&
255 sed -e "/^\$/q" patch >hdrs &&
256 check_patch hdrs &&
257 grep "^From: F R Om <from@example.com>\$" hdrs
260 test_expect_success '--no-from overrides format.from' '
261 git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout main..side >patch &&
262 sed -e "/^\$/q" patch >hdrs &&
263 check_patch hdrs &&
264 ! grep "^From: F R Om <from@example.com>\$" hdrs
267 test_expect_success '--from overrides format.from' '
268 git -c format.from="F R Om <from@example.com>" format-patch --from --stdout main..side >patch &&
269 sed -e "/^\$/q" patch >hdrs &&
270 check_patch hdrs &&
271 ! grep "^From: F R Om <from@example.com>\$" hdrs
274 test_expect_success '--no-to overrides config.to' '
275 git config --replace-all format.to \
276 "R E Cipient <rcipient@example.com>" &&
277 git format-patch --no-to --stdout main..side >patch10 &&
278 sed -e "/^\$/q" patch10 >hdrs10 &&
279 check_patch hdrs10 &&
280 ! grep "^To: R E Cipient <rcipient@example.com>\$" hdrs10
283 test_expect_success '--no-to and --to replaces config.to' '
284 git config --replace-all format.to \
285 "Someone <someone@out.there>" &&
286 git format-patch --no-to --to="Someone Else <else@out.there>" \
287 --stdout main..side >patch11 &&
288 sed -e "/^\$/q" patch11 >hdrs11 &&
289 check_patch hdrs11 &&
290 ! grep "^To: Someone <someone@out.there>\$" hdrs11 &&
291 grep "^To: Someone Else <else@out.there>\$" hdrs11
294 test_expect_success '--no-cc overrides config.cc' '
295 git config --replace-all format.cc \
296 "C E Cipient <rcipient@example.com>" &&
297 git format-patch --no-cc --stdout main..side >patch12 &&
298 sed -e "/^\$/q" patch12 >hdrs12 &&
299 check_patch hdrs12 &&
300 ! grep "^Cc: C E Cipient <rcipient@example.com>\$" hdrs12
303 test_expect_success '--no-add-header overrides config.headers' '
304 git config --replace-all format.headers \
305 "Header1: B E Cipient <rcipient@example.com>" &&
306 git format-patch --no-add-header --stdout main..side >patch13 &&
307 sed -e "/^\$/q" patch13 >hdrs13 &&
308 check_patch hdrs13 &&
309 ! grep "^Header1: B E Cipient <rcipient@example.com>\$" hdrs13
312 test_expect_success 'multiple files' '
313 rm -rf patches/ &&
314 git checkout side &&
315 git format-patch -o patches/ main &&
316 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
319 test_expect_success 'filename length limit' '
320 test_when_finished "rm -f 000*" &&
321 rm -rf 000[1-9]-*.patch &&
322 for len in 15 25 35
324 git format-patch --filename-max-length=$len -3 side &&
325 max=$(
326 for patch in 000[1-9]-*.patch
328 echo "$patch" | wc -c
329 done |
330 sort -nr |
331 head -n 1
332 ) &&
333 test $max -le $len || return 1
334 done
337 test_expect_success 'filename length limit from config' '
338 test_when_finished "rm -f 000*" &&
339 rm -rf 000[1-9]-*.patch &&
340 for len in 15 25 35
342 git -c format.filenameMaxLength=$len format-patch -3 side &&
343 max=$(
344 for patch in 000[1-9]-*.patch
346 echo "$patch" | wc -c
347 done |
348 sort -nr |
349 head -n 1
350 ) &&
351 test $max -le $len || return 1
352 done
355 test_expect_success 'filename limit applies only to basename' '
356 test_when_finished "rm -rf patches/" &&
357 rm -rf patches/ &&
358 for len in 15 25 35
360 git format-patch -o patches --filename-max-length=$len -3 side &&
361 max=$(
362 for patch in patches/000[1-9]-*.patch
364 echo "${patch#patches/}" | wc -c
365 done |
366 sort -nr |
367 head -n 1
368 ) &&
369 test $max -le $len || return 1
370 done
373 test_expect_success 'reroll count' '
374 rm -fr patches &&
375 git format-patch -o patches --cover-letter --reroll-count 4 main..side >list &&
376 ! grep -v "^patches/v4-000[0-3]-" list &&
377 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
378 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
381 test_expect_success 'reroll count (-v)' '
382 rm -fr patches &&
383 git format-patch -o patches --cover-letter -v4 main..side >list &&
384 ! grep -v "^patches/v4-000[0-3]-" list &&
385 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
386 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
389 check_threading () {
390 expect="$1" &&
391 shift &&
392 git format-patch --stdout "$@" >patch &&
393 # Prints everything between the Message-ID and In-Reply-To,
394 # and replaces all Message-ID-lookalikes by a sequence number
395 perl -ne '
396 if (/^(message-id|references|in-reply-to)/i) {
397 $printing = 1;
398 } elsif (/^\S/) {
399 $printing = 0;
401 if ($printing) {
402 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
403 for $k (keys %h) {s/$k/$h{$k}/};
404 print;
406 print "---\n" if /^From /i;
407 ' <patch >actual &&
408 test_cmp "$expect" actual
411 cat >>expect.no-threading <<EOF
417 test_expect_success 'no threading' '
418 git checkout side &&
419 check_threading expect.no-threading main
422 cat >expect.thread <<EOF
424 Message-Id: <0>
426 Message-Id: <1>
427 In-Reply-To: <0>
428 References: <0>
430 Message-Id: <2>
431 In-Reply-To: <0>
432 References: <0>
435 test_expect_success 'thread' '
436 check_threading expect.thread --thread main
439 cat >expect.in-reply-to <<EOF
441 Message-Id: <0>
442 In-Reply-To: <1>
443 References: <1>
445 Message-Id: <2>
446 In-Reply-To: <1>
447 References: <1>
449 Message-Id: <3>
450 In-Reply-To: <1>
451 References: <1>
454 test_expect_success 'thread in-reply-to' '
455 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
456 --thread main
459 cat >expect.cover-letter <<EOF
461 Message-Id: <0>
463 Message-Id: <1>
464 In-Reply-To: <0>
465 References: <0>
467 Message-Id: <2>
468 In-Reply-To: <0>
469 References: <0>
471 Message-Id: <3>
472 In-Reply-To: <0>
473 References: <0>
476 test_expect_success 'thread cover-letter' '
477 check_threading expect.cover-letter --cover-letter --thread main
480 cat >expect.cl-irt <<EOF
482 Message-Id: <0>
483 In-Reply-To: <1>
484 References: <1>
486 Message-Id: <2>
487 In-Reply-To: <0>
488 References: <1>
491 Message-Id: <3>
492 In-Reply-To: <0>
493 References: <1>
496 Message-Id: <4>
497 In-Reply-To: <0>
498 References: <1>
502 test_expect_success 'thread cover-letter in-reply-to' '
503 check_threading expect.cl-irt --cover-letter \
504 --in-reply-to="<test.message>" --thread main
507 test_expect_success 'thread explicit shallow' '
508 check_threading expect.cl-irt --cover-letter \
509 --in-reply-to="<test.message>" --thread=shallow main
512 cat >expect.deep <<EOF
514 Message-Id: <0>
516 Message-Id: <1>
517 In-Reply-To: <0>
518 References: <0>
520 Message-Id: <2>
521 In-Reply-To: <1>
522 References: <0>
526 test_expect_success 'thread deep' '
527 check_threading expect.deep --thread=deep main
530 cat >expect.deep-irt <<EOF
532 Message-Id: <0>
533 In-Reply-To: <1>
534 References: <1>
536 Message-Id: <2>
537 In-Reply-To: <0>
538 References: <1>
541 Message-Id: <3>
542 In-Reply-To: <2>
543 References: <1>
548 test_expect_success 'thread deep in-reply-to' '
549 check_threading expect.deep-irt --thread=deep \
550 --in-reply-to="<test.message>" main
553 cat >expect.deep-cl <<EOF
555 Message-Id: <0>
557 Message-Id: <1>
558 In-Reply-To: <0>
559 References: <0>
561 Message-Id: <2>
562 In-Reply-To: <1>
563 References: <0>
566 Message-Id: <3>
567 In-Reply-To: <2>
568 References: <0>
573 test_expect_success 'thread deep cover-letter' '
574 check_threading expect.deep-cl --cover-letter --thread=deep main
577 cat >expect.deep-cl-irt <<EOF
579 Message-Id: <0>
580 In-Reply-To: <1>
581 References: <1>
583 Message-Id: <2>
584 In-Reply-To: <0>
585 References: <1>
588 Message-Id: <3>
589 In-Reply-To: <2>
590 References: <1>
594 Message-Id: <4>
595 In-Reply-To: <3>
596 References: <1>
602 test_expect_success 'thread deep cover-letter in-reply-to' '
603 check_threading expect.deep-cl-irt --cover-letter \
604 --in-reply-to="<test.message>" --thread=deep main
607 test_expect_success 'thread via config' '
608 test_config format.thread true &&
609 check_threading expect.thread main
612 test_expect_success 'thread deep via config' '
613 test_config format.thread deep &&
614 check_threading expect.deep main
617 test_expect_success 'thread config + override' '
618 test_config format.thread deep &&
619 check_threading expect.thread --thread main
622 test_expect_success 'thread config + --no-thread' '
623 test_config format.thread deep &&
624 check_threading expect.no-threading --no-thread main
627 test_expect_success 'excessive subject' '
628 rm -rf patches/ &&
629 git checkout side &&
630 before=$(git hash-object file) &&
631 before=$(git rev-parse --short $before) &&
632 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
633 after=$(git hash-object file) &&
634 after=$(git rev-parse --short $after) &&
635 git update-index file &&
636 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." &&
637 git format-patch -o patches/ main..side &&
638 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
641 test_expect_success 'failure to write cover-letter aborts gracefully' '
642 test_when_finished "rmdir 0000-cover-letter.patch" &&
643 mkdir 0000-cover-letter.patch &&
644 test_must_fail git format-patch --no-renames --cover-letter -1
647 test_expect_success 'cover-letter inherits diff options' '
648 git mv file foo &&
649 git commit -m foo &&
650 git format-patch --no-renames --cover-letter -1 &&
651 check_patch 0000-cover-letter.patch &&
652 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
653 git format-patch --cover-letter -1 -M &&
654 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
657 cat >expect <<EOF
658 This is an excessively long subject line for a message due to the
659 habit some projects have of not having a short, one-line subject at
660 the start of the commit message, but rather sticking a whole
661 paragraph right at the start as the only thing in the commit
662 message. It had better not become the filename for the patch.
667 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
668 git format-patch --cover-letter -2 &&
669 sed -e "1,/A U Thor/d" -e "/^\$/q" 0000-cover-letter.patch >output &&
670 test_cmp expect output
673 cat >expect <<EOF
674 index $before..$after 100644
675 --- a/file
676 +++ b/file
677 @@ -13,4 +13,20 @@ C
685 test_expect_success 'format-patch respects -U' '
686 git format-patch -U4 -2 &&
687 sed -e "1,/^diff/d" -e "/^+5/q" \
688 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
689 >output &&
690 test_cmp expect output
693 cat >expect <<EOF
695 diff --git a/file b/file
696 index $before..$after 100644
697 --- a/file
698 +++ b/file
699 @@ -14,3 +14,19 @@ C
706 test_expect_success 'format-patch -p suppresses stat' '
707 git format-patch -p -2 &&
708 sed -e "1,/^\$/d" -e "/^+5/q" 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&
709 test_cmp expect output
712 test_expect_success 'format-patch from a subdirectory (1)' '
713 filename=$(
714 rm -rf sub &&
715 mkdir -p sub/dir &&
716 cd sub/dir &&
717 git format-patch -1
718 ) &&
719 case "$filename" in
721 ;; # ok
723 echo "Oops? $filename"
724 false
726 esac &&
727 test -f "$filename"
730 test_expect_success 'format-patch from a subdirectory (2)' '
731 filename=$(
732 rm -rf sub &&
733 mkdir -p sub/dir &&
734 cd sub/dir &&
735 git format-patch -1 -o ..
736 ) &&
737 case "$filename" in
738 ../0*)
739 ;; # ok
741 echo "Oops? $filename"
742 false
744 esac &&
745 basename=$(expr "$filename" : ".*/\(.*\)") &&
746 test -f "sub/$basename"
749 test_expect_success 'format-patch from a subdirectory (3)' '
750 rm -f 0* &&
751 filename=$(
752 rm -rf sub &&
753 mkdir -p sub/dir &&
754 cd sub/dir &&
755 git format-patch -1 -o "$TRASH_DIRECTORY"
756 ) &&
757 basename=$(expr "$filename" : ".*/\(.*\)") &&
758 test -f "$basename"
761 test_expect_success 'format-patch --in-reply-to' '
762 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" >patch8 &&
763 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
764 grep "^References: <baz@foo.bar>" patch8
767 test_expect_success 'format-patch --signoff' '
768 git format-patch -1 --signoff --stdout >out &&
769 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
772 test_expect_success 'format-patch --notes --signoff' '
773 git notes --ref test add -m "test message" HEAD &&
774 git format-patch -1 --signoff --stdout --notes=test >out &&
775 # Three dashes must come after S-o-b
776 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
777 sed "1,/^Signed-off-by: /d" out | grep "test message" &&
778 # Notes message must come after three dashes
779 ! sed "/^---$/q" out | grep "test message" &&
780 sed "1,/^---$/d" out | grep "test message"
783 test_expect_success 'format-patch notes output control' '
784 git notes add -m "notes config message" HEAD &&
785 test_when_finished git notes remove HEAD &&
787 git format-patch -1 --stdout >out &&
788 ! grep "notes config message" out &&
789 git format-patch -1 --stdout --notes >out &&
790 grep "notes config message" out &&
791 git format-patch -1 --stdout --no-notes >out &&
792 ! grep "notes config message" out &&
793 git format-patch -1 --stdout --notes --no-notes >out &&
794 ! grep "notes config message" out &&
795 git format-patch -1 --stdout --no-notes --notes >out &&
796 grep "notes config message" out &&
798 test_config format.notes true &&
799 git format-patch -1 --stdout >out &&
800 grep "notes config message" out &&
801 git format-patch -1 --stdout --notes >out &&
802 grep "notes config message" out &&
803 git format-patch -1 --stdout --no-notes >out &&
804 ! grep "notes config message" out &&
805 git format-patch -1 --stdout --notes --no-notes >out &&
806 ! grep "notes config message" out &&
807 git format-patch -1 --stdout --no-notes --notes >out &&
808 grep "notes config message" out
811 test_expect_success 'format-patch with multiple notes refs' '
812 git notes --ref note1 add -m "this is note 1" HEAD &&
813 test_when_finished git notes --ref note1 remove HEAD &&
814 git notes --ref note2 add -m "this is note 2" HEAD &&
815 test_when_finished git notes --ref note2 remove HEAD &&
817 git format-patch -1 --stdout >out &&
818 ! grep "this is note 1" out &&
819 ! grep "this is note 2" out &&
820 git format-patch -1 --stdout --notes=note1 >out &&
821 grep "this is note 1" out &&
822 ! grep "this is note 2" out &&
823 git format-patch -1 --stdout --notes=note2 >out &&
824 ! grep "this is note 1" out &&
825 grep "this is note 2" out &&
826 git format-patch -1 --stdout --notes=note1 --notes=note2 >out &&
827 grep "this is note 1" out &&
828 grep "this is note 2" out &&
830 test_config format.notes note1 &&
831 git format-patch -1 --stdout >out &&
832 grep "this is note 1" out &&
833 ! grep "this is note 2" out &&
834 git format-patch -1 --stdout --no-notes >out &&
835 ! grep "this is note 1" out &&
836 ! grep "this is note 2" out &&
837 git format-patch -1 --stdout --notes=note2 >out &&
838 grep "this is note 1" out &&
839 grep "this is note 2" out &&
840 git format-patch -1 --stdout --no-notes --notes=note2 >out &&
841 ! grep "this is note 1" out &&
842 grep "this is note 2" out &&
844 git config --add format.notes note2 &&
845 git format-patch -1 --stdout >out &&
846 grep "this is note 1" out &&
847 grep "this is note 2" out &&
848 git format-patch -1 --stdout --no-notes >out &&
849 ! grep "this is note 1" out &&
850 ! grep "this is note 2" out
853 test_expect_success 'format-patch with multiple notes refs in config' '
854 test_when_finished "test_unconfig format.notes" &&
856 git notes --ref note1 add -m "this is note 1" HEAD &&
857 test_when_finished git notes --ref note1 remove HEAD &&
858 git notes --ref note2 add -m "this is note 2" HEAD &&
859 test_when_finished git notes --ref note2 remove HEAD &&
861 git config format.notes note1 &&
862 git format-patch -1 --stdout >out &&
863 grep "this is note 1" out &&
864 ! grep "this is note 2" out &&
865 git config format.notes note2 &&
866 git format-patch -1 --stdout >out &&
867 ! grep "this is note 1" out &&
868 grep "this is note 2" out &&
869 git config --add format.notes note1 &&
870 git format-patch -1 --stdout >out &&
871 grep "this is note 1" out &&
872 grep "this is note 2" out &&
874 git config --replace-all format.notes note1 &&
875 git config --add format.notes false &&
876 git format-patch -1 --stdout >out &&
877 ! grep "this is note 1" out &&
878 ! grep "this is note 2" out &&
879 git config --add format.notes note2 &&
880 git format-patch -1 --stdout >out &&
881 ! grep "this is note 1" out &&
882 grep "this is note 2" out
885 echo "fatal: --name-only does not make sense" >expect.name-only
886 echo "fatal: --name-status does not make sense" >expect.name-status
887 echo "fatal: --check does not make sense" >expect.check
889 test_expect_success 'options no longer allowed for format-patch' '
890 test_must_fail git format-patch --name-only 2>output &&
891 test_cmp expect.name-only output &&
892 test_must_fail git format-patch --name-status 2>output &&
893 test_cmp expect.name-status output &&
894 test_must_fail git format-patch --check 2>output &&
895 test_cmp expect.check output
898 test_expect_success 'format-patch --numstat should produce a patch' '
899 git format-patch --numstat --stdout main..side >output &&
900 grep "^diff --git a/" output >diff &&
901 test_line_count = 5 diff
904 test_expect_success 'format-patch -- <path>' '
905 git format-patch main..side -- file 2>error &&
906 ! grep "Use .--" error
909 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
910 git format-patch --ignore-if-in-upstream HEAD
913 test_expect_success 'get git version' '
914 git_version=$(git --version) &&
915 git_version=${git_version##* }
918 signature() {
919 printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
922 test_expect_success 'format-patch default signature' '
923 git format-patch --stdout -1 >patch &&
924 tail -n 3 patch >output &&
925 signature >expect &&
926 test_cmp expect output
929 test_expect_success 'format-patch --signature' '
930 git format-patch --stdout --signature="my sig" -1 >patch &&
931 tail -n 3 patch >output &&
932 signature "my sig" >expect &&
933 test_cmp expect output
936 test_expect_success 'format-patch with format.signature config' '
937 git config format.signature "config sig" &&
938 git format-patch --stdout -1 >output &&
939 grep "config sig" output
942 test_expect_success 'format-patch --signature overrides format.signature' '
943 git config format.signature "config sig" &&
944 git format-patch --stdout --signature="overrides" -1 >output &&
945 ! grep "config sig" output &&
946 grep "overrides" output
949 test_expect_success 'format-patch --no-signature ignores format.signature' '
950 git config format.signature "config sig" &&
951 git format-patch --stdout --signature="my sig" --no-signature \
952 -1 >output &&
953 check_patch output &&
954 ! grep "config sig" output &&
955 ! grep "my sig" output &&
956 ! grep "^-- \$" output
959 test_expect_success 'format-patch --signature --cover-letter' '
960 git config --unset-all format.signature &&
961 git format-patch --stdout --signature="my sig" --cover-letter \
962 -1 >output &&
963 grep "my sig" output >sig &&
964 test_line_count = 2 sig
967 test_expect_success 'format.signature="" suppresses signatures' '
968 git config format.signature "" &&
969 git format-patch --stdout -1 >output &&
970 check_patch output &&
971 ! grep "^-- \$" output
974 test_expect_success 'format-patch --no-signature suppresses signatures' '
975 git config --unset-all format.signature &&
976 git format-patch --stdout --no-signature -1 >output &&
977 check_patch output &&
978 ! grep "^-- \$" output
981 test_expect_success 'format-patch --signature="" suppresses signatures' '
982 git format-patch --stdout --signature="" -1 >output &&
983 check_patch output &&
984 ! grep "^-- \$" output
987 test_expect_success 'prepare mail-signature input' '
988 cat >mail-signature <<-\EOF
990 Test User <test.email@kernel.org>
991 http://git.kernel.org/cgit/git/git.git
993 git.kernel.org/?p=git/git.git;a=summary
998 test_expect_success '--signature-file=file works' '
999 git format-patch --stdout --signature-file=mail-signature -1 >output &&
1000 check_patch output &&
1001 sed -e "1,/^-- \$/d" output >actual &&
1003 cat mail-signature && echo
1004 } >expect &&
1005 test_cmp expect actual
1008 test_expect_success 'format.signaturefile works' '
1009 test_config format.signaturefile mail-signature &&
1010 git format-patch --stdout -1 >output &&
1011 check_patch output &&
1012 sed -e "1,/^-- \$/d" output >actual &&
1014 cat mail-signature && echo
1015 } >expect &&
1016 test_cmp expect actual
1019 test_expect_success '--no-signature suppresses format.signaturefile ' '
1020 test_config format.signaturefile mail-signature &&
1021 git format-patch --stdout --no-signature -1 >output &&
1022 check_patch output &&
1023 ! grep "^-- \$" output
1026 test_expect_success '--signature-file overrides format.signaturefile' '
1027 cat >other-mail-signature <<-\EOF &&
1028 Use this other signature instead of mail-signature.
1030 test_config format.signaturefile mail-signature &&
1031 git format-patch --stdout \
1032 --signature-file=other-mail-signature -1 >output &&
1033 check_patch output &&
1034 sed -e "1,/^-- \$/d" output >actual &&
1036 cat other-mail-signature && echo
1037 } >expect &&
1038 test_cmp expect actual
1041 test_expect_success '--signature overrides format.signaturefile' '
1042 test_config format.signaturefile mail-signature &&
1043 git format-patch --stdout --signature="my sig" -1 >output &&
1044 check_patch output &&
1045 grep "my sig" output
1048 test_expect_success TTY 'format-patch --stdout paginates' '
1049 rm -f pager_used &&
1050 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
1051 test_path_is_file pager_used
1054 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
1055 rm -f pager_used &&
1056 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
1057 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
1058 test_path_is_missing pager_used &&
1059 test_path_is_missing .git/pager_used
1062 test_expect_success 'format-patch handles multi-line subjects' '
1063 rm -rf patches/ &&
1064 echo content >>file &&
1065 for i in one two three; do echo $i; done >msg &&
1066 git add file &&
1067 git commit -F msg &&
1068 git format-patch -o patches -1 &&
1069 grep ^Subject: patches/0001-one.patch >actual &&
1070 echo "Subject: [PATCH] one two three" >expect &&
1071 test_cmp expect actual
1074 test_expect_success 'format-patch handles multi-line encoded subjects' '
1075 rm -rf patches/ &&
1076 echo content >>file &&
1077 for i in en två tre; do echo $i; done >msg &&
1078 git add file &&
1079 git commit -F msg &&
1080 git format-patch -o patches -1 &&
1081 grep ^Subject: patches/0001-en.patch >actual &&
1082 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
1083 test_cmp expect actual
1086 M8="foo bar "
1087 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1088 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1089 cat >expect <<'EOF'
1090 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1091 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1092 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1093 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1094 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1095 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1096 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1098 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
1099 echo content >>file &&
1100 git add file &&
1101 git commit -m "$M512" &&
1102 git format-patch --stdout -1 >patch &&
1103 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1104 test_cmp expect subject
1107 M8="föö bar "
1108 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1109 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1110 cat >expect <<'EOF'
1111 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1112 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1113 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1114 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1115 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1116 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1117 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1118 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1119 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1120 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1121 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1122 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1123 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1124 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1125 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1126 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1127 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1128 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1129 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1130 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1131 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1132 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1133 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1134 =?UTF-8?q?bar?=
1136 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
1137 rm -rf patches/ &&
1138 echo content >>file &&
1139 git add file &&
1140 git commit -m "$M512" &&
1141 git format-patch --stdout -1 >patch &&
1142 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1143 test_cmp expect subject
1146 check_author() {
1147 echo content >>file &&
1148 git add file &&
1149 GIT_AUTHOR_NAME=$1 git commit -m author-check &&
1150 git format-patch --stdout -1 >patch &&
1151 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1152 test_cmp expect actual
1155 cat >expect <<'EOF'
1156 From: "Foo B. Bar" <author@example.com>
1158 test_expect_success 'format-patch quotes dot in from-headers' '
1159 check_author "Foo B. Bar"
1162 cat >expect <<'EOF'
1163 From: "Foo \"The Baz\" Bar" <author@example.com>
1165 test_expect_success 'format-patch quotes double-quote in from-headers' '
1166 check_author "Foo \"The Baz\" Bar"
1169 cat >expect <<'EOF'
1170 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1172 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1173 check_author "Föo Bar"
1176 cat >expect <<'EOF'
1177 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1179 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1180 check_author "Föo B. Bar"
1183 cat >expect <<EOF
1184 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1185 <author@example.com>
1187 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1188 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1191 cat >expect <<'EOF'
1192 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1193 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1194 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1196 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1197 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"
1200 cat >expect <<'EOF'
1201 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1202 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1203 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1205 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1206 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"
1209 cat >expect <<'EOF'
1210 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1211 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1212 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1213 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1214 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1216 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1217 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"
1220 cat >expect <<'EOF'
1221 From: Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1222 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1223 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1225 test_expect_success 'format-patch wraps extremely long from-header (non-ASCII without Q-encoding)' '
1226 echo content >>file &&
1227 git add file &&
1228 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" \
1229 git commit -m author-check &&
1230 git format-patch --no-encode-email-headers --stdout -1 >patch &&
1231 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1232 test_cmp expect actual
1235 cat >expect <<'EOF'
1236 Subject: [PATCH] Foö
1238 test_expect_success 'subject lines are unencoded with --no-encode-email-headers' '
1239 echo content >>file &&
1240 git add file &&
1241 git commit -m "Foö" &&
1242 git format-patch --no-encode-email-headers -1 --stdout >patch &&
1243 grep ^Subject: patch >actual &&
1244 test_cmp expect actual
1247 cat >expect <<'EOF'
1248 Subject: [PATCH] Foö
1250 test_expect_success 'subject lines are unencoded with format.encodeEmailHeaders=false' '
1251 echo content >>file &&
1252 git add file &&
1253 git commit -m "Foö" &&
1254 git config format.encodeEmailHeaders false &&
1255 git format-patch -1 --stdout >patch &&
1256 grep ^Subject: patch >actual &&
1257 test_cmp expect actual
1260 cat >expect <<'EOF'
1261 Subject: [PATCH] =?UTF-8?q?Fo=C3=B6?=
1263 test_expect_success '--encode-email-headers overrides format.encodeEmailHeaders' '
1264 echo content >>file &&
1265 git add file &&
1266 git commit -m "Foö" &&
1267 git config format.encodeEmailHeaders false &&
1268 git format-patch --encode-email-headers -1 --stdout >patch &&
1269 grep ^Subject: patch >actual &&
1270 test_cmp expect actual
1273 cat >expect <<'EOF'
1274 Subject: header with . in it
1276 test_expect_success 'subject lines do not have 822 atom-quoting' '
1277 echo content >>file &&
1278 git add file &&
1279 git commit -m "header with . in it" &&
1280 git format-patch -k -1 --stdout >patch &&
1281 grep ^Subject: patch >actual &&
1282 test_cmp expect actual
1285 cat >expect <<'EOF'
1286 Subject: [PREFIX 1/1] header with . in it
1288 test_expect_success 'subject prefixes have space prepended' '
1289 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1290 grep ^Subject: patch >actual &&
1291 test_cmp expect actual
1294 cat >expect <<'EOF'
1295 Subject: [1/1] header with . in it
1297 test_expect_success 'empty subject prefix does not have extra space' '
1298 git format-patch -n -1 --stdout --subject-prefix= >patch &&
1299 grep ^Subject: patch >actual &&
1300 test_cmp expect actual
1303 test_expect_success '--rfc' '
1304 cat >expect <<-\EOF &&
1305 Subject: [RFC PATCH 1/1] header with . in it
1307 git format-patch -n -1 --stdout --rfc >patch &&
1308 grep ^Subject: patch >actual &&
1309 test_cmp expect actual
1312 test_expect_success '--from=ident notices bogus ident' '
1313 test_must_fail git format-patch -1 --stdout --from=foo >patch
1316 test_expect_success '--from=ident replaces author' '
1317 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1318 cat >expect <<-\EOF &&
1319 From: Me <me@example.com>
1321 From: A U Thor <author@example.com>
1324 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1325 test_cmp expect patch.head
1328 test_expect_success '--from uses committer ident' '
1329 git format-patch -1 --stdout --from >patch &&
1330 cat >expect <<-\EOF &&
1331 From: C O Mitter <committer@example.com>
1333 From: A U Thor <author@example.com>
1336 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1337 test_cmp expect patch.head
1340 test_expect_success '--from omits redundant in-body header' '
1341 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1342 cat >expect <<-\EOF &&
1343 From: A U Thor <author@example.com>
1346 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1347 test_cmp expect patch.head
1350 test_expect_success 'in-body headers trigger content encoding' '
1351 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1352 test_when_finished "git reset --hard HEAD^" &&
1353 git format-patch -1 --stdout --from >patch &&
1354 cat >expect <<-\EOF &&
1355 From: C O Mitter <committer@example.com>
1356 Content-Type: text/plain; charset=UTF-8
1358 From: éxötìc <author@example.com>
1361 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" patch >patch.head &&
1362 test_cmp expect patch.head
1365 append_signoff()
1367 C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1368 git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1369 sed -n -e "1,/^---$/p" append_signoff.patch |
1370 egrep -n "^Subject|Sign|^$"
1373 test_expect_success 'signoff: commit with no body' '
1374 append_signoff </dev/null >actual &&
1375 cat <<-\EOF | sed "s/EOL$//" >expect &&
1376 4:Subject: [PATCH] EOL
1378 9:Signed-off-by: C O Mitter <committer@example.com>
1380 test_cmp expect actual
1383 test_expect_success 'signoff: commit with only subject' '
1384 echo subject | append_signoff >actual &&
1385 cat >expect <<-\EOF &&
1386 4:Subject: [PATCH] subject
1388 9:Signed-off-by: C O Mitter <committer@example.com>
1390 test_cmp expect actual
1393 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1394 printf subject | append_signoff >actual &&
1395 cat >expect <<-\EOF &&
1396 4:Subject: [PATCH] subject
1398 9:Signed-off-by: C O Mitter <committer@example.com>
1400 test_cmp expect actual
1403 test_expect_success 'signoff: no existing signoffs' '
1404 append_signoff <<-\EOF >actual &&
1405 subject
1407 body
1409 cat >expect <<-\EOF &&
1410 4:Subject: [PATCH] subject
1413 11:Signed-off-by: C O Mitter <committer@example.com>
1415 test_cmp expect actual
1418 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1419 printf "subject\n\nbody" | append_signoff >actual &&
1420 cat >expect <<-\EOF &&
1421 4:Subject: [PATCH] subject
1424 11:Signed-off-by: C O Mitter <committer@example.com>
1426 test_cmp expect actual
1429 test_expect_success 'signoff: some random signoff' '
1430 append_signoff <<-\EOF >actual &&
1431 subject
1433 body
1435 Signed-off-by: my@house
1437 cat >expect <<-\EOF &&
1438 4:Subject: [PATCH] subject
1441 11:Signed-off-by: my@house
1442 12:Signed-off-by: C O Mitter <committer@example.com>
1444 test_cmp expect actual
1447 test_expect_success 'signoff: misc conforming footer elements' '
1448 append_signoff <<-\EOF >actual &&
1449 subject
1451 body
1453 Signed-off-by: my@house
1454 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1455 Tested-by: Some One <someone@example.com>
1456 Bug: 1234
1458 cat >expect <<-\EOF &&
1459 4:Subject: [PATCH] subject
1462 11:Signed-off-by: my@house
1463 15:Signed-off-by: C O Mitter <committer@example.com>
1465 test_cmp expect actual
1468 test_expect_success 'signoff: some random signoff-alike' '
1469 append_signoff <<-\EOF >actual &&
1470 subject
1472 body
1473 Fooled-by-me: my@house
1475 cat >expect <<-\EOF &&
1476 4:Subject: [PATCH] subject
1479 12:Signed-off-by: C O Mitter <committer@example.com>
1481 test_cmp expect actual
1484 test_expect_success 'signoff: not really a signoff' '
1485 append_signoff <<-\EOF >actual &&
1486 subject
1488 I want to mention about Signed-off-by: here.
1490 cat >expect <<-\EOF &&
1491 4:Subject: [PATCH] subject
1493 9:I want to mention about Signed-off-by: here.
1495 11:Signed-off-by: C O Mitter <committer@example.com>
1497 test_cmp expect actual
1500 test_expect_success 'signoff: not really a signoff (2)' '
1501 append_signoff <<-\EOF >actual &&
1502 subject
1504 My unfortunate
1505 Signed-off-by: example happens to be wrapped here.
1507 cat >expect <<-\EOF &&
1508 4:Subject: [PATCH] subject
1510 10:Signed-off-by: example happens to be wrapped here.
1511 11:Signed-off-by: C O Mitter <committer@example.com>
1513 test_cmp expect actual
1516 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1517 append_signoff <<-\EOF >actual &&
1518 subject
1520 Signed-off-by: my@house
1521 Signed-off-by: your@house
1523 A lot of houses.
1525 cat >expect <<-\EOF &&
1526 4:Subject: [PATCH] subject
1528 9:Signed-off-by: my@house
1529 10:Signed-off-by: your@house
1532 14:Signed-off-by: C O Mitter <committer@example.com>
1534 test_cmp expect actual
1537 test_expect_success 'signoff: the same signoff at the end' '
1538 append_signoff <<-\EOF >actual &&
1539 subject
1541 body
1543 Signed-off-by: C O Mitter <committer@example.com>
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: the same signoff at the end, no trailing NL' '
1555 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1556 append_signoff >actual &&
1557 cat >expect <<-\EOF &&
1558 4:Subject: [PATCH] subject
1560 9:Signed-off-by: C O Mitter <committer@example.com>
1562 test_cmp expect actual
1565 test_expect_success 'signoff: the same signoff NOT at the end' '
1566 append_signoff <<-\EOF >actual &&
1567 subject
1569 body
1571 Signed-off-by: C O Mitter <committer@example.com>
1572 Signed-off-by: my@house
1574 cat >expect <<-\EOF &&
1575 4:Subject: [PATCH] subject
1578 11:Signed-off-by: C O Mitter <committer@example.com>
1579 12:Signed-off-by: my@house
1581 test_cmp expect actual
1584 test_expect_success 'signoff: tolerate garbage in conforming footer' '
1585 append_signoff <<-\EOF >actual &&
1586 subject
1588 body
1590 Tested-by: my@house
1591 Some Trash
1592 Signed-off-by: C O Mitter <committer@example.com>
1594 cat >expect <<-\EOF &&
1595 4:Subject: [PATCH] subject
1598 13:Signed-off-by: C O Mitter <committer@example.com>
1600 test_cmp expect actual
1603 test_expect_success 'signoff: respect trailer config' '
1604 append_signoff <<-\EOF >actual &&
1605 subject
1607 Myfooter: x
1608 Some Trash
1610 cat >expect <<-\EOF &&
1611 4:Subject: [PATCH] subject
1614 12:Signed-off-by: C O Mitter <committer@example.com>
1616 test_cmp expect actual &&
1618 test_config trailer.Myfooter.ifexists add &&
1619 append_signoff <<-\EOF >actual &&
1620 subject
1622 Myfooter: x
1623 Some Trash
1625 cat >expect <<-\EOF &&
1626 4:Subject: [PATCH] subject
1628 11:Signed-off-by: C O Mitter <committer@example.com>
1630 test_cmp expect actual
1633 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1634 append_signoff <<-\EOF >actual &&
1635 subject
1637 body
1639 Reviewed-id: Noone
1640 Tested-by: my@house
1641 Change-id: Ideadbeef
1642 Signed-off-by: C O Mitter <committer@example.com>
1643 Bug: 1234
1645 cat >expect <<-\EOF &&
1646 4:Subject: [PATCH] subject
1649 14:Signed-off-by: C O Mitter <committer@example.com>
1651 test_cmp expect actual
1654 test_expect_success 'format patch ignores color.ui' '
1655 test_unconfig color.ui &&
1656 git format-patch --stdout -1 >expect &&
1657 test_config color.ui always &&
1658 git format-patch --stdout -1 >actual &&
1659 test_cmp expect actual
1662 test_expect_success 'format patch respects diff.relative' '
1663 rm -rf subdir &&
1664 mkdir subdir &&
1665 echo other content >subdir/file2 &&
1666 git add subdir/file2 &&
1667 git commit -F msg &&
1668 test_unconfig diff.relative &&
1669 git format-patch --relative=subdir --stdout -1 >expect &&
1670 test_config diff.relative true &&
1671 git -C subdir format-patch --stdout -1 >actual &&
1672 test_cmp expect actual
1675 test_expect_success 'cover letter with invalid --cover-from-description and config' '
1676 test_config branch.rebuild-1.description "config subject
1678 body" &&
1679 test_must_fail git format-patch --cover-letter --cover-from-description garbage main &&
1680 test_config format.coverFromDescription garbage &&
1681 test_must_fail git format-patch --cover-letter main
1684 test_expect_success 'cover letter with format.coverFromDescription = default' '
1685 test_config branch.rebuild-1.description "config subject
1687 body" &&
1688 test_config format.coverFromDescription default &&
1689 git checkout rebuild-1 &&
1690 git format-patch --stdout --cover-letter main >actual &&
1691 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1692 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1693 grep "^config subject$" actual &&
1694 grep "^body$" actual
1697 test_expect_success 'cover letter with --cover-from-description default' '
1698 test_config branch.rebuild-1.description "config subject
1700 body" &&
1701 git checkout rebuild-1 &&
1702 git format-patch --stdout --cover-letter --cover-from-description default main >actual &&
1703 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1704 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1705 grep "^config subject$" actual &&
1706 grep "^body$" actual
1709 test_expect_success 'cover letter with format.coverFromDescription = none' '
1710 test_config branch.rebuild-1.description "config subject
1712 body" &&
1713 test_config format.coverFromDescription none &&
1714 git checkout rebuild-1 &&
1715 git format-patch --stdout --cover-letter main >actual &&
1716 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1717 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1718 ! grep "^config subject$" actual &&
1719 ! grep "^body$" actual
1722 test_expect_success 'cover letter with --cover-from-description none' '
1723 test_config branch.rebuild-1.description "config subject
1725 body" &&
1726 git checkout rebuild-1 &&
1727 git format-patch --stdout --cover-letter --cover-from-description none main >actual &&
1728 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1729 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1730 ! grep "^config subject$" actual &&
1731 ! grep "^body$" actual
1734 test_expect_success 'cover letter with format.coverFromDescription = message' '
1735 test_config branch.rebuild-1.description "config subject
1737 body" &&
1738 test_config format.coverFromDescription message &&
1739 git checkout rebuild-1 &&
1740 git format-patch --stdout --cover-letter main >actual &&
1741 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1742 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1743 grep "^config subject$" actual &&
1744 grep "^body$" actual
1747 test_expect_success 'cover letter with --cover-from-description message' '
1748 test_config branch.rebuild-1.description "config subject
1750 body" &&
1751 git checkout rebuild-1 &&
1752 git format-patch --stdout --cover-letter --cover-from-description message main >actual &&
1753 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1754 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1755 grep "^config subject$" actual &&
1756 grep "^body$" actual
1759 test_expect_success 'cover letter with format.coverFromDescription = subject' '
1760 test_config branch.rebuild-1.description "config subject
1762 body" &&
1763 test_config format.coverFromDescription subject &&
1764 git checkout rebuild-1 &&
1765 git format-patch --stdout --cover-letter main >actual &&
1766 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1767 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1768 ! grep "^config subject$" actual &&
1769 grep "^body$" actual
1772 test_expect_success 'cover letter with --cover-from-description subject' '
1773 test_config branch.rebuild-1.description "config subject
1775 body" &&
1776 git checkout rebuild-1 &&
1777 git format-patch --stdout --cover-letter --cover-from-description subject main >actual &&
1778 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1779 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1780 ! grep "^config subject$" actual &&
1781 grep "^body$" actual
1784 test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' '
1785 test_config branch.rebuild-1.description "config subject
1787 body" &&
1788 test_config format.coverFromDescription auto &&
1789 git checkout rebuild-1 &&
1790 git format-patch --stdout --cover-letter main >actual &&
1791 grep "^Subject: \[PATCH 0/2\] config subject$" 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 auto (short subject line)' '
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 auto main >actual &&
1803 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1804 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1805 ! grep "^config subject$" actual &&
1806 grep "^body$" actual
1809 test_expect_success 'cover letter with format.coverFromDescription = auto (long subject line)' '
1810 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
1812 body" &&
1813 test_config format.coverFromDescription auto &&
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 "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1819 grep "^body$" actual
1822 test_expect_success 'cover letter with --cover-from-description auto (long subject line)' '
1823 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
1825 body" &&
1826 git checkout rebuild-1 &&
1827 git format-patch --stdout --cover-letter --cover-from-description auto main >actual &&
1828 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1829 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1830 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1831 grep "^body$" actual
1834 test_expect_success 'cover letter with command-line --cover-from-description overrides config' '
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 --cover-from-description subject main >actual &&
1841 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1842 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1843 ! grep "^config subject$" actual &&
1844 grep "^body$" actual
1847 test_expect_success 'cover letter using branch description (1)' '
1848 git checkout rebuild-1 &&
1849 test_config branch.rebuild-1.description hello &&
1850 git format-patch --stdout --cover-letter main >actual &&
1851 grep hello actual
1854 test_expect_success 'cover letter using branch description (2)' '
1855 git checkout rebuild-1 &&
1856 test_config branch.rebuild-1.description hello &&
1857 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1858 grep hello actual
1861 test_expect_success 'cover letter using branch description (3)' '
1862 git checkout rebuild-1 &&
1863 test_config branch.rebuild-1.description hello &&
1864 git format-patch --stdout --cover-letter ^main rebuild-1 >actual &&
1865 grep hello actual
1868 test_expect_success 'cover letter using branch description (4)' '
1869 git checkout rebuild-1 &&
1870 test_config branch.rebuild-1.description hello &&
1871 git format-patch --stdout --cover-letter main.. >actual &&
1872 grep hello actual
1875 test_expect_success 'cover letter using branch description (5)' '
1876 git checkout rebuild-1 &&
1877 test_config branch.rebuild-1.description hello &&
1878 git format-patch --stdout --cover-letter -2 HEAD >actual &&
1879 grep hello actual
1882 test_expect_success 'cover letter using branch description (6)' '
1883 git checkout rebuild-1 &&
1884 test_config branch.rebuild-1.description hello &&
1885 git format-patch --stdout --cover-letter -2 >actual &&
1886 grep hello actual
1889 test_expect_success 'cover letter with nothing' '
1890 git format-patch --stdout --cover-letter >actual &&
1891 test_line_count = 0 actual
1894 test_expect_success 'cover letter auto' '
1895 mkdir -p tmp &&
1896 test_when_finished "rm -rf tmp;
1897 git config --unset format.coverletter" &&
1899 git config format.coverletter auto &&
1900 git format-patch -o tmp -1 >list &&
1901 test_line_count = 1 list &&
1902 git format-patch -o tmp -2 >list &&
1903 test_line_count = 3 list
1906 test_expect_success 'cover letter auto user override' '
1907 mkdir -p tmp &&
1908 test_when_finished "rm -rf tmp;
1909 git config --unset format.coverletter" &&
1911 git config format.coverletter auto &&
1912 git format-patch -o tmp --cover-letter -1 >list &&
1913 test_line_count = 2 list &&
1914 git format-patch -o tmp --cover-letter -2 >list &&
1915 test_line_count = 3 list &&
1916 git format-patch -o tmp --no-cover-letter -1 >list &&
1917 test_line_count = 1 list &&
1918 git format-patch -o tmp --no-cover-letter -2 >list &&
1919 test_line_count = 2 list
1922 test_expect_success 'format-patch --zero-commit' '
1923 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1924 grep "^From " patch2 | sort | uniq >actual &&
1925 echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
1926 test_cmp expect actual
1929 test_expect_success 'From line has expected format' '
1930 git format-patch --stdout v2..v1 >patch2 &&
1931 grep "^From " patch2 >from &&
1932 grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1933 test_cmp from filtered
1936 test_expect_success 'format-patch -o with no leading directories' '
1937 rm -fr patches &&
1938 git format-patch -o patches main..side &&
1939 count=$(git rev-list --count main..side) &&
1940 ls patches >list &&
1941 test_line_count = $count list
1944 test_expect_success 'format-patch -o with leading existing directories' '
1945 rm -rf existing-dir &&
1946 mkdir existing-dir &&
1947 git format-patch -o existing-dir/patches main..side &&
1948 count=$(git rev-list --count main..side) &&
1949 ls existing-dir/patches >list &&
1950 test_line_count = $count list
1953 test_expect_success 'format-patch -o with leading non-existing directories' '
1954 rm -rf non-existing-dir &&
1955 git format-patch -o non-existing-dir/patches main..side &&
1956 count=$(git rev-list --count main..side) &&
1957 test_path_is_dir non-existing-dir &&
1958 ls non-existing-dir/patches >list &&
1959 test_line_count = $count list
1962 test_expect_success 'format-patch format.outputDirectory option' '
1963 test_config format.outputDirectory patches &&
1964 rm -fr patches &&
1965 git format-patch main..side &&
1966 count=$(git rev-list --count main..side) &&
1967 ls patches >list &&
1968 test_line_count = $count list
1971 test_expect_success 'format-patch -o overrides format.outputDirectory' '
1972 test_config format.outputDirectory patches &&
1973 rm -fr patches patchset &&
1974 git format-patch main..side -o patchset &&
1975 test_path_is_missing patches &&
1976 test_path_is_dir patchset
1979 test_expect_success 'format-patch forbids multiple outputs' '
1980 rm -fr outfile outdir &&
1981 test_must_fail \
1982 git format-patch --stdout --output-directory=outdir &&
1983 test_must_fail \
1984 git format-patch --stdout --output=outfile &&
1985 test_must_fail \
1986 git format-patch --output=outfile --output-directory=outdir
1989 test_expect_success 'configured outdir does not conflict with output options' '
1990 rm -fr outfile outdir &&
1991 test_config format.outputDirectory outdir &&
1992 git format-patch --stdout &&
1993 test_path_is_missing outdir &&
1994 git format-patch --output=outfile &&
1995 test_path_is_missing outdir
1998 test_expect_success 'format-patch --output' '
1999 rm -fr outfile &&
2000 git format-patch -3 --stdout HEAD >expect &&
2001 git format-patch -3 --output=outfile HEAD &&
2002 test_cmp expect outfile
2005 test_expect_success 'format-patch --cover-letter --output' '
2006 rm -fr outfile &&
2007 git format-patch --cover-letter -3 --stdout HEAD >expect &&
2008 git format-patch --cover-letter -3 --output=outfile HEAD &&
2009 test_cmp expect outfile
2012 test_expect_success 'format-patch --base' '
2013 git checkout patchid &&
2015 git format-patch --stdout --base=HEAD~3 -1 >patch &&
2016 tail -n 7 patch >actual1 &&
2018 git format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&
2019 tail -n 7 patch >actual2 &&
2021 echo >expect &&
2022 git rev-parse HEAD~3 >commit-id-base &&
2023 echo "base-commit: $(cat commit-id-base)" >>expect &&
2025 git show --patch HEAD~2 >patch &&
2026 git patch-id --stable <patch >patch.id.raw &&
2027 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2029 git show --patch HEAD~1 >patch &&
2030 git patch-id --stable <patch >patch.id.raw &&
2031 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2033 signature >>expect &&
2034 test_cmp expect actual1 &&
2035 test_cmp expect actual2 &&
2037 echo >fail &&
2038 echo "base-commit: $(cat commit-id-base)" >>fail &&
2040 git show --patch HEAD~2 >patch &&
2041 git patch-id --unstable <patch >patch.id.raw &&
2042 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2044 git show --patch HEAD~1 >patch &&
2045 git patch-id --unstable <patch >patch.id.raw &&
2046 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2048 signature >>fail &&
2049 ! test_cmp fail actual1 &&
2050 ! test_cmp fail actual2
2053 test_expect_success 'format-patch --base errors out when base commit is in revision list' '
2054 test_must_fail git format-patch --base=HEAD -2 &&
2055 test_must_fail git format-patch --base=HEAD~1 -2 &&
2056 git format-patch --stdout --base=HEAD~2 -2 >patch &&
2057 grep "^base-commit:" patch >actual &&
2058 git rev-parse HEAD~2 >commit-id-base &&
2059 echo "base-commit: $(cat commit-id-base)" >expect &&
2060 test_cmp expect actual
2063 test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
2064 # For history as below:
2066 # ---Q---P---Z---Y---*---X
2067 # \ /
2068 # ------------W
2070 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
2071 git checkout -b topic1 main &&
2072 git rev-parse HEAD >commit-id-base &&
2073 test_commit P &&
2074 git rev-parse HEAD >commit-id-P &&
2075 test_commit Z &&
2076 git rev-parse HEAD >commit-id-Z &&
2077 test_commit Y &&
2078 git checkout -b topic2 main &&
2079 test_commit W &&
2080 git merge topic1 &&
2081 test_commit X &&
2082 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
2083 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
2084 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
2085 grep "^base-commit:" patch >actual &&
2086 echo "base-commit: $(cat commit-id-base)" >expect &&
2087 test_cmp expect actual
2090 test_expect_success 'format-patch --base=auto' '
2091 git checkout -b upstream main &&
2092 git checkout -b local upstream &&
2093 git branch --set-upstream-to=upstream &&
2094 test_commit N1 &&
2095 test_commit N2 &&
2096 git format-patch --stdout --base=auto -2 >patch &&
2097 grep "^base-commit:" patch >actual &&
2098 git rev-parse upstream >commit-id-base &&
2099 echo "base-commit: $(cat commit-id-base)" >expect &&
2100 test_cmp expect actual
2103 test_expect_success 'format-patch errors out when history involves criss-cross' '
2104 # setup criss-cross history
2106 # B---M1---D
2107 # / \ /
2108 # A X
2109 # \ / \
2110 # C---M2---E
2112 git checkout main &&
2113 test_commit A &&
2114 git checkout -b xb main &&
2115 test_commit B &&
2116 git checkout -b xc main &&
2117 test_commit C &&
2118 git checkout -b xbc xb -- &&
2119 git merge xc &&
2120 git checkout -b xcb xc -- &&
2121 git branch --set-upstream-to=xbc &&
2122 git merge xb &&
2123 git checkout xbc &&
2124 test_commit D &&
2125 git checkout xcb &&
2126 test_commit E &&
2127 test_must_fail git format-patch --base=auto -1
2130 test_expect_success 'format-patch format.useAutoBase whenAble history involves criss-cross' '
2131 test_config format.useAutoBase whenAble &&
2132 git format-patch -1 >patch &&
2133 ! grep "^base-commit:" patch
2136 test_expect_success 'format-patch format.useAutoBase option' '
2137 git checkout local &&
2138 test_config format.useAutoBase true &&
2139 git format-patch --stdout -1 >patch &&
2140 grep "^base-commit:" patch >actual &&
2141 git rev-parse upstream >commit-id-base &&
2142 echo "base-commit: $(cat commit-id-base)" >expect &&
2143 test_cmp expect actual
2146 test_expect_success 'format-patch format.useAutoBase option with whenAble' '
2147 git checkout local &&
2148 test_config format.useAutoBase whenAble &&
2149 git format-patch --stdout -1 >patch &&
2150 grep "^base-commit:" patch >actual &&
2151 git rev-parse upstream >commit-id-base &&
2152 echo "base-commit: $(cat commit-id-base)" >expect &&
2153 test_cmp expect actual
2156 test_expect_success 'format-patch --base overrides format.useAutoBase' '
2157 test_config format.useAutoBase true &&
2158 git format-patch --stdout --base=HEAD~1 -1 >patch &&
2159 grep "^base-commit:" patch >actual &&
2160 git rev-parse HEAD~1 >commit-id-base &&
2161 echo "base-commit: $(cat commit-id-base)" >expect &&
2162 test_cmp expect actual
2165 test_expect_success 'format-patch --no-base overrides format.useAutoBase' '
2166 test_config format.useAutoBase true &&
2167 git format-patch --stdout --no-base -1 >patch &&
2168 ! grep "^base-commit:" patch
2171 test_expect_success 'format-patch --no-base overrides format.useAutoBase whenAble' '
2172 test_config format.useAutoBase whenAble &&
2173 git format-patch --stdout --no-base -1 >patch &&
2174 ! grep "^base-commit:" patch
2177 test_expect_success 'format-patch --base with --attach' '
2178 git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
2179 sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
2180 patch >actual &&
2181 test_write_lines 1 2 >expect &&
2182 test_cmp expect actual
2184 test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
2185 test_when_finished "rm -fr patches" &&
2186 git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
2187 ! egrep "^--+mimemime" patches/0000*.patch &&
2188 egrep "^--+mimemime$" patches/0001*.patch >output &&
2189 test_line_count = 2 output &&
2190 egrep "^--+mimemime--$" patches/0001*.patch >output &&
2191 test_line_count = 1 output
2194 test_expect_success 'format-patch --pretty=mboxrd' '
2195 sp=" " &&
2196 cat >msg <<-INPUT_END &&
2197 mboxrd should escape the body
2199 From could trip up a loose mbox parser
2200 >From extra escape for reversibility
2201 >>From extra escape for reversibility 2
2202 from lower case not escaped
2203 Fromm bad speling not escaped
2204 From with leading space not escaped
2207 From
2208 From$sp
2209 From $sp
2210 From $sp
2211 INPUT_END
2213 cat >expect <<-INPUT_END &&
2214 >From could trip up a loose mbox parser
2215 >>From extra escape for reversibility
2216 >>>From extra escape for reversibility 2
2217 from lower case not escaped
2218 Fromm bad speling not escaped
2219 From with leading space not escaped
2222 From
2223 From
2224 From
2225 From
2226 INPUT_END
2228 C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
2229 git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
2230 git grep -h --no-index -A11 \
2231 "^>From could trip up a loose mbox parser" patch >actual &&
2232 test_cmp expect actual
2235 test_expect_success 'interdiff: setup' '
2236 git checkout -b boop main &&
2237 test_commit fnorp blorp &&
2238 test_commit fleep blorp
2241 test_expect_success 'interdiff: cover-letter' '
2242 sed "y/q/ /" >expect <<-\EOF &&
2243 +fleep
2246 git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
2247 test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch &&
2248 test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch &&
2249 sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual &&
2250 test_cmp expect actual
2253 test_expect_success 'interdiff: reroll-count' '
2254 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2255 test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2258 test_expect_success 'interdiff: solo-patch' '
2259 cat >expect <<-\EOF &&
2260 +fleep
2263 git format-patch --interdiff=boop~2 -1 boop &&
2264 test_i18ngrep "^Interdiff:$" 0001-fleep.patch &&
2265 sed "1,/^ @@ /d; /^$/q" 0001-fleep.patch >actual &&
2266 test_cmp expect actual
2269 test_done