mailmap doc: create a new "gitmailmap(5)" man page
[git/debian.git] / t / t4014-format-patch.sh
blobc5e5e0da3feef439415dbf9cfd235140eba7d0d9
1 #!/bin/sh
3 # Copyright (c) 2006 Junio C Hamano
6 test_description='various format-patch tests'
8 . ./test-lib.sh
9 . "$TEST_DIRECTORY"/lib-terminal.sh
11 test_expect_success setup '
12 for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
13 cat file >elif &&
14 git add file elif &&
15 test_tick &&
16 git commit -m Initial &&
17 git checkout -b side &&
19 for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
20 test_chmod +x elif &&
21 test_tick &&
22 git commit -m "Side changes #1" &&
24 for i in D E F; do echo "$i"; done >>file &&
25 git update-index file &&
26 test_tick &&
27 git commit -m "Side changes #2" &&
28 git tag C2 &&
30 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
31 git update-index file &&
32 test_tick &&
33 git commit -m "Side changes #3 with \\n backslash-n in it." &&
35 git checkout master &&
36 git diff-tree -p C2 >patch &&
37 git apply --index <patch &&
38 test_tick &&
39 git commit -m "Master accepts moral equivalent of #2" &&
41 git checkout side &&
42 git checkout -b patchid &&
43 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file2 &&
44 for i in 1 2 3 A 4 B C 7 8 9 10 D E F 5 6; do echo "$i"; done >file3 &&
45 for i in 8 9 10; do echo "$i"; done >file &&
46 git add file file2 file3 &&
47 test_tick &&
48 git commit -m "patchid 1" &&
49 for i in 4 A B 7 8 9 10; do echo "$i"; done >file2 &&
50 for i in 8 9 10 5 6; do echo "$i"; done >file3 &&
51 git add file2 file3 &&
52 test_tick &&
53 git commit -m "patchid 2" &&
54 for i in 10 5 6; do echo "$i"; done >file &&
55 git add file &&
56 test_tick &&
57 git commit -m "patchid 3" &&
59 git checkout master
62 test_expect_success 'format-patch --ignore-if-in-upstream' '
63 git format-patch --stdout master..side >patch0 &&
64 grep "^From " patch0 >from0 &&
65 test_line_count = 3 from0
68 test_expect_success 'format-patch --ignore-if-in-upstream' '
69 git format-patch --stdout \
70 --ignore-if-in-upstream master..side >patch1 &&
71 grep "^From " patch1 >from1 &&
72 test_line_count = 2 from1
75 test_expect_success 'format-patch --ignore-if-in-upstream handles tags' '
76 git tag -a v1 -m tag side &&
77 git tag -a v2 -m tag master &&
78 git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
79 grep "^From " patch1 >from1 &&
80 test_line_count = 2 from1
83 test_expect_success "format-patch doesn't consider merge commits" '
84 git checkout -b feature master &&
85 echo "Another line" >>file &&
86 test_tick &&
87 git commit -am "Feature branch change #1" &&
88 echo "Yet another line" >>file &&
89 test_tick &&
90 git commit -am "Feature branch change #2" &&
91 git checkout -b merger master &&
92 test_tick &&
93 git merge --no-ff feature &&
94 git format-patch -3 --stdout >patch &&
95 grep "^From " patch >from &&
96 test_line_count = 3 from
99 test_expect_success 'format-patch result applies' '
100 git checkout -b rebuild-0 master &&
101 git am -3 patch0 &&
102 git rev-list master.. >list &&
103 test_line_count = 2 list
106 test_expect_success 'format-patch --ignore-if-in-upstream result applies' '
107 git checkout -b rebuild-1 master &&
108 git am -3 patch1 &&
109 git rev-list master.. >list &&
110 test_line_count = 2 list
113 test_expect_success 'commit did not screw up the log message' '
114 git cat-file commit side >actual &&
115 grep "^Side .* with .* backslash-n" actual
118 test_expect_success 'format-patch did not screw up the log message' '
119 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
120 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
123 test_expect_success 'replay did not screw up the log message' '
124 git cat-file commit rebuild-1 >actual &&
125 grep "^Side .* with .* backslash-n" actual
128 test_expect_success 'extra headers' '
129 git config format.headers "To: R E Cipient <rcipient@example.com>
130 " &&
131 git config --add format.headers "Cc: S E Cipient <scipient@example.com>
132 " &&
133 git format-patch --stdout master..side >patch2 &&
134 sed -e "/^\$/q" patch2 >hdrs2 &&
135 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
136 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
139 test_expect_success 'extra headers without newlines' '
140 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
141 git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
142 git format-patch --stdout master..side >patch3 &&
143 sed -e "/^\$/q" patch3 >hdrs3 &&
144 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
145 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
148 test_expect_success 'extra headers with multiple To:s' '
149 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
150 git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
151 git format-patch --stdout master..side >patch4 &&
152 sed -e "/^\$/q" patch4 >hdrs4 &&
153 grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
154 grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
157 test_expect_success 'additional command line cc (ascii)' '
158 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
159 git format-patch --cc="S E Cipient <scipient@example.com>" --stdout master..side >patch5 &&
160 sed -e "/^\$/q" patch5 >hdrs5 &&
161 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
162 grep "^ *S E Cipient <scipient@example.com>\$" hdrs5
165 test_expect_failure 'additional command line cc (rfc822)' '
166 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
167 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side >patch5 &&
168 sed -e "/^\$/q" patch5 >hdrs5 &&
169 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
170 grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" hdrs5
173 test_expect_success 'command line headers' '
174 git config --unset-all format.headers &&
175 git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side >patch6 &&
176 sed -e "/^\$/q" patch6 >hdrs6 &&
177 grep "^Cc: R E Cipient <rcipient@example.com>\$" hdrs6
180 test_expect_success 'configuration headers and command line headers' '
181 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
182 git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side >patch7 &&
183 sed -e "/^\$/q" patch7 >hdrs7 &&
184 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs7 &&
185 grep "^ *S E Cipient <scipient@example.com>\$" hdrs7
188 test_expect_success 'command line To: header (ascii)' '
189 git config --unset-all format.headers &&
190 git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side >patch8 &&
191 sed -e "/^\$/q" patch8 >hdrs8 &&
192 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs8
195 test_expect_failure 'command line To: header (rfc822)' '
196 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side >patch8 &&
197 sed -e "/^\$/q" patch8 >hdrs8 &&
198 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs8
201 test_expect_failure 'command line To: header (rfc2047)' '
202 git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side >patch8 &&
203 sed -e "/^\$/q" patch8 >hdrs8 &&
204 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs8
207 test_expect_success 'configuration To: header (ascii)' '
208 git config format.to "R E Cipient <rcipient@example.com>" &&
209 git format-patch --stdout master..side >patch9 &&
210 sed -e "/^\$/q" patch9 >hdrs9 &&
211 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs9
214 test_expect_failure 'configuration To: header (rfc822)' '
215 git config format.to "R. E. Cipient <rcipient@example.com>" &&
216 git format-patch --stdout master..side >patch9 &&
217 sed -e "/^\$/q" patch9 >hdrs9 &&
218 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs9
221 test_expect_failure 'configuration To: header (rfc2047)' '
222 git config format.to "R Ä Cipient <rcipient@example.com>" &&
223 git format-patch --stdout master..side >patch9 &&
224 sed -e "/^\$/q" patch9 >hdrs9 &&
225 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs9
228 # check_patch <patch>: Verify that <patch> looks like a half-sane
229 # patch email to avoid a false positive with !grep
230 check_patch () {
231 grep -e "^From:" "$1" &&
232 grep -e "^Date:" "$1" &&
233 grep -e "^Subject:" "$1"
236 test_expect_success 'format.from=false' '
237 git -c format.from=false format-patch --stdout master..side >patch &&
238 sed -e "/^\$/q" patch >hdrs &&
239 check_patch patch &&
240 ! grep "^From: C O Mitter <committer@example.com>\$" hdrs
243 test_expect_success 'format.from=true' '
244 git -c format.from=true format-patch --stdout master..side >patch &&
245 sed -e "/^\$/q" patch >hdrs &&
246 check_patch hdrs &&
247 grep "^From: C O Mitter <committer@example.com>\$" hdrs
250 test_expect_success 'format.from with address' '
251 git -c format.from="F R Om <from@example.com>" format-patch --stdout master..side >patch &&
252 sed -e "/^\$/q" patch >hdrs &&
253 check_patch hdrs &&
254 grep "^From: F R Om <from@example.com>\$" hdrs
257 test_expect_success '--no-from overrides format.from' '
258 git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout master..side >patch &&
259 sed -e "/^\$/q" patch >hdrs &&
260 check_patch hdrs &&
261 ! grep "^From: F R Om <from@example.com>\$" hdrs
264 test_expect_success '--from overrides format.from' '
265 git -c format.from="F R Om <from@example.com>" format-patch --from --stdout master..side >patch &&
266 sed -e "/^\$/q" patch >hdrs &&
267 check_patch hdrs &&
268 ! grep "^From: F R Om <from@example.com>\$" hdrs
271 test_expect_success '--no-to overrides config.to' '
272 git config --replace-all format.to \
273 "R E Cipient <rcipient@example.com>" &&
274 git format-patch --no-to --stdout master..side >patch10 &&
275 sed -e "/^\$/q" patch10 >hdrs10 &&
276 check_patch hdrs10 &&
277 ! grep "^To: R E Cipient <rcipient@example.com>\$" hdrs10
280 test_expect_success '--no-to and --to replaces config.to' '
281 git config --replace-all format.to \
282 "Someone <someone@out.there>" &&
283 git format-patch --no-to --to="Someone Else <else@out.there>" \
284 --stdout master..side >patch11 &&
285 sed -e "/^\$/q" patch11 >hdrs11 &&
286 check_patch hdrs11 &&
287 ! grep "^To: Someone <someone@out.there>\$" hdrs11 &&
288 grep "^To: Someone Else <else@out.there>\$" hdrs11
291 test_expect_success '--no-cc overrides config.cc' '
292 git config --replace-all format.cc \
293 "C E Cipient <rcipient@example.com>" &&
294 git format-patch --no-cc --stdout master..side >patch12 &&
295 sed -e "/^\$/q" patch12 >hdrs12 &&
296 check_patch hdrs12 &&
297 ! grep "^Cc: C E Cipient <rcipient@example.com>\$" hdrs12
300 test_expect_success '--no-add-header overrides config.headers' '
301 git config --replace-all format.headers \
302 "Header1: B E Cipient <rcipient@example.com>" &&
303 git format-patch --no-add-header --stdout master..side >patch13 &&
304 sed -e "/^\$/q" patch13 >hdrs13 &&
305 check_patch hdrs13 &&
306 ! grep "^Header1: B E Cipient <rcipient@example.com>\$" hdrs13
309 test_expect_success 'multiple files' '
310 rm -rf patches/ &&
311 git checkout side &&
312 git format-patch -o patches/ master &&
313 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
316 test_expect_success 'filename length limit' '
317 test_when_finished "rm -f 000*" &&
318 rm -rf 000[1-9]-*.patch &&
319 for len in 15 25 35
321 git format-patch --filename-max-length=$len -3 side &&
322 max=$(
323 for patch in 000[1-9]-*.patch
325 echo "$patch" | wc -c
326 done |
327 sort -nr |
328 head -n 1
329 ) &&
330 test $max -le $len || return 1
331 done
334 test_expect_success 'filename length limit from config' '
335 test_when_finished "rm -f 000*" &&
336 rm -rf 000[1-9]-*.patch &&
337 for len in 15 25 35
339 git -c format.filenameMaxLength=$len format-patch -3 side &&
340 max=$(
341 for patch in 000[1-9]-*.patch
343 echo "$patch" | wc -c
344 done |
345 sort -nr |
346 head -n 1
347 ) &&
348 test $max -le $len || return 1
349 done
352 test_expect_success 'filename limit applies only to basename' '
353 test_when_finished "rm -rf patches/" &&
354 rm -rf patches/ &&
355 for len in 15 25 35
357 git format-patch -o patches --filename-max-length=$len -3 side &&
358 max=$(
359 for patch in patches/000[1-9]-*.patch
361 echo "${patch#patches/}" | wc -c
362 done |
363 sort -nr |
364 head -n 1
365 ) &&
366 test $max -le $len || return 1
367 done
370 test_expect_success 'reroll count' '
371 rm -fr patches &&
372 git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
373 ! grep -v "^patches/v4-000[0-3]-" list &&
374 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
375 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
378 test_expect_success 'reroll count (-v)' '
379 rm -fr patches &&
380 git format-patch -o patches --cover-letter -v4 master..side >list &&
381 ! grep -v "^patches/v4-000[0-3]-" list &&
382 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
383 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
386 check_threading () {
387 expect="$1" &&
388 shift &&
389 git format-patch --stdout "$@" >patch &&
390 # Prints everything between the Message-ID and In-Reply-To,
391 # and replaces all Message-ID-lookalikes by a sequence number
392 perl -ne '
393 if (/^(message-id|references|in-reply-to)/i) {
394 $printing = 1;
395 } elsif (/^\S/) {
396 $printing = 0;
398 if ($printing) {
399 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
400 for $k (keys %h) {s/$k/$h{$k}/};
401 print;
403 print "---\n" if /^From /i;
404 ' <patch >actual &&
405 test_cmp "$expect" actual
408 cat >>expect.no-threading <<EOF
414 test_expect_success 'no threading' '
415 git checkout side &&
416 check_threading expect.no-threading master
419 cat >expect.thread <<EOF
421 Message-Id: <0>
423 Message-Id: <1>
424 In-Reply-To: <0>
425 References: <0>
427 Message-Id: <2>
428 In-Reply-To: <0>
429 References: <0>
432 test_expect_success 'thread' '
433 check_threading expect.thread --thread master
436 cat >expect.in-reply-to <<EOF
438 Message-Id: <0>
439 In-Reply-To: <1>
440 References: <1>
442 Message-Id: <2>
443 In-Reply-To: <1>
444 References: <1>
446 Message-Id: <3>
447 In-Reply-To: <1>
448 References: <1>
451 test_expect_success 'thread in-reply-to' '
452 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
453 --thread master
456 cat >expect.cover-letter <<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>
468 Message-Id: <3>
469 In-Reply-To: <0>
470 References: <0>
473 test_expect_success 'thread cover-letter' '
474 check_threading expect.cover-letter --cover-letter --thread master
477 cat >expect.cl-irt <<EOF
479 Message-Id: <0>
480 In-Reply-To: <1>
481 References: <1>
483 Message-Id: <2>
484 In-Reply-To: <0>
485 References: <1>
488 Message-Id: <3>
489 In-Reply-To: <0>
490 References: <1>
493 Message-Id: <4>
494 In-Reply-To: <0>
495 References: <1>
499 test_expect_success 'thread cover-letter in-reply-to' '
500 check_threading expect.cl-irt --cover-letter \
501 --in-reply-to="<test.message>" --thread master
504 test_expect_success 'thread explicit shallow' '
505 check_threading expect.cl-irt --cover-letter \
506 --in-reply-to="<test.message>" --thread=shallow master
509 cat >expect.deep <<EOF
511 Message-Id: <0>
513 Message-Id: <1>
514 In-Reply-To: <0>
515 References: <0>
517 Message-Id: <2>
518 In-Reply-To: <1>
519 References: <0>
523 test_expect_success 'thread deep' '
524 check_threading expect.deep --thread=deep master
527 cat >expect.deep-irt <<EOF
529 Message-Id: <0>
530 In-Reply-To: <1>
531 References: <1>
533 Message-Id: <2>
534 In-Reply-To: <0>
535 References: <1>
538 Message-Id: <3>
539 In-Reply-To: <2>
540 References: <1>
545 test_expect_success 'thread deep in-reply-to' '
546 check_threading expect.deep-irt --thread=deep \
547 --in-reply-to="<test.message>" master
550 cat >expect.deep-cl <<EOF
552 Message-Id: <0>
554 Message-Id: <1>
555 In-Reply-To: <0>
556 References: <0>
558 Message-Id: <2>
559 In-Reply-To: <1>
560 References: <0>
563 Message-Id: <3>
564 In-Reply-To: <2>
565 References: <0>
570 test_expect_success 'thread deep cover-letter' '
571 check_threading expect.deep-cl --cover-letter --thread=deep master
574 cat >expect.deep-cl-irt <<EOF
576 Message-Id: <0>
577 In-Reply-To: <1>
578 References: <1>
580 Message-Id: <2>
581 In-Reply-To: <0>
582 References: <1>
585 Message-Id: <3>
586 In-Reply-To: <2>
587 References: <1>
591 Message-Id: <4>
592 In-Reply-To: <3>
593 References: <1>
599 test_expect_success 'thread deep cover-letter in-reply-to' '
600 check_threading expect.deep-cl-irt --cover-letter \
601 --in-reply-to="<test.message>" --thread=deep master
604 test_expect_success 'thread via config' '
605 test_config format.thread true &&
606 check_threading expect.thread master
609 test_expect_success 'thread deep via config' '
610 test_config format.thread deep &&
611 check_threading expect.deep master
614 test_expect_success 'thread config + override' '
615 test_config format.thread deep &&
616 check_threading expect.thread --thread master
619 test_expect_success 'thread config + --no-thread' '
620 test_config format.thread deep &&
621 check_threading expect.no-threading --no-thread master
624 test_expect_success 'excessive subject' '
625 rm -rf patches/ &&
626 git checkout side &&
627 before=$(git hash-object file) &&
628 before=$(git rev-parse --short $before) &&
629 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
630 after=$(git hash-object file) &&
631 after=$(git rev-parse --short $after) &&
632 git update-index file &&
633 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." &&
634 git format-patch -o patches/ master..side &&
635 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
638 test_expect_success 'failure to write cover-letter aborts gracefully' '
639 test_when_finished "rmdir 0000-cover-letter.patch" &&
640 mkdir 0000-cover-letter.patch &&
641 test_must_fail git format-patch --no-renames --cover-letter -1
644 test_expect_success 'cover-letter inherits diff options' '
645 git mv file foo &&
646 git commit -m foo &&
647 git format-patch --no-renames --cover-letter -1 &&
648 check_patch 0000-cover-letter.patch &&
649 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
650 git format-patch --cover-letter -1 -M &&
651 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
654 cat >expect <<EOF
655 This is an excessively long subject line for a message due to the
656 habit some projects have of not having a short, one-line subject at
657 the start of the commit message, but rather sticking a whole
658 paragraph right at the start as the only thing in the commit
659 message. It had better not become the filename for the patch.
664 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
665 git format-patch --cover-letter -2 &&
666 sed -e "1,/A U Thor/d" -e "/^\$/q" 0000-cover-letter.patch >output &&
667 test_cmp expect output
670 cat >expect <<EOF
671 index $before..$after 100644
672 --- a/file
673 +++ b/file
674 @@ -13,4 +13,20 @@ C
682 test_expect_success 'format-patch respects -U' '
683 git format-patch -U4 -2 &&
684 sed -e "1,/^diff/d" -e "/^+5/q" \
685 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
686 >output &&
687 test_cmp expect output
690 cat >expect <<EOF
692 diff --git a/file b/file
693 index $before..$after 100644
694 --- a/file
695 +++ b/file
696 @@ -14,3 +14,19 @@ C
703 test_expect_success 'format-patch -p suppresses stat' '
704 git format-patch -p -2 &&
705 sed -e "1,/^\$/d" -e "/^+5/q" 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&
706 test_cmp expect output
709 test_expect_success 'format-patch from a subdirectory (1)' '
710 filename=$(
711 rm -rf sub &&
712 mkdir -p sub/dir &&
713 cd sub/dir &&
714 git format-patch -1
715 ) &&
716 case "$filename" in
718 ;; # ok
720 echo "Oops? $filename"
721 false
723 esac &&
724 test -f "$filename"
727 test_expect_success 'format-patch from a subdirectory (2)' '
728 filename=$(
729 rm -rf sub &&
730 mkdir -p sub/dir &&
731 cd sub/dir &&
732 git format-patch -1 -o ..
733 ) &&
734 case "$filename" in
735 ../0*)
736 ;; # ok
738 echo "Oops? $filename"
739 false
741 esac &&
742 basename=$(expr "$filename" : ".*/\(.*\)") &&
743 test -f "sub/$basename"
746 test_expect_success 'format-patch from a subdirectory (3)' '
747 rm -f 0* &&
748 filename=$(
749 rm -rf sub &&
750 mkdir -p sub/dir &&
751 cd sub/dir &&
752 git format-patch -1 -o "$TRASH_DIRECTORY"
753 ) &&
754 basename=$(expr "$filename" : ".*/\(.*\)") &&
755 test -f "$basename"
758 test_expect_success 'format-patch --in-reply-to' '
759 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" >patch8 &&
760 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
761 grep "^References: <baz@foo.bar>" patch8
764 test_expect_success 'format-patch --signoff' '
765 git format-patch -1 --signoff --stdout >out &&
766 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
769 test_expect_success 'format-patch --notes --signoff' '
770 git notes --ref test add -m "test message" HEAD &&
771 git format-patch -1 --signoff --stdout --notes=test >out &&
772 # Three dashes must come after S-o-b
773 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
774 sed "1,/^Signed-off-by: /d" out | grep "test message" &&
775 # Notes message must come after three dashes
776 ! sed "/^---$/q" out | grep "test message" &&
777 sed "1,/^---$/d" out | grep "test message"
780 test_expect_success 'format-patch notes output control' '
781 git notes add -m "notes config message" HEAD &&
782 test_when_finished git notes remove HEAD &&
784 git format-patch -1 --stdout >out &&
785 ! grep "notes config message" out &&
786 git format-patch -1 --stdout --notes >out &&
787 grep "notes config message" out &&
788 git format-patch -1 --stdout --no-notes >out &&
789 ! grep "notes config message" out &&
790 git format-patch -1 --stdout --notes --no-notes >out &&
791 ! grep "notes config message" out &&
792 git format-patch -1 --stdout --no-notes --notes >out &&
793 grep "notes config message" out &&
795 test_config format.notes true &&
796 git format-patch -1 --stdout >out &&
797 grep "notes config message" out &&
798 git format-patch -1 --stdout --notes >out &&
799 grep "notes config message" out &&
800 git format-patch -1 --stdout --no-notes >out &&
801 ! grep "notes config message" out &&
802 git format-patch -1 --stdout --notes --no-notes >out &&
803 ! grep "notes config message" out &&
804 git format-patch -1 --stdout --no-notes --notes >out &&
805 grep "notes config message" out
808 test_expect_success 'format-patch with multiple notes refs' '
809 git notes --ref note1 add -m "this is note 1" HEAD &&
810 test_when_finished git notes --ref note1 remove HEAD &&
811 git notes --ref note2 add -m "this is note 2" HEAD &&
812 test_when_finished git notes --ref note2 remove HEAD &&
814 git format-patch -1 --stdout >out &&
815 ! grep "this is note 1" out &&
816 ! grep "this is note 2" out &&
817 git format-patch -1 --stdout --notes=note1 >out &&
818 grep "this is note 1" out &&
819 ! grep "this is note 2" out &&
820 git format-patch -1 --stdout --notes=note2 >out &&
821 ! grep "this is note 1" out &&
822 grep "this is note 2" out &&
823 git format-patch -1 --stdout --notes=note1 --notes=note2 >out &&
824 grep "this is note 1" out &&
825 grep "this is note 2" out &&
827 test_config format.notes note1 &&
828 git format-patch -1 --stdout >out &&
829 grep "this is note 1" out &&
830 ! grep "this is note 2" out &&
831 git format-patch -1 --stdout --no-notes >out &&
832 ! grep "this is note 1" out &&
833 ! grep "this is note 2" out &&
834 git format-patch -1 --stdout --notes=note2 >out &&
835 grep "this is note 1" out &&
836 grep "this is note 2" out &&
837 git format-patch -1 --stdout --no-notes --notes=note2 >out &&
838 ! grep "this is note 1" out &&
839 grep "this is note 2" out &&
841 git config --add format.notes note2 &&
842 git format-patch -1 --stdout >out &&
843 grep "this is note 1" out &&
844 grep "this is note 2" out &&
845 git format-patch -1 --stdout --no-notes >out &&
846 ! grep "this is note 1" out &&
847 ! grep "this is note 2" out
850 test_expect_success 'format-patch with multiple notes refs in config' '
851 test_when_finished "test_unconfig format.notes" &&
853 git notes --ref note1 add -m "this is note 1" HEAD &&
854 test_when_finished git notes --ref note1 remove HEAD &&
855 git notes --ref note2 add -m "this is note 2" HEAD &&
856 test_when_finished git notes --ref note2 remove HEAD &&
858 git config format.notes note1 &&
859 git format-patch -1 --stdout >out &&
860 grep "this is note 1" out &&
861 ! grep "this is note 2" out &&
862 git config format.notes note2 &&
863 git format-patch -1 --stdout >out &&
864 ! grep "this is note 1" out &&
865 grep "this is note 2" out &&
866 git config --add format.notes note1 &&
867 git format-patch -1 --stdout >out &&
868 grep "this is note 1" out &&
869 grep "this is note 2" out &&
871 git config --replace-all format.notes note1 &&
872 git config --add format.notes false &&
873 git format-patch -1 --stdout >out &&
874 ! grep "this is note 1" out &&
875 ! grep "this is note 2" out &&
876 git config --add format.notes note2 &&
877 git format-patch -1 --stdout >out &&
878 ! grep "this is note 1" out &&
879 grep "this is note 2" out
882 echo "fatal: --name-only does not make sense" >expect.name-only
883 echo "fatal: --name-status does not make sense" >expect.name-status
884 echo "fatal: --check does not make sense" >expect.check
886 test_expect_success 'options no longer allowed for format-patch' '
887 test_must_fail git format-patch --name-only 2>output &&
888 test_i18ncmp expect.name-only output &&
889 test_must_fail git format-patch --name-status 2>output &&
890 test_i18ncmp expect.name-status output &&
891 test_must_fail git format-patch --check 2>output &&
892 test_i18ncmp expect.check output
895 test_expect_success 'format-patch --numstat should produce a patch' '
896 git format-patch --numstat --stdout master..side >output &&
897 grep "^diff --git a/" output >diff &&
898 test_line_count = 5 diff
901 test_expect_success 'format-patch -- <path>' '
902 git format-patch master..side -- file 2>error &&
903 ! grep "Use .--" error
906 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
907 git format-patch --ignore-if-in-upstream HEAD
910 test_expect_success 'get git version' '
911 git_version=$(git --version) &&
912 git_version=${git_version##* }
915 signature() {
916 printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
919 test_expect_success 'format-patch default signature' '
920 git format-patch --stdout -1 >patch &&
921 tail -n 3 patch >output &&
922 signature >expect &&
923 test_cmp expect output
926 test_expect_success 'format-patch --signature' '
927 git format-patch --stdout --signature="my sig" -1 >patch &&
928 tail -n 3 patch >output &&
929 signature "my sig" >expect &&
930 test_cmp expect output
933 test_expect_success 'format-patch with format.signature config' '
934 git config format.signature "config sig" &&
935 git format-patch --stdout -1 >output &&
936 grep "config sig" output
939 test_expect_success 'format-patch --signature overrides format.signature' '
940 git config format.signature "config sig" &&
941 git format-patch --stdout --signature="overrides" -1 >output &&
942 ! grep "config sig" output &&
943 grep "overrides" output
946 test_expect_success 'format-patch --no-signature ignores format.signature' '
947 git config format.signature "config sig" &&
948 git format-patch --stdout --signature="my sig" --no-signature \
949 -1 >output &&
950 check_patch output &&
951 ! grep "config sig" output &&
952 ! grep "my sig" output &&
953 ! grep "^-- \$" output
956 test_expect_success 'format-patch --signature --cover-letter' '
957 git config --unset-all format.signature &&
958 git format-patch --stdout --signature="my sig" --cover-letter \
959 -1 >output &&
960 grep "my sig" output >sig &&
961 test_line_count = 2 sig
964 test_expect_success 'format.signature="" suppresses signatures' '
965 git config format.signature "" &&
966 git format-patch --stdout -1 >output &&
967 check_patch output &&
968 ! grep "^-- \$" output
971 test_expect_success 'format-patch --no-signature suppresses signatures' '
972 git config --unset-all format.signature &&
973 git format-patch --stdout --no-signature -1 >output &&
974 check_patch output &&
975 ! grep "^-- \$" output
978 test_expect_success 'format-patch --signature="" suppresses signatures' '
979 git format-patch --stdout --signature="" -1 >output &&
980 check_patch output &&
981 ! grep "^-- \$" output
984 test_expect_success 'prepare mail-signature input' '
985 cat >mail-signature <<-\EOF
987 Test User <test.email@kernel.org>
988 http://git.kernel.org/cgit/git/git.git
990 git.kernel.org/?p=git/git.git;a=summary
995 test_expect_success '--signature-file=file works' '
996 git format-patch --stdout --signature-file=mail-signature -1 >output &&
997 check_patch output &&
998 sed -e "1,/^-- \$/d" output >actual &&
1000 cat mail-signature && echo
1001 } >expect &&
1002 test_cmp expect actual
1005 test_expect_success 'format.signaturefile works' '
1006 test_config format.signaturefile mail-signature &&
1007 git format-patch --stdout -1 >output &&
1008 check_patch output &&
1009 sed -e "1,/^-- \$/d" output >actual &&
1011 cat mail-signature && echo
1012 } >expect &&
1013 test_cmp expect actual
1016 test_expect_success '--no-signature suppresses format.signaturefile ' '
1017 test_config format.signaturefile mail-signature &&
1018 git format-patch --stdout --no-signature -1 >output &&
1019 check_patch output &&
1020 ! grep "^-- \$" output
1023 test_expect_success '--signature-file overrides format.signaturefile' '
1024 cat >other-mail-signature <<-\EOF &&
1025 Use this other signature instead of mail-signature.
1027 test_config format.signaturefile mail-signature &&
1028 git format-patch --stdout \
1029 --signature-file=other-mail-signature -1 >output &&
1030 check_patch output &&
1031 sed -e "1,/^-- \$/d" output >actual &&
1033 cat other-mail-signature && echo
1034 } >expect &&
1035 test_cmp expect actual
1038 test_expect_success '--signature overrides format.signaturefile' '
1039 test_config format.signaturefile mail-signature &&
1040 git format-patch --stdout --signature="my sig" -1 >output &&
1041 check_patch output &&
1042 grep "my sig" output
1045 test_expect_success TTY 'format-patch --stdout paginates' '
1046 rm -f pager_used &&
1047 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
1048 test_path_is_file pager_used
1051 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
1052 rm -f pager_used &&
1053 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
1054 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
1055 test_path_is_missing pager_used &&
1056 test_path_is_missing .git/pager_used
1059 test_expect_success 'format-patch handles multi-line subjects' '
1060 rm -rf patches/ &&
1061 echo content >>file &&
1062 for i in one two three; do echo $i; done >msg &&
1063 git add file &&
1064 git commit -F msg &&
1065 git format-patch -o patches -1 &&
1066 grep ^Subject: patches/0001-one.patch >actual &&
1067 echo "Subject: [PATCH] one two three" >expect &&
1068 test_cmp expect actual
1071 test_expect_success 'format-patch handles multi-line encoded subjects' '
1072 rm -rf patches/ &&
1073 echo content >>file &&
1074 for i in en två tre; do echo $i; done >msg &&
1075 git add file &&
1076 git commit -F msg &&
1077 git format-patch -o patches -1 &&
1078 grep ^Subject: patches/0001-en.patch >actual &&
1079 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
1080 test_cmp expect actual
1083 M8="foo bar "
1084 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1085 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1086 cat >expect <<'EOF'
1087 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1088 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1089 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1090 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1091 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1092 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1093 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1095 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
1096 echo content >>file &&
1097 git add file &&
1098 git commit -m "$M512" &&
1099 git format-patch --stdout -1 >patch &&
1100 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1101 test_cmp expect subject
1104 M8="föö bar "
1105 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1106 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1107 cat >expect <<'EOF'
1108 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1109 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1110 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1111 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1112 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1113 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1114 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1115 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1116 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1117 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1118 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1119 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1120 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1121 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1122 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1123 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1124 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1125 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1126 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1127 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1128 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1129 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1130 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1131 =?UTF-8?q?bar?=
1133 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
1134 rm -rf patches/ &&
1135 echo content >>file &&
1136 git add file &&
1137 git commit -m "$M512" &&
1138 git format-patch --stdout -1 >patch &&
1139 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1140 test_cmp expect subject
1143 check_author() {
1144 echo content >>file &&
1145 git add file &&
1146 GIT_AUTHOR_NAME=$1 git commit -m author-check &&
1147 git format-patch --stdout -1 >patch &&
1148 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1149 test_cmp expect actual
1152 cat >expect <<'EOF'
1153 From: "Foo B. Bar" <author@example.com>
1155 test_expect_success 'format-patch quotes dot in from-headers' '
1156 check_author "Foo B. Bar"
1159 cat >expect <<'EOF'
1160 From: "Foo \"The Baz\" Bar" <author@example.com>
1162 test_expect_success 'format-patch quotes double-quote in from-headers' '
1163 check_author "Foo \"The Baz\" Bar"
1166 cat >expect <<'EOF'
1167 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1169 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1170 check_author "Föo Bar"
1173 cat >expect <<'EOF'
1174 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1176 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1177 check_author "Föo B. Bar"
1180 cat >expect <<EOF
1181 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1182 <author@example.com>
1184 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1185 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1188 cat >expect <<'EOF'
1189 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1190 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1191 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1193 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1194 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"
1197 cat >expect <<'EOF'
1198 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1199 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1200 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1202 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1203 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"
1206 cat >expect <<'EOF'
1207 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1208 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1209 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1210 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1211 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1213 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1214 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"
1217 cat >expect <<'EOF'
1218 From: Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1219 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1220 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1222 test_expect_success 'format-patch wraps extremely long from-header (non-ASCII without Q-encoding)' '
1223 echo content >>file &&
1224 git add file &&
1225 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" \
1226 git commit -m author-check &&
1227 git format-patch --no-encode-email-headers --stdout -1 >patch &&
1228 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1229 test_cmp expect actual
1232 cat >expect <<'EOF'
1233 Subject: [PATCH] Foö
1235 test_expect_success 'subject lines are unencoded with --no-encode-email-headers' '
1236 echo content >>file &&
1237 git add file &&
1238 git commit -m "Foö" &&
1239 git format-patch --no-encode-email-headers -1 --stdout >patch &&
1240 grep ^Subject: patch >actual &&
1241 test_cmp expect actual
1244 cat >expect <<'EOF'
1245 Subject: [PATCH] Foö
1247 test_expect_success 'subject lines are unencoded with format.encodeEmailHeaders=false' '
1248 echo content >>file &&
1249 git add file &&
1250 git commit -m "Foö" &&
1251 git config format.encodeEmailHeaders false &&
1252 git format-patch -1 --stdout >patch &&
1253 grep ^Subject: patch >actual &&
1254 test_cmp expect actual
1257 cat >expect <<'EOF'
1258 Subject: [PATCH] =?UTF-8?q?Fo=C3=B6?=
1260 test_expect_success '--encode-email-headers overrides format.encodeEmailHeaders' '
1261 echo content >>file &&
1262 git add file &&
1263 git commit -m "Foö" &&
1264 git config format.encodeEmailHeaders false &&
1265 git format-patch --encode-email-headers -1 --stdout >patch &&
1266 grep ^Subject: patch >actual &&
1267 test_cmp expect actual
1270 cat >expect <<'EOF'
1271 Subject: header with . in it
1273 test_expect_success 'subject lines do not have 822 atom-quoting' '
1274 echo content >>file &&
1275 git add file &&
1276 git commit -m "header with . in it" &&
1277 git format-patch -k -1 --stdout >patch &&
1278 grep ^Subject: patch >actual &&
1279 test_cmp expect actual
1282 cat >expect <<'EOF'
1283 Subject: [PREFIX 1/1] header with . in it
1285 test_expect_success 'subject prefixes have space prepended' '
1286 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1287 grep ^Subject: patch >actual &&
1288 test_cmp expect actual
1291 cat >expect <<'EOF'
1292 Subject: [1/1] header with . in it
1294 test_expect_success 'empty subject prefix does not have extra space' '
1295 git format-patch -n -1 --stdout --subject-prefix= >patch &&
1296 grep ^Subject: patch >actual &&
1297 test_cmp expect actual
1300 test_expect_success '--rfc' '
1301 cat >expect <<-\EOF &&
1302 Subject: [RFC PATCH 1/1] header with . in it
1304 git format-patch -n -1 --stdout --rfc >patch &&
1305 grep ^Subject: patch >actual &&
1306 test_cmp expect actual
1309 test_expect_success '--from=ident notices bogus ident' '
1310 test_must_fail git format-patch -1 --stdout --from=foo >patch
1313 test_expect_success '--from=ident replaces author' '
1314 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1315 cat >expect <<-\EOF &&
1316 From: Me <me@example.com>
1318 From: A U Thor <author@example.com>
1321 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1322 test_cmp expect patch.head
1325 test_expect_success '--from uses committer ident' '
1326 git format-patch -1 --stdout --from >patch &&
1327 cat >expect <<-\EOF &&
1328 From: C O Mitter <committer@example.com>
1330 From: A U Thor <author@example.com>
1333 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1334 test_cmp expect patch.head
1337 test_expect_success '--from omits redundant in-body header' '
1338 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1339 cat >expect <<-\EOF &&
1340 From: A U Thor <author@example.com>
1343 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1344 test_cmp expect patch.head
1347 test_expect_success 'in-body headers trigger content encoding' '
1348 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1349 test_when_finished "git reset --hard HEAD^" &&
1350 git format-patch -1 --stdout --from >patch &&
1351 cat >expect <<-\EOF &&
1352 From: C O Mitter <committer@example.com>
1353 Content-Type: text/plain; charset=UTF-8
1355 From: éxötìc <author@example.com>
1358 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" patch >patch.head &&
1359 test_cmp expect patch.head
1362 append_signoff()
1364 C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1365 git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1366 sed -n -e "1,/^---$/p" append_signoff.patch |
1367 egrep -n "^Subject|Sign|^$"
1370 test_expect_success 'signoff: commit with no body' '
1371 append_signoff </dev/null >actual &&
1372 cat <<-\EOF | sed "s/EOL$//" >expect &&
1373 4:Subject: [PATCH] EOL
1375 9:Signed-off-by: C O Mitter <committer@example.com>
1377 test_cmp expect actual
1380 test_expect_success 'signoff: commit with only subject' '
1381 echo subject | append_signoff >actual &&
1382 cat >expect <<-\EOF &&
1383 4:Subject: [PATCH] subject
1385 9:Signed-off-by: C O Mitter <committer@example.com>
1387 test_cmp expect actual
1390 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1391 printf subject | append_signoff >actual &&
1392 cat >expect <<-\EOF &&
1393 4:Subject: [PATCH] subject
1395 9:Signed-off-by: C O Mitter <committer@example.com>
1397 test_cmp expect actual
1400 test_expect_success 'signoff: no existing signoffs' '
1401 append_signoff <<-\EOF >actual &&
1402 subject
1404 body
1406 cat >expect <<-\EOF &&
1407 4:Subject: [PATCH] subject
1410 11:Signed-off-by: C O Mitter <committer@example.com>
1412 test_cmp expect actual
1415 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1416 printf "subject\n\nbody" | append_signoff >actual &&
1417 cat >expect <<-\EOF &&
1418 4:Subject: [PATCH] subject
1421 11:Signed-off-by: C O Mitter <committer@example.com>
1423 test_cmp expect actual
1426 test_expect_success 'signoff: some random signoff' '
1427 append_signoff <<-\EOF >actual &&
1428 subject
1430 body
1432 Signed-off-by: my@house
1434 cat >expect <<-\EOF &&
1435 4:Subject: [PATCH] subject
1438 11:Signed-off-by: my@house
1439 12:Signed-off-by: C O Mitter <committer@example.com>
1441 test_cmp expect actual
1444 test_expect_success 'signoff: misc conforming footer elements' '
1445 append_signoff <<-\EOF >actual &&
1446 subject
1448 body
1450 Signed-off-by: my@house
1451 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1452 Tested-by: Some One <someone@example.com>
1453 Bug: 1234
1455 cat >expect <<-\EOF &&
1456 4:Subject: [PATCH] subject
1459 11:Signed-off-by: my@house
1460 15:Signed-off-by: C O Mitter <committer@example.com>
1462 test_cmp expect actual
1465 test_expect_success 'signoff: some random signoff-alike' '
1466 append_signoff <<-\EOF >actual &&
1467 subject
1469 body
1470 Fooled-by-me: my@house
1472 cat >expect <<-\EOF &&
1473 4:Subject: [PATCH] subject
1476 12:Signed-off-by: C O Mitter <committer@example.com>
1478 test_cmp expect actual
1481 test_expect_success 'signoff: not really a signoff' '
1482 append_signoff <<-\EOF >actual &&
1483 subject
1485 I want to mention about Signed-off-by: here.
1487 cat >expect <<-\EOF &&
1488 4:Subject: [PATCH] subject
1490 9:I want to mention about Signed-off-by: here.
1492 11:Signed-off-by: C O Mitter <committer@example.com>
1494 test_cmp expect actual
1497 test_expect_success 'signoff: not really a signoff (2)' '
1498 append_signoff <<-\EOF >actual &&
1499 subject
1501 My unfortunate
1502 Signed-off-by: example happens to be wrapped here.
1504 cat >expect <<-\EOF &&
1505 4:Subject: [PATCH] subject
1507 10:Signed-off-by: example happens to be wrapped here.
1508 11:Signed-off-by: C O Mitter <committer@example.com>
1510 test_cmp expect actual
1513 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1514 append_signoff <<-\EOF >actual &&
1515 subject
1517 Signed-off-by: my@house
1518 Signed-off-by: your@house
1520 A lot of houses.
1522 cat >expect <<-\EOF &&
1523 4:Subject: [PATCH] subject
1525 9:Signed-off-by: my@house
1526 10:Signed-off-by: your@house
1529 14:Signed-off-by: C O Mitter <committer@example.com>
1531 test_cmp expect actual
1534 test_expect_success 'signoff: the same signoff at the end' '
1535 append_signoff <<-\EOF >actual &&
1536 subject
1538 body
1540 Signed-off-by: C O Mitter <committer@example.com>
1542 cat >expect <<-\EOF &&
1543 4:Subject: [PATCH] subject
1546 11:Signed-off-by: C O Mitter <committer@example.com>
1548 test_cmp expect actual
1551 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1552 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1553 append_signoff >actual &&
1554 cat >expect <<-\EOF &&
1555 4:Subject: [PATCH] subject
1557 9:Signed-off-by: C O Mitter <committer@example.com>
1559 test_cmp expect actual
1562 test_expect_success 'signoff: the same signoff NOT at the end' '
1563 append_signoff <<-\EOF >actual &&
1564 subject
1566 body
1568 Signed-off-by: C O Mitter <committer@example.com>
1569 Signed-off-by: my@house
1571 cat >expect <<-\EOF &&
1572 4:Subject: [PATCH] subject
1575 11:Signed-off-by: C O Mitter <committer@example.com>
1576 12:Signed-off-by: my@house
1578 test_cmp expect actual
1581 test_expect_success 'signoff: tolerate garbage in conforming footer' '
1582 append_signoff <<-\EOF >actual &&
1583 subject
1585 body
1587 Tested-by: my@house
1588 Some Trash
1589 Signed-off-by: C O Mitter <committer@example.com>
1591 cat >expect <<-\EOF &&
1592 4:Subject: [PATCH] subject
1595 13:Signed-off-by: C O Mitter <committer@example.com>
1597 test_cmp expect actual
1600 test_expect_success 'signoff: respect trailer config' '
1601 append_signoff <<-\EOF >actual &&
1602 subject
1604 Myfooter: x
1605 Some Trash
1607 cat >expect <<-\EOF &&
1608 4:Subject: [PATCH] subject
1611 12:Signed-off-by: C O Mitter <committer@example.com>
1613 test_cmp expect actual &&
1615 test_config trailer.Myfooter.ifexists add &&
1616 append_signoff <<-\EOF >actual &&
1617 subject
1619 Myfooter: x
1620 Some Trash
1622 cat >expect <<-\EOF &&
1623 4:Subject: [PATCH] subject
1625 11:Signed-off-by: C O Mitter <committer@example.com>
1627 test_cmp expect actual
1630 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1631 append_signoff <<-\EOF >actual &&
1632 subject
1634 body
1636 Reviewed-id: Noone
1637 Tested-by: my@house
1638 Change-id: Ideadbeef
1639 Signed-off-by: C O Mitter <committer@example.com>
1640 Bug: 1234
1642 cat >expect <<-\EOF &&
1643 4:Subject: [PATCH] subject
1646 14:Signed-off-by: C O Mitter <committer@example.com>
1648 test_cmp expect actual
1651 test_expect_success 'format patch ignores color.ui' '
1652 test_unconfig color.ui &&
1653 git format-patch --stdout -1 >expect &&
1654 test_config color.ui always &&
1655 git format-patch --stdout -1 >actual &&
1656 test_cmp expect actual
1659 test_expect_success 'format patch respects diff.relative' '
1660 rm -rf subdir &&
1661 mkdir subdir &&
1662 echo other content >subdir/file2 &&
1663 git add subdir/file2 &&
1664 git commit -F msg &&
1665 test_unconfig diff.relative &&
1666 git format-patch --relative=subdir --stdout -1 >expect &&
1667 test_config diff.relative true &&
1668 git -C subdir format-patch --stdout -1 >actual &&
1669 test_cmp expect actual
1672 test_expect_success 'cover letter with invalid --cover-from-description and config' '
1673 test_config branch.rebuild-1.description "config subject
1675 body" &&
1676 test_must_fail git format-patch --cover-letter --cover-from-description garbage master &&
1677 test_config format.coverFromDescription garbage &&
1678 test_must_fail git format-patch --cover-letter master
1681 test_expect_success 'cover letter with format.coverFromDescription = default' '
1682 test_config branch.rebuild-1.description "config subject
1684 body" &&
1685 test_config format.coverFromDescription default &&
1686 git checkout rebuild-1 &&
1687 git format-patch --stdout --cover-letter master >actual &&
1688 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1689 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1690 grep "^config subject$" actual &&
1691 grep "^body$" actual
1694 test_expect_success 'cover letter with --cover-from-description default' '
1695 test_config branch.rebuild-1.description "config subject
1697 body" &&
1698 git checkout rebuild-1 &&
1699 git format-patch --stdout --cover-letter --cover-from-description default master >actual &&
1700 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1701 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1702 grep "^config subject$" actual &&
1703 grep "^body$" actual
1706 test_expect_success 'cover letter with format.coverFromDescription = none' '
1707 test_config branch.rebuild-1.description "config subject
1709 body" &&
1710 test_config format.coverFromDescription none &&
1711 git checkout rebuild-1 &&
1712 git format-patch --stdout --cover-letter master >actual &&
1713 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1714 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1715 ! grep "^config subject$" actual &&
1716 ! grep "^body$" actual
1719 test_expect_success 'cover letter with --cover-from-description none' '
1720 test_config branch.rebuild-1.description "config subject
1722 body" &&
1723 git checkout rebuild-1 &&
1724 git format-patch --stdout --cover-letter --cover-from-description none master >actual &&
1725 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1726 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1727 ! grep "^config subject$" actual &&
1728 ! grep "^body$" actual
1731 test_expect_success 'cover letter with format.coverFromDescription = message' '
1732 test_config branch.rebuild-1.description "config subject
1734 body" &&
1735 test_config format.coverFromDescription message &&
1736 git checkout rebuild-1 &&
1737 git format-patch --stdout --cover-letter master >actual &&
1738 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1739 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1740 grep "^config subject$" actual &&
1741 grep "^body$" actual
1744 test_expect_success 'cover letter with --cover-from-description message' '
1745 test_config branch.rebuild-1.description "config subject
1747 body" &&
1748 git checkout rebuild-1 &&
1749 git format-patch --stdout --cover-letter --cover-from-description message master >actual &&
1750 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1751 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1752 grep "^config subject$" actual &&
1753 grep "^body$" actual
1756 test_expect_success 'cover letter with format.coverFromDescription = subject' '
1757 test_config branch.rebuild-1.description "config subject
1759 body" &&
1760 test_config format.coverFromDescription subject &&
1761 git checkout rebuild-1 &&
1762 git format-patch --stdout --cover-letter master >actual &&
1763 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1764 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1765 ! grep "^config subject$" actual &&
1766 grep "^body$" actual
1769 test_expect_success 'cover letter with --cover-from-description subject' '
1770 test_config branch.rebuild-1.description "config subject
1772 body" &&
1773 git checkout rebuild-1 &&
1774 git format-patch --stdout --cover-letter --cover-from-description subject master >actual &&
1775 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1776 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1777 ! grep "^config subject$" actual &&
1778 grep "^body$" actual
1781 test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' '
1782 test_config branch.rebuild-1.description "config subject
1784 body" &&
1785 test_config format.coverFromDescription auto &&
1786 git checkout rebuild-1 &&
1787 git format-patch --stdout --cover-letter master >actual &&
1788 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1789 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1790 ! grep "^config subject$" actual &&
1791 grep "^body$" actual
1794 test_expect_success 'cover letter with --cover-from-description auto (short subject line)' '
1795 test_config branch.rebuild-1.description "config subject
1797 body" &&
1798 git checkout rebuild-1 &&
1799 git format-patch --stdout --cover-letter --cover-from-description auto master >actual &&
1800 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1801 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1802 ! grep "^config subject$" actual &&
1803 grep "^body$" actual
1806 test_expect_success 'cover letter with format.coverFromDescription = auto (long subject line)' '
1807 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
1809 body" &&
1810 test_config format.coverFromDescription auto &&
1811 git checkout rebuild-1 &&
1812 git format-patch --stdout --cover-letter master >actual &&
1813 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1814 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1815 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1816 grep "^body$" actual
1819 test_expect_success 'cover letter with --cover-from-description auto (long subject line)' '
1820 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
1822 body" &&
1823 git checkout rebuild-1 &&
1824 git format-patch --stdout --cover-letter --cover-from-description auto master >actual &&
1825 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1826 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1827 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1828 grep "^body$" actual
1831 test_expect_success 'cover letter with command-line --cover-from-description overrides config' '
1832 test_config branch.rebuild-1.description "config subject
1834 body" &&
1835 test_config format.coverFromDescription none &&
1836 git checkout rebuild-1 &&
1837 git format-patch --stdout --cover-letter --cover-from-description subject master >actual &&
1838 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1839 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1840 ! grep "^config subject$" actual &&
1841 grep "^body$" actual
1844 test_expect_success 'cover letter using branch description (1)' '
1845 git checkout rebuild-1 &&
1846 test_config branch.rebuild-1.description hello &&
1847 git format-patch --stdout --cover-letter master >actual &&
1848 grep hello actual
1851 test_expect_success 'cover letter using branch description (2)' '
1852 git checkout rebuild-1 &&
1853 test_config branch.rebuild-1.description hello &&
1854 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1855 grep hello actual
1858 test_expect_success 'cover letter using branch description (3)' '
1859 git checkout rebuild-1 &&
1860 test_config branch.rebuild-1.description hello &&
1861 git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1862 grep hello actual
1865 test_expect_success 'cover letter using branch description (4)' '
1866 git checkout rebuild-1 &&
1867 test_config branch.rebuild-1.description hello &&
1868 git format-patch --stdout --cover-letter master.. >actual &&
1869 grep hello actual
1872 test_expect_success 'cover letter using branch description (5)' '
1873 git checkout rebuild-1 &&
1874 test_config branch.rebuild-1.description hello &&
1875 git format-patch --stdout --cover-letter -2 HEAD >actual &&
1876 grep hello actual
1879 test_expect_success 'cover letter using branch description (6)' '
1880 git checkout rebuild-1 &&
1881 test_config branch.rebuild-1.description hello &&
1882 git format-patch --stdout --cover-letter -2 >actual &&
1883 grep hello actual
1886 test_expect_success 'cover letter with nothing' '
1887 git format-patch --stdout --cover-letter >actual &&
1888 test_line_count = 0 actual
1891 test_expect_success 'cover letter auto' '
1892 mkdir -p tmp &&
1893 test_when_finished "rm -rf tmp;
1894 git config --unset format.coverletter" &&
1896 git config format.coverletter auto &&
1897 git format-patch -o tmp -1 >list &&
1898 test_line_count = 1 list &&
1899 git format-patch -o tmp -2 >list &&
1900 test_line_count = 3 list
1903 test_expect_success 'cover letter auto user override' '
1904 mkdir -p tmp &&
1905 test_when_finished "rm -rf tmp;
1906 git config --unset format.coverletter" &&
1908 git config format.coverletter auto &&
1909 git format-patch -o tmp --cover-letter -1 >list &&
1910 test_line_count = 2 list &&
1911 git format-patch -o tmp --cover-letter -2 >list &&
1912 test_line_count = 3 list &&
1913 git format-patch -o tmp --no-cover-letter -1 >list &&
1914 test_line_count = 1 list &&
1915 git format-patch -o tmp --no-cover-letter -2 >list &&
1916 test_line_count = 2 list
1919 test_expect_success 'format-patch --zero-commit' '
1920 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1921 grep "^From " patch2 | sort | uniq >actual &&
1922 echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
1923 test_cmp expect actual
1926 test_expect_success 'From line has expected format' '
1927 git format-patch --stdout v2..v1 >patch2 &&
1928 grep "^From " patch2 >from &&
1929 grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1930 test_cmp from filtered
1933 test_expect_success 'format-patch -o with no leading directories' '
1934 rm -fr patches &&
1935 git format-patch -o patches master..side &&
1936 count=$(git rev-list --count master..side) &&
1937 ls patches >list &&
1938 test_line_count = $count list
1941 test_expect_success 'format-patch -o with leading existing directories' '
1942 rm -rf existing-dir &&
1943 mkdir existing-dir &&
1944 git format-patch -o existing-dir/patches master..side &&
1945 count=$(git rev-list --count master..side) &&
1946 ls existing-dir/patches >list &&
1947 test_line_count = $count list
1950 test_expect_success 'format-patch -o with leading non-existing directories' '
1951 rm -rf non-existing-dir &&
1952 git format-patch -o non-existing-dir/patches master..side &&
1953 count=$(git rev-list --count master..side) &&
1954 test_path_is_dir non-existing-dir &&
1955 ls non-existing-dir/patches >list &&
1956 test_line_count = $count list
1959 test_expect_success 'format-patch format.outputDirectory option' '
1960 test_config format.outputDirectory patches &&
1961 rm -fr patches &&
1962 git format-patch master..side &&
1963 count=$(git rev-list --count master..side) &&
1964 ls patches >list &&
1965 test_line_count = $count list
1968 test_expect_success 'format-patch -o overrides format.outputDirectory' '
1969 test_config format.outputDirectory patches &&
1970 rm -fr patches patchset &&
1971 git format-patch master..side -o patchset &&
1972 test_path_is_missing patches &&
1973 test_path_is_dir patchset
1976 test_expect_success 'format-patch forbids multiple outputs' '
1977 rm -fr outfile outdir &&
1978 test_must_fail \
1979 git format-patch --stdout --output-directory=outdir &&
1980 test_must_fail \
1981 git format-patch --stdout --output=outfile &&
1982 test_must_fail \
1983 git format-patch --output=outfile --output-directory=outdir
1986 test_expect_success 'configured outdir does not conflict with output options' '
1987 rm -fr outfile outdir &&
1988 test_config format.outputDirectory outdir &&
1989 git format-patch --stdout &&
1990 test_path_is_missing outdir &&
1991 git format-patch --output=outfile &&
1992 test_path_is_missing outdir
1995 test_expect_success 'format-patch --output' '
1996 rm -fr outfile &&
1997 git format-patch -3 --stdout HEAD >expect &&
1998 git format-patch -3 --output=outfile HEAD &&
1999 test_cmp expect outfile
2002 test_expect_success 'format-patch --cover-letter --output' '
2003 rm -fr outfile &&
2004 git format-patch --cover-letter -3 --stdout HEAD >expect &&
2005 git format-patch --cover-letter -3 --output=outfile HEAD &&
2006 test_cmp expect outfile
2009 test_expect_success 'format-patch --base' '
2010 git checkout patchid &&
2012 git format-patch --stdout --base=HEAD~3 -1 >patch &&
2013 tail -n 7 patch >actual1 &&
2015 git format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&
2016 tail -n 7 patch >actual2 &&
2018 echo >expect &&
2019 git rev-parse HEAD~3 >commit-id-base &&
2020 echo "base-commit: $(cat commit-id-base)" >>expect &&
2022 git show --patch HEAD~2 >patch &&
2023 git patch-id --stable <patch >patch.id.raw &&
2024 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2026 git show --patch HEAD~1 >patch &&
2027 git patch-id --stable <patch >patch.id.raw &&
2028 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2030 signature >>expect &&
2031 test_cmp expect actual1 &&
2032 test_cmp expect actual2 &&
2034 echo >fail &&
2035 echo "base-commit: $(cat commit-id-base)" >>fail &&
2037 git show --patch HEAD~2 >patch &&
2038 git patch-id --unstable <patch >patch.id.raw &&
2039 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2041 git show --patch HEAD~1 >patch &&
2042 git patch-id --unstable <patch >patch.id.raw &&
2043 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2045 signature >>fail &&
2046 ! test_cmp fail actual1 &&
2047 ! test_cmp fail actual2
2050 test_expect_success 'format-patch --base errors out when base commit is in revision list' '
2051 test_must_fail git format-patch --base=HEAD -2 &&
2052 test_must_fail git format-patch --base=HEAD~1 -2 &&
2053 git format-patch --stdout --base=HEAD~2 -2 >patch &&
2054 grep "^base-commit:" patch >actual &&
2055 git rev-parse HEAD~2 >commit-id-base &&
2056 echo "base-commit: $(cat commit-id-base)" >expect &&
2057 test_cmp expect actual
2060 test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
2061 # For history as below:
2063 # ---Q---P---Z---Y---*---X
2064 # \ /
2065 # ------------W
2067 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
2068 git checkout -b topic1 master &&
2069 git rev-parse HEAD >commit-id-base &&
2070 test_commit P &&
2071 git rev-parse HEAD >commit-id-P &&
2072 test_commit Z &&
2073 git rev-parse HEAD >commit-id-Z &&
2074 test_commit Y &&
2075 git checkout -b topic2 master &&
2076 test_commit W &&
2077 git merge topic1 &&
2078 test_commit X &&
2079 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
2080 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
2081 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
2082 grep "^base-commit:" patch >actual &&
2083 echo "base-commit: $(cat commit-id-base)" >expect &&
2084 test_cmp expect actual
2087 test_expect_success 'format-patch --base=auto' '
2088 git checkout -b upstream master &&
2089 git checkout -b local upstream &&
2090 git branch --set-upstream-to=upstream &&
2091 test_commit N1 &&
2092 test_commit N2 &&
2093 git format-patch --stdout --base=auto -2 >patch &&
2094 grep "^base-commit:" patch >actual &&
2095 git rev-parse upstream >commit-id-base &&
2096 echo "base-commit: $(cat commit-id-base)" >expect &&
2097 test_cmp expect actual
2100 test_expect_success 'format-patch errors out when history involves criss-cross' '
2101 # setup criss-cross history
2103 # B---M1---D
2104 # / \ /
2105 # A X
2106 # \ / \
2107 # C---M2---E
2109 git checkout master &&
2110 test_commit A &&
2111 git checkout -b xb master &&
2112 test_commit B &&
2113 git checkout -b xc master &&
2114 test_commit C &&
2115 git checkout -b xbc xb -- &&
2116 git merge xc &&
2117 git checkout -b xcb xc -- &&
2118 git branch --set-upstream-to=xbc &&
2119 git merge xb &&
2120 git checkout xbc &&
2121 test_commit D &&
2122 git checkout xcb &&
2123 test_commit E &&
2124 test_must_fail git format-patch --base=auto -1
2127 test_expect_success 'format-patch format.useAutoBase whenAble history involves criss-cross' '
2128 test_config format.useAutoBase whenAble &&
2129 git format-patch -1 >patch &&
2130 ! grep "^base-commit:" patch
2133 test_expect_success 'format-patch format.useAutoBase option' '
2134 git checkout local &&
2135 test_config format.useAutoBase true &&
2136 git format-patch --stdout -1 >patch &&
2137 grep "^base-commit:" patch >actual &&
2138 git rev-parse upstream >commit-id-base &&
2139 echo "base-commit: $(cat commit-id-base)" >expect &&
2140 test_cmp expect actual
2143 test_expect_success 'format-patch format.useAutoBase option with whenAble' '
2144 git checkout local &&
2145 test_config format.useAutoBase whenAble &&
2146 git format-patch --stdout -1 >patch &&
2147 grep "^base-commit:" patch >actual &&
2148 git rev-parse upstream >commit-id-base &&
2149 echo "base-commit: $(cat commit-id-base)" >expect &&
2150 test_cmp expect actual
2153 test_expect_success 'format-patch --base overrides format.useAutoBase' '
2154 test_config format.useAutoBase true &&
2155 git format-patch --stdout --base=HEAD~1 -1 >patch &&
2156 grep "^base-commit:" patch >actual &&
2157 git rev-parse HEAD~1 >commit-id-base &&
2158 echo "base-commit: $(cat commit-id-base)" >expect &&
2159 test_cmp expect actual
2162 test_expect_success 'format-patch --no-base overrides format.useAutoBase' '
2163 test_config format.useAutoBase true &&
2164 git format-patch --stdout --no-base -1 >patch &&
2165 ! grep "^base-commit:" patch
2168 test_expect_success 'format-patch --no-base overrides format.useAutoBase whenAble' '
2169 test_config format.useAutoBase whenAble &&
2170 git format-patch --stdout --no-base -1 >patch &&
2171 ! grep "^base-commit:" patch
2174 test_expect_success 'format-patch --base with --attach' '
2175 git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
2176 sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
2177 patch >actual &&
2178 test_write_lines 1 2 >expect &&
2179 test_cmp expect actual
2181 test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
2182 test_when_finished "rm -fr patches" &&
2183 git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
2184 ! egrep "^--+mimemime" patches/0000*.patch &&
2185 egrep "^--+mimemime$" patches/0001*.patch >output &&
2186 test_line_count = 2 output &&
2187 egrep "^--+mimemime--$" patches/0001*.patch >output &&
2188 test_line_count = 1 output
2191 test_expect_success 'format-patch --pretty=mboxrd' '
2192 sp=" " &&
2193 cat >msg <<-INPUT_END &&
2194 mboxrd should escape the body
2196 From could trip up a loose mbox parser
2197 >From extra escape for reversibility
2198 >>From extra escape for reversibility 2
2199 from lower case not escaped
2200 Fromm bad speling not escaped
2201 From with leading space not escaped
2204 From
2205 From$sp
2206 From $sp
2207 From $sp
2208 INPUT_END
2210 cat >expect <<-INPUT_END &&
2211 >From could trip up a loose mbox parser
2212 >>From extra escape for reversibility
2213 >>>From extra escape for reversibility 2
2214 from lower case not escaped
2215 Fromm bad speling not escaped
2216 From with leading space not escaped
2219 From
2220 From
2221 From
2222 From
2223 INPUT_END
2225 C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
2226 git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
2227 git grep -h --no-index -A11 \
2228 "^>From could trip up a loose mbox parser" patch >actual &&
2229 test_cmp expect actual
2232 test_expect_success 'interdiff: setup' '
2233 git checkout -b boop master &&
2234 test_commit fnorp blorp &&
2235 test_commit fleep blorp
2238 test_expect_success 'interdiff: cover-letter' '
2239 sed "y/q/ /" >expect <<-\EOF &&
2240 +fleep
2243 git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
2244 test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch &&
2245 test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch &&
2246 sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual &&
2247 test_cmp expect actual
2250 test_expect_success 'interdiff: reroll-count' '
2251 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2252 test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2255 test_expect_success 'interdiff: solo-patch' '
2256 cat >expect <<-\EOF &&
2257 +fleep
2260 git format-patch --interdiff=boop~2 -1 boop &&
2261 test_i18ngrep "^Interdiff:$" 0001-fleep.patch &&
2262 sed "1,/^ @@ /d; /^$/q" 0001-fleep.patch >actual &&
2263 test_cmp expect actual
2266 test_done