Sync with Git 2.35.3
[alt-git.git] / t / t4014-format-patch.sh
blob7dc5a5c736e3f2db0c4bc29c20321b6a386661df
1 #!/bin/sh
3 # Copyright (c) 2006 Junio C Hamano
6 test_description='various format-patch tests'
8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
11 . ./test-lib.sh
12 . "$TEST_DIRECTORY"/lib-terminal.sh
14 test_expect_success setup '
15 test_write_lines 1 2 3 4 5 6 7 8 9 10 >file &&
16 cat file >elif &&
17 git add file elif &&
18 test_tick &&
19 git commit -m Initial &&
20 git checkout -b side &&
22 test_write_lines 1 2 5 6 A B C 7 8 9 10 >file &&
23 test_chmod +x elif &&
24 test_tick &&
25 git commit -m "Side changes #1" &&
27 test_write_lines D E F >>file &&
28 git update-index file &&
29 test_tick &&
30 git commit -m "Side changes #2" &&
31 git tag C2 &&
33 test_write_lines 5 6 1 2 3 A 4 B C 7 8 9 10 D E F >file &&
34 git update-index file &&
35 test_tick &&
36 git commit -m "Side changes #3 with \\n backslash-n in it." &&
38 git checkout main &&
39 git diff-tree -p C2 >patch &&
40 git apply --index <patch &&
41 test_tick &&
42 git commit -m "Main accepts moral equivalent of #2" &&
44 git checkout side &&
45 git checkout -b patchid &&
46 test_write_lines 5 6 1 2 3 A 4 B C 7 8 9 10 D E F >file2 &&
47 test_write_lines 1 2 3 A 4 B C 7 8 9 10 D E F 5 6 >file3 &&
48 test_write_lines 8 9 10 >file &&
49 git add file file2 file3 &&
50 test_tick &&
51 git commit -m "patchid 1" &&
52 test_write_lines 4 A B 7 8 9 10 >file2 &&
53 test_write_lines 8 9 10 5 6 >file3 &&
54 git add file2 file3 &&
55 test_tick &&
56 git commit -m "patchid 2" &&
57 test_write_lines 10 5 6 >file &&
58 git add file &&
59 test_tick &&
60 git commit -m "patchid 3" &&
62 git checkout 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 || exit 1
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 || exit 1
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 || exit 1
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 test_expect_success 'reroll count (-v) with a fractional number' '
390 rm -fr patches &&
391 git format-patch -o patches --cover-letter -v4.4 main..side >list &&
392 ! grep -v "^patches/v4.4-000[0-3]-" list &&
393 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
394 ! grep -v "^Subject: \[PATCH v4.4 [0-3]/3\] " subjects
397 test_expect_success 'reroll (-v) count with a non number' '
398 rm -fr patches &&
399 git format-patch -o patches --cover-letter -v4rev2 main..side >list &&
400 ! grep -v "^patches/v4rev2-000[0-3]-" list &&
401 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
402 ! grep -v "^Subject: \[PATCH v4rev2 [0-3]/3\] " subjects
405 test_expect_success 'reroll (-v) count with a non-pathname character' '
406 rm -fr patches &&
407 git format-patch -o patches --cover-letter -v4---..././../--1/.2// main..side >list &&
408 ! grep -v "patches/v4-\.-\.-\.-1-\.2-000[0-3]-" list &&
409 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
410 ! grep -v "^Subject: \[PATCH v4---\.\.\./\./\.\./--1/\.2// [0-3]/3\] " subjects
413 check_threading () {
414 expect="$1" &&
415 shift &&
416 git format-patch --stdout "$@" >patch &&
417 # Prints everything between the Message-ID and In-Reply-To,
418 # and replaces all Message-ID-lookalikes by a sequence number
419 perl -ne '
420 if (/^(message-id|references|in-reply-to)/i) {
421 $printing = 1;
422 } elsif (/^\S/) {
423 $printing = 0;
425 if ($printing) {
426 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
427 for $k (keys %h) {s/$k/$h{$k}/};
428 print;
430 print "---\n" if /^From /i;
431 ' <patch >actual &&
432 test_cmp "$expect" actual
435 cat >>expect.no-threading <<EOF
441 test_expect_success 'no threading' '
442 git checkout side &&
443 check_threading expect.no-threading main
446 cat >expect.thread <<EOF
448 Message-Id: <0>
450 Message-Id: <1>
451 In-Reply-To: <0>
452 References: <0>
454 Message-Id: <2>
455 In-Reply-To: <0>
456 References: <0>
459 test_expect_success 'thread' '
460 check_threading expect.thread --thread main
463 cat >expect.in-reply-to <<EOF
465 Message-Id: <0>
466 In-Reply-To: <1>
467 References: <1>
469 Message-Id: <2>
470 In-Reply-To: <1>
471 References: <1>
473 Message-Id: <3>
474 In-Reply-To: <1>
475 References: <1>
478 test_expect_success 'thread in-reply-to' '
479 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
480 --thread main
483 cat >expect.cover-letter <<EOF
485 Message-Id: <0>
487 Message-Id: <1>
488 In-Reply-To: <0>
489 References: <0>
491 Message-Id: <2>
492 In-Reply-To: <0>
493 References: <0>
495 Message-Id: <3>
496 In-Reply-To: <0>
497 References: <0>
500 test_expect_success 'thread cover-letter' '
501 check_threading expect.cover-letter --cover-letter --thread main
504 cat >expect.cl-irt <<EOF
506 Message-Id: <0>
507 In-Reply-To: <1>
508 References: <1>
510 Message-Id: <2>
511 In-Reply-To: <0>
512 References: <1>
515 Message-Id: <3>
516 In-Reply-To: <0>
517 References: <1>
520 Message-Id: <4>
521 In-Reply-To: <0>
522 References: <1>
526 test_expect_success 'thread cover-letter in-reply-to' '
527 check_threading expect.cl-irt --cover-letter \
528 --in-reply-to="<test.message>" --thread main
531 test_expect_success 'thread explicit shallow' '
532 check_threading expect.cl-irt --cover-letter \
533 --in-reply-to="<test.message>" --thread=shallow main
536 cat >expect.deep <<EOF
538 Message-Id: <0>
540 Message-Id: <1>
541 In-Reply-To: <0>
542 References: <0>
544 Message-Id: <2>
545 In-Reply-To: <1>
546 References: <0>
550 test_expect_success 'thread deep' '
551 check_threading expect.deep --thread=deep main
554 cat >expect.deep-irt <<EOF
556 Message-Id: <0>
557 In-Reply-To: <1>
558 References: <1>
560 Message-Id: <2>
561 In-Reply-To: <0>
562 References: <1>
565 Message-Id: <3>
566 In-Reply-To: <2>
567 References: <1>
572 test_expect_success 'thread deep in-reply-to' '
573 check_threading expect.deep-irt --thread=deep \
574 --in-reply-to="<test.message>" main
577 cat >expect.deep-cl <<EOF
579 Message-Id: <0>
581 Message-Id: <1>
582 In-Reply-To: <0>
583 References: <0>
585 Message-Id: <2>
586 In-Reply-To: <1>
587 References: <0>
590 Message-Id: <3>
591 In-Reply-To: <2>
592 References: <0>
597 test_expect_success 'thread deep cover-letter' '
598 check_threading expect.deep-cl --cover-letter --thread=deep main
601 cat >expect.deep-cl-irt <<EOF
603 Message-Id: <0>
604 In-Reply-To: <1>
605 References: <1>
607 Message-Id: <2>
608 In-Reply-To: <0>
609 References: <1>
612 Message-Id: <3>
613 In-Reply-To: <2>
614 References: <1>
618 Message-Id: <4>
619 In-Reply-To: <3>
620 References: <1>
626 test_expect_success 'thread deep cover-letter in-reply-to' '
627 check_threading expect.deep-cl-irt --cover-letter \
628 --in-reply-to="<test.message>" --thread=deep main
631 test_expect_success 'thread via config' '
632 test_config format.thread true &&
633 check_threading expect.thread main
636 test_expect_success 'thread deep via config' '
637 test_config format.thread deep &&
638 check_threading expect.deep main
641 test_expect_success 'thread config + override' '
642 test_config format.thread deep &&
643 check_threading expect.thread --thread main
646 test_expect_success 'thread config + --no-thread' '
647 test_config format.thread deep &&
648 check_threading expect.no-threading --no-thread main
651 test_expect_success 'excessive subject' '
652 rm -rf patches/ &&
653 git checkout side &&
654 before=$(git hash-object file) &&
655 before=$(git rev-parse --short $before) &&
656 test_write_lines 5 6 1 2 3 A 4 B C 7 8 9 10 D E F >>file &&
657 after=$(git hash-object file) &&
658 after=$(git rev-parse --short $after) &&
659 git update-index file &&
660 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." &&
661 git format-patch -o patches/ main..side &&
662 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
665 test_expect_success 'failure to write cover-letter aborts gracefully' '
666 test_when_finished "rmdir 0000-cover-letter.patch" &&
667 mkdir 0000-cover-letter.patch &&
668 test_must_fail git format-patch --no-renames --cover-letter -1
671 test_expect_success 'cover-letter inherits diff options' '
672 git mv file foo &&
673 git commit -m foo &&
674 git format-patch --no-renames --cover-letter -1 &&
675 check_patch 0000-cover-letter.patch &&
676 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
677 git format-patch --cover-letter -1 -M &&
678 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
681 cat >expect <<EOF
682 This is an excessively long subject line for a message due to the
683 habit some projects have of not having a short, one-line subject at
684 the start of the commit message, but rather sticking a whole
685 paragraph right at the start as the only thing in the commit
686 message. It had better not become the filename for the patch.
691 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
692 git format-patch --cover-letter -2 &&
693 sed -e "1,/A U Thor/d" -e "/^\$/q" 0000-cover-letter.patch >output &&
694 test_cmp expect output
697 cat >expect <<EOF
698 index $before..$after 100644
699 --- a/file
700 +++ b/file
701 @@ -13,4 +13,20 @@ C
709 test_expect_success 'format-patch respects -U' '
710 git format-patch -U4 -2 &&
711 sed -e "1,/^diff/d" -e "/^+5/q" \
712 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
713 >output &&
714 test_cmp expect output
717 cat >expect <<EOF
719 diff --git a/file b/file
720 index $before..$after 100644
721 --- a/file
722 +++ b/file
723 @@ -14,3 +14,19 @@ C
730 test_expect_success 'format-patch -p suppresses stat' '
731 git format-patch -p -2 &&
732 sed -e "1,/^\$/d" -e "/^+5/q" 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&
733 test_cmp expect output
736 test_expect_success 'format-patch from a subdirectory (1)' '
737 filename=$(
738 rm -rf sub &&
739 mkdir -p sub/dir &&
740 cd sub/dir &&
741 git format-patch -1
742 ) &&
743 case "$filename" in
745 ;; # ok
747 echo "Oops? $filename"
748 false
750 esac &&
751 test -f "$filename"
754 test_expect_success 'format-patch from a subdirectory (2)' '
755 filename=$(
756 rm -rf sub &&
757 mkdir -p sub/dir &&
758 cd sub/dir &&
759 git format-patch -1 -o ..
760 ) &&
761 case "$filename" in
762 ../0*)
763 ;; # ok
765 echo "Oops? $filename"
766 false
768 esac &&
769 basename=$(expr "$filename" : ".*/\(.*\)") &&
770 test -f "sub/$basename"
773 test_expect_success 'format-patch from a subdirectory (3)' '
774 rm -f 0* &&
775 filename=$(
776 rm -rf sub &&
777 mkdir -p sub/dir &&
778 cd sub/dir &&
779 git format-patch -1 -o "$TRASH_DIRECTORY"
780 ) &&
781 basename=$(expr "$filename" : ".*/\(.*\)") &&
782 test -f "$basename"
785 test_expect_success 'format-patch --in-reply-to' '
786 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" >patch8 &&
787 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
788 grep "^References: <baz@foo.bar>" patch8
791 test_expect_success 'format-patch --signoff' '
792 git format-patch -1 --signoff --stdout >out &&
793 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
796 test_expect_success 'format-patch --notes --signoff' '
797 git notes --ref test add -m "test message" HEAD &&
798 git format-patch -1 --signoff --stdout --notes=test >out &&
799 # Three dashes must come after S-o-b
800 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
801 sed "1,/^Signed-off-by: /d" out | grep "test message" &&
802 # Notes message must come after three dashes
803 ! sed "/^---$/q" out | grep "test message" &&
804 sed "1,/^---$/d" out | grep "test message"
807 test_expect_success 'format-patch notes output control' '
808 git notes add -m "notes config message" HEAD &&
809 test_when_finished git notes remove HEAD &&
811 git format-patch -1 --stdout >out &&
812 ! grep "notes config message" out &&
813 git format-patch -1 --stdout --notes >out &&
814 grep "notes config message" out &&
815 git format-patch -1 --stdout --no-notes >out &&
816 ! grep "notes config message" out &&
817 git format-patch -1 --stdout --notes --no-notes >out &&
818 ! grep "notes config message" out &&
819 git format-patch -1 --stdout --no-notes --notes >out &&
820 grep "notes config message" out &&
822 test_config format.notes true &&
823 git format-patch -1 --stdout >out &&
824 grep "notes config message" out &&
825 git format-patch -1 --stdout --notes >out &&
826 grep "notes config message" out &&
827 git format-patch -1 --stdout --no-notes >out &&
828 ! grep "notes config message" out &&
829 git format-patch -1 --stdout --notes --no-notes >out &&
830 ! grep "notes config message" out &&
831 git format-patch -1 --stdout --no-notes --notes >out &&
832 grep "notes config message" out
835 test_expect_success 'format-patch with multiple notes refs' '
836 git notes --ref note1 add -m "this is note 1" HEAD &&
837 test_when_finished git notes --ref note1 remove HEAD &&
838 git notes --ref note2 add -m "this is note 2" HEAD &&
839 test_when_finished git notes --ref note2 remove HEAD &&
841 git format-patch -1 --stdout >out &&
842 ! grep "this is note 1" out &&
843 ! grep "this is note 2" out &&
844 git format-patch -1 --stdout --notes=note1 >out &&
845 grep "this is note 1" out &&
846 ! grep "this is note 2" out &&
847 git format-patch -1 --stdout --notes=note2 >out &&
848 ! grep "this is note 1" out &&
849 grep "this is note 2" out &&
850 git format-patch -1 --stdout --notes=note1 --notes=note2 >out &&
851 grep "this is note 1" out &&
852 grep "this is note 2" out &&
854 test_config format.notes note1 &&
855 git format-patch -1 --stdout >out &&
856 grep "this is note 1" out &&
857 ! grep "this is note 2" out &&
858 git format-patch -1 --stdout --no-notes >out &&
859 ! grep "this is note 1" out &&
860 ! grep "this is note 2" out &&
861 git format-patch -1 --stdout --notes=note2 >out &&
862 grep "this is note 1" out &&
863 grep "this is note 2" out &&
864 git format-patch -1 --stdout --no-notes --notes=note2 >out &&
865 ! grep "this is note 1" out &&
866 grep "this is note 2" out &&
868 git config --add format.notes note2 &&
869 git format-patch -1 --stdout >out &&
870 grep "this is note 1" out &&
871 grep "this is note 2" out &&
872 git format-patch -1 --stdout --no-notes >out &&
873 ! grep "this is note 1" out &&
874 ! grep "this is note 2" out
877 test_expect_success 'format-patch with multiple notes refs in config' '
878 test_when_finished "test_unconfig format.notes" &&
880 git notes --ref note1 add -m "this is note 1" HEAD &&
881 test_when_finished git notes --ref note1 remove HEAD &&
882 git notes --ref note2 add -m "this is note 2" HEAD &&
883 test_when_finished git notes --ref note2 remove HEAD &&
885 git config format.notes note1 &&
886 git format-patch -1 --stdout >out &&
887 grep "this is note 1" out &&
888 ! grep "this is note 2" out &&
889 git config format.notes note2 &&
890 git format-patch -1 --stdout >out &&
891 ! grep "this is note 1" out &&
892 grep "this is note 2" out &&
893 git config --add format.notes note1 &&
894 git format-patch -1 --stdout >out &&
895 grep "this is note 1" out &&
896 grep "this is note 2" out &&
898 git config --replace-all format.notes note1 &&
899 git config --add format.notes false &&
900 git format-patch -1 --stdout >out &&
901 ! grep "this is note 1" out &&
902 ! grep "this is note 2" out &&
903 git config --add format.notes note2 &&
904 git format-patch -1 --stdout >out &&
905 ! grep "this is note 1" out &&
906 grep "this is note 2" out
909 echo "fatal: --name-only does not make sense" >expect.name-only
910 echo "fatal: --name-status does not make sense" >expect.name-status
911 echo "fatal: --check does not make sense" >expect.check
913 test_expect_success 'options no longer allowed for format-patch' '
914 test_must_fail git format-patch --name-only 2>output &&
915 test_cmp expect.name-only output &&
916 test_must_fail git format-patch --name-status 2>output &&
917 test_cmp expect.name-status output &&
918 test_must_fail git format-patch --check 2>output &&
919 test_cmp expect.check output
922 test_expect_success 'format-patch --numstat should produce a patch' '
923 git format-patch --numstat --stdout main..side >output &&
924 grep "^diff --git a/" output >diff &&
925 test_line_count = 5 diff
928 test_expect_success 'format-patch -- <path>' '
929 git format-patch main..side -- file 2>error &&
930 ! grep "Use .--" error
933 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
934 git format-patch --ignore-if-in-upstream HEAD
937 test_expect_success 'get git version' '
938 git_version=$(git --version) &&
939 git_version=${git_version##* }
942 signature() {
943 printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
946 test_expect_success 'format-patch default signature' '
947 git format-patch --stdout -1 >patch &&
948 tail -n 3 patch >output &&
949 signature >expect &&
950 test_cmp expect output
953 test_expect_success 'format-patch --signature' '
954 git format-patch --stdout --signature="my sig" -1 >patch &&
955 tail -n 3 patch >output &&
956 signature "my sig" >expect &&
957 test_cmp expect output
960 test_expect_success 'format-patch with format.signature config' '
961 git config format.signature "config sig" &&
962 git format-patch --stdout -1 >output &&
963 grep "config sig" output
966 test_expect_success 'format-patch --signature overrides format.signature' '
967 git config format.signature "config sig" &&
968 git format-patch --stdout --signature="overrides" -1 >output &&
969 ! grep "config sig" output &&
970 grep "overrides" output
973 test_expect_success 'format-patch --no-signature ignores format.signature' '
974 git config format.signature "config sig" &&
975 git format-patch --stdout --signature="my sig" --no-signature \
976 -1 >output &&
977 check_patch output &&
978 ! grep "config sig" output &&
979 ! grep "my sig" output &&
980 ! grep "^-- \$" output
983 test_expect_success 'format-patch --signature --cover-letter' '
984 git config --unset-all format.signature &&
985 git format-patch --stdout --signature="my sig" --cover-letter \
986 -1 >output &&
987 grep "my sig" output >sig &&
988 test_line_count = 2 sig
991 test_expect_success 'format.signature="" suppresses signatures' '
992 git config format.signature "" &&
993 git format-patch --stdout -1 >output &&
994 check_patch output &&
995 ! grep "^-- \$" output
998 test_expect_success 'format-patch --no-signature suppresses signatures' '
999 git config --unset-all format.signature &&
1000 git format-patch --stdout --no-signature -1 >output &&
1001 check_patch output &&
1002 ! grep "^-- \$" output
1005 test_expect_success 'format-patch --signature="" suppresses signatures' '
1006 git format-patch --stdout --signature="" -1 >output &&
1007 check_patch output &&
1008 ! grep "^-- \$" output
1011 test_expect_success 'prepare mail-signature input' '
1012 cat >mail-signature <<-\EOF
1014 Test User <test.email@kernel.org>
1015 http://git.kernel.org/cgit/git/git.git
1017 git.kernel.org/?p=git/git.git;a=summary
1022 test_expect_success '--signature-file=file works' '
1023 git format-patch --stdout --signature-file=mail-signature -1 >output &&
1024 check_patch output &&
1025 sed -e "1,/^-- \$/d" output >actual &&
1027 cat mail-signature && echo
1028 } >expect &&
1029 test_cmp expect actual
1032 test_expect_success 'format.signaturefile works' '
1033 test_config format.signaturefile mail-signature &&
1034 git format-patch --stdout -1 >output &&
1035 check_patch output &&
1036 sed -e "1,/^-- \$/d" output >actual &&
1038 cat mail-signature && echo
1039 } >expect &&
1040 test_cmp expect actual
1043 test_expect_success '--no-signature suppresses format.signaturefile ' '
1044 test_config format.signaturefile mail-signature &&
1045 git format-patch --stdout --no-signature -1 >output &&
1046 check_patch output &&
1047 ! grep "^-- \$" output
1050 test_expect_success '--signature-file overrides format.signaturefile' '
1051 cat >other-mail-signature <<-\EOF &&
1052 Use this other signature instead of mail-signature.
1054 test_config format.signaturefile mail-signature &&
1055 git format-patch --stdout \
1056 --signature-file=other-mail-signature -1 >output &&
1057 check_patch output &&
1058 sed -e "1,/^-- \$/d" output >actual &&
1060 cat other-mail-signature && echo
1061 } >expect &&
1062 test_cmp expect actual
1065 test_expect_success '--signature overrides format.signaturefile' '
1066 test_config format.signaturefile mail-signature &&
1067 git format-patch --stdout --signature="my sig" -1 >output &&
1068 check_patch output &&
1069 grep "my sig" output
1072 test_expect_success TTY 'format-patch --stdout paginates' '
1073 rm -f pager_used &&
1074 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
1075 test_path_is_file pager_used
1078 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
1079 rm -f pager_used &&
1080 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
1081 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
1082 test_path_is_missing pager_used &&
1083 test_path_is_missing .git/pager_used
1086 test_expect_success 'format-patch handles multi-line subjects' '
1087 rm -rf patches/ &&
1088 echo content >>file &&
1089 test_write_lines one two three >msg &&
1090 git add file &&
1091 git commit -F msg &&
1092 git format-patch -o patches -1 &&
1093 grep ^Subject: patches/0001-one.patch >actual &&
1094 echo "Subject: [PATCH] one two three" >expect &&
1095 test_cmp expect actual
1098 test_expect_success 'format-patch handles multi-line encoded subjects' '
1099 rm -rf patches/ &&
1100 echo content >>file &&
1101 test_write_lines en två tre >msg &&
1102 git add file &&
1103 git commit -F msg &&
1104 git format-patch -o patches -1 &&
1105 grep ^Subject: patches/0001-en.patch >actual &&
1106 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
1107 test_cmp expect actual
1110 M8="foo bar "
1111 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1112 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1113 cat >expect <<'EOF'
1114 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1115 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1116 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1117 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1118 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1119 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1120 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1122 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
1123 echo content >>file &&
1124 git add file &&
1125 git commit -m "$M512" &&
1126 git format-patch --stdout -1 >patch &&
1127 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1128 test_cmp expect subject
1131 M8="föö bar "
1132 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1133 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1134 cat >expect <<'EOF'
1135 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1136 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1137 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1138 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1139 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1140 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1141 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1142 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1143 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1144 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1145 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1146 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1147 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1148 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1149 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1150 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1151 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1152 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1153 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1154 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1155 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1156 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1157 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1158 =?UTF-8?q?bar?=
1160 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
1161 rm -rf patches/ &&
1162 echo content >>file &&
1163 git add file &&
1164 git commit -m "$M512" &&
1165 git format-patch --stdout -1 >patch &&
1166 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1167 test_cmp expect subject
1170 check_author() {
1171 echo content >>file &&
1172 git add file &&
1173 GIT_AUTHOR_NAME=$1 git commit -m author-check &&
1174 git format-patch --stdout -1 >patch &&
1175 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1176 test_cmp expect actual
1179 cat >expect <<'EOF'
1180 From: "Foo B. Bar" <author@example.com>
1182 test_expect_success 'format-patch quotes dot in from-headers' '
1183 check_author "Foo B. Bar"
1186 cat >expect <<'EOF'
1187 From: "Foo \"The Baz\" Bar" <author@example.com>
1189 test_expect_success 'format-patch quotes double-quote in from-headers' '
1190 check_author "Foo \"The Baz\" Bar"
1193 cat >expect <<'EOF'
1194 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1196 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1197 check_author "Föo Bar"
1200 cat >expect <<'EOF'
1201 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1203 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1204 check_author "Föo B. Bar"
1207 cat >expect <<EOF
1208 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1209 <author@example.com>
1211 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1212 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1215 cat >expect <<'EOF'
1216 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1217 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1218 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1220 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1221 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"
1224 cat >expect <<'EOF'
1225 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1226 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1227 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1229 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1230 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"
1233 cat >expect <<'EOF'
1234 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1235 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1236 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1237 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1238 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1240 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1241 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"
1244 cat >expect <<'EOF'
1245 From: Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1246 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1247 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1249 test_expect_success 'format-patch wraps extremely long from-header (non-ASCII without Q-encoding)' '
1250 echo content >>file &&
1251 git add file &&
1252 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" \
1253 git commit -m author-check &&
1254 git format-patch --no-encode-email-headers --stdout -1 >patch &&
1255 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1256 test_cmp expect actual
1259 cat >expect <<'EOF'
1260 Subject: [PATCH] Foö
1262 test_expect_success 'subject lines are unencoded with --no-encode-email-headers' '
1263 echo content >>file &&
1264 git add file &&
1265 git commit -m "Foö" &&
1266 git format-patch --no-encode-email-headers -1 --stdout >patch &&
1267 grep ^Subject: patch >actual &&
1268 test_cmp expect actual
1271 cat >expect <<'EOF'
1272 Subject: [PATCH] Foö
1274 test_expect_success 'subject lines are unencoded with format.encodeEmailHeaders=false' '
1275 echo content >>file &&
1276 git add file &&
1277 git commit -m "Foö" &&
1278 git config format.encodeEmailHeaders false &&
1279 git format-patch -1 --stdout >patch &&
1280 grep ^Subject: patch >actual &&
1281 test_cmp expect actual
1284 cat >expect <<'EOF'
1285 Subject: [PATCH] =?UTF-8?q?Fo=C3=B6?=
1287 test_expect_success '--encode-email-headers overrides format.encodeEmailHeaders' '
1288 echo content >>file &&
1289 git add file &&
1290 git commit -m "Foö" &&
1291 git config format.encodeEmailHeaders false &&
1292 git format-patch --encode-email-headers -1 --stdout >patch &&
1293 grep ^Subject: patch >actual &&
1294 test_cmp expect actual
1297 cat >expect <<'EOF'
1298 Subject: header with . in it
1300 test_expect_success 'subject lines do not have 822 atom-quoting' '
1301 echo content >>file &&
1302 git add file &&
1303 git commit -m "header with . in it" &&
1304 git format-patch -k -1 --stdout >patch &&
1305 grep ^Subject: patch >actual &&
1306 test_cmp expect actual
1309 cat >expect <<'EOF'
1310 Subject: [PREFIX 1/1] header with . in it
1312 test_expect_success 'subject prefixes have space prepended' '
1313 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1314 grep ^Subject: patch >actual &&
1315 test_cmp expect actual
1318 cat >expect <<'EOF'
1319 Subject: [1/1] header with . in it
1321 test_expect_success 'empty subject prefix does not have extra space' '
1322 git format-patch -n -1 --stdout --subject-prefix= >patch &&
1323 grep ^Subject: patch >actual &&
1324 test_cmp expect actual
1327 test_expect_success '--rfc' '
1328 cat >expect <<-\EOF &&
1329 Subject: [RFC PATCH 1/1] header with . in it
1331 git format-patch -n -1 --stdout --rfc >patch &&
1332 grep ^Subject: patch >actual &&
1333 test_cmp expect actual
1336 test_expect_success '--from=ident notices bogus ident' '
1337 test_must_fail git format-patch -1 --stdout --from=foo >patch
1340 test_expect_success '--from=ident replaces author' '
1341 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1342 cat >expect <<-\EOF &&
1343 From: Me <me@example.com>
1345 From: A U Thor <author@example.com>
1348 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1349 test_cmp expect patch.head
1352 test_expect_success '--from uses committer ident' '
1353 git format-patch -1 --stdout --from >patch &&
1354 cat >expect <<-\EOF &&
1355 From: C O Mitter <committer@example.com>
1357 From: A U Thor <author@example.com>
1360 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1361 test_cmp expect patch.head
1364 test_expect_success '--from omits redundant in-body header' '
1365 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1366 cat >expect <<-\EOF &&
1367 From: A U Thor <author@example.com>
1370 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1371 test_cmp expect patch.head
1374 test_expect_success 'in-body headers trigger content encoding' '
1375 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1376 test_when_finished "git reset --hard HEAD^" &&
1377 git format-patch -1 --stdout --from >patch &&
1378 cat >expect <<-\EOF &&
1379 From: C O Mitter <committer@example.com>
1380 Content-Type: text/plain; charset=UTF-8
1382 From: éxötìc <author@example.com>
1385 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" patch >patch.head &&
1386 test_cmp expect patch.head
1389 append_signoff()
1391 C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1392 git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1393 sed -n -e "1,/^---$/p" append_signoff.patch |
1394 egrep -n "^Subject|Sign|^$"
1397 test_expect_success 'signoff: commit with no body' '
1398 append_signoff </dev/null >actual &&
1399 cat <<-\EOF | sed "s/EOL$//" >expect &&
1400 4:Subject: [PATCH] EOL
1402 9:Signed-off-by: C O Mitter <committer@example.com>
1404 test_cmp expect actual
1407 test_expect_success 'signoff: commit with only subject' '
1408 echo subject | append_signoff >actual &&
1409 cat >expect <<-\EOF &&
1410 4:Subject: [PATCH] subject
1412 9:Signed-off-by: C O Mitter <committer@example.com>
1414 test_cmp expect actual
1417 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1418 printf subject | append_signoff >actual &&
1419 cat >expect <<-\EOF &&
1420 4:Subject: [PATCH] subject
1422 9:Signed-off-by: C O Mitter <committer@example.com>
1424 test_cmp expect actual
1427 test_expect_success 'signoff: no existing signoffs' '
1428 append_signoff <<-\EOF >actual &&
1429 subject
1431 body
1433 cat >expect <<-\EOF &&
1434 4:Subject: [PATCH] subject
1437 11:Signed-off-by: C O Mitter <committer@example.com>
1439 test_cmp expect actual
1442 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1443 printf "subject\n\nbody" | append_signoff >actual &&
1444 cat >expect <<-\EOF &&
1445 4:Subject: [PATCH] subject
1448 11:Signed-off-by: C O Mitter <committer@example.com>
1450 test_cmp expect actual
1453 test_expect_success 'signoff: some random signoff' '
1454 append_signoff <<-\EOF >actual &&
1455 subject
1457 body
1459 Signed-off-by: my@house
1461 cat >expect <<-\EOF &&
1462 4:Subject: [PATCH] subject
1465 11:Signed-off-by: my@house
1466 12:Signed-off-by: C O Mitter <committer@example.com>
1468 test_cmp expect actual
1471 test_expect_success 'signoff: misc conforming footer elements' '
1472 append_signoff <<-\EOF >actual &&
1473 subject
1475 body
1477 Signed-off-by: my@house
1478 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1479 Tested-by: Some One <someone@example.com>
1480 Bug: 1234
1482 cat >expect <<-\EOF &&
1483 4:Subject: [PATCH] subject
1486 11:Signed-off-by: my@house
1487 15:Signed-off-by: C O Mitter <committer@example.com>
1489 test_cmp expect actual
1492 test_expect_success 'signoff: some random signoff-alike' '
1493 append_signoff <<-\EOF >actual &&
1494 subject
1496 body
1497 Fooled-by-me: my@house
1499 cat >expect <<-\EOF &&
1500 4:Subject: [PATCH] subject
1503 12:Signed-off-by: C O Mitter <committer@example.com>
1505 test_cmp expect actual
1508 test_expect_success 'signoff: not really a signoff' '
1509 append_signoff <<-\EOF >actual &&
1510 subject
1512 I want to mention about Signed-off-by: here.
1514 cat >expect <<-\EOF &&
1515 4:Subject: [PATCH] subject
1517 9:I want to mention about Signed-off-by: here.
1519 11:Signed-off-by: C O Mitter <committer@example.com>
1521 test_cmp expect actual
1524 test_expect_success 'signoff: not really a signoff (2)' '
1525 append_signoff <<-\EOF >actual &&
1526 subject
1528 My unfortunate
1529 Signed-off-by: example happens to be wrapped here.
1531 cat >expect <<-\EOF &&
1532 4:Subject: [PATCH] subject
1534 10:Signed-off-by: example happens to be wrapped here.
1535 11:Signed-off-by: C O Mitter <committer@example.com>
1537 test_cmp expect actual
1540 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1541 append_signoff <<-\EOF >actual &&
1542 subject
1544 Signed-off-by: my@house
1545 Signed-off-by: your@house
1547 A lot of houses.
1549 cat >expect <<-\EOF &&
1550 4:Subject: [PATCH] subject
1552 9:Signed-off-by: my@house
1553 10:Signed-off-by: your@house
1556 14:Signed-off-by: C O Mitter <committer@example.com>
1558 test_cmp expect actual
1561 test_expect_success 'signoff: the same signoff at the end' '
1562 append_signoff <<-\EOF >actual &&
1563 subject
1565 body
1567 Signed-off-by: C O Mitter <committer@example.com>
1569 cat >expect <<-\EOF &&
1570 4:Subject: [PATCH] subject
1573 11:Signed-off-by: C O Mitter <committer@example.com>
1575 test_cmp expect actual
1578 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1579 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1580 append_signoff >actual &&
1581 cat >expect <<-\EOF &&
1582 4:Subject: [PATCH] subject
1584 9:Signed-off-by: C O Mitter <committer@example.com>
1586 test_cmp expect actual
1589 test_expect_success 'signoff: the same signoff NOT at the end' '
1590 append_signoff <<-\EOF >actual &&
1591 subject
1593 body
1595 Signed-off-by: C O Mitter <committer@example.com>
1596 Signed-off-by: my@house
1598 cat >expect <<-\EOF &&
1599 4:Subject: [PATCH] subject
1602 11:Signed-off-by: C O Mitter <committer@example.com>
1603 12:Signed-off-by: my@house
1605 test_cmp expect actual
1608 test_expect_success 'signoff: tolerate garbage in conforming footer' '
1609 append_signoff <<-\EOF >actual &&
1610 subject
1612 body
1614 Tested-by: my@house
1615 Some Trash
1616 Signed-off-by: C O Mitter <committer@example.com>
1618 cat >expect <<-\EOF &&
1619 4:Subject: [PATCH] subject
1622 13:Signed-off-by: C O Mitter <committer@example.com>
1624 test_cmp expect actual
1627 test_expect_success 'signoff: respect trailer config' '
1628 append_signoff <<-\EOF >actual &&
1629 subject
1631 Myfooter: x
1632 Some Trash
1634 cat >expect <<-\EOF &&
1635 4:Subject: [PATCH] subject
1638 12:Signed-off-by: C O Mitter <committer@example.com>
1640 test_cmp expect actual &&
1642 test_config trailer.Myfooter.ifexists add &&
1643 append_signoff <<-\EOF >actual &&
1644 subject
1646 Myfooter: x
1647 Some Trash
1649 cat >expect <<-\EOF &&
1650 4:Subject: [PATCH] subject
1652 11:Signed-off-by: C O Mitter <committer@example.com>
1654 test_cmp expect actual
1657 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1658 append_signoff <<-\EOF >actual &&
1659 subject
1661 body
1663 Reviewed-id: Noone
1664 Tested-by: my@house
1665 Change-id: Ideadbeef
1666 Signed-off-by: C O Mitter <committer@example.com>
1667 Bug: 1234
1669 cat >expect <<-\EOF &&
1670 4:Subject: [PATCH] subject
1673 14:Signed-off-by: C O Mitter <committer@example.com>
1675 test_cmp expect actual
1678 test_expect_success 'format patch ignores color.ui' '
1679 test_unconfig color.ui &&
1680 git format-patch --stdout -1 >expect &&
1681 test_config color.ui always &&
1682 git format-patch --stdout -1 >actual &&
1683 test_cmp expect actual
1686 test_expect_success 'format patch respects diff.relative' '
1687 rm -rf subdir &&
1688 mkdir subdir &&
1689 echo other content >subdir/file2 &&
1690 git add subdir/file2 &&
1691 git commit -F msg &&
1692 test_unconfig diff.relative &&
1693 git format-patch --relative=subdir --stdout -1 >expect &&
1694 test_config diff.relative true &&
1695 git -C subdir format-patch --stdout -1 >actual &&
1696 test_cmp expect actual
1699 test_expect_success 'cover letter with invalid --cover-from-description and config' '
1700 test_config branch.rebuild-1.description "config subject
1702 body" &&
1703 test_must_fail git format-patch --cover-letter --cover-from-description garbage main &&
1704 test_config format.coverFromDescription garbage &&
1705 test_must_fail git format-patch --cover-letter main
1708 test_expect_success 'cover letter with format.coverFromDescription = default' '
1709 test_config branch.rebuild-1.description "config subject
1711 body" &&
1712 test_config format.coverFromDescription default &&
1713 git checkout rebuild-1 &&
1714 git format-patch --stdout --cover-letter main >actual &&
1715 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1716 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1717 grep "^config subject$" actual &&
1718 grep "^body$" actual
1721 test_expect_success 'cover letter with --cover-from-description default' '
1722 test_config branch.rebuild-1.description "config subject
1724 body" &&
1725 git checkout rebuild-1 &&
1726 git format-patch --stdout --cover-letter --cover-from-description default main >actual &&
1727 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1728 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1729 grep "^config subject$" actual &&
1730 grep "^body$" actual
1733 test_expect_success 'cover letter with format.coverFromDescription = none' '
1734 test_config branch.rebuild-1.description "config subject
1736 body" &&
1737 test_config format.coverFromDescription none &&
1738 git checkout rebuild-1 &&
1739 git format-patch --stdout --cover-letter main >actual &&
1740 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1741 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1742 ! grep "^config subject$" actual &&
1743 ! grep "^body$" actual
1746 test_expect_success 'cover letter with --cover-from-description none' '
1747 test_config branch.rebuild-1.description "config subject
1749 body" &&
1750 git checkout rebuild-1 &&
1751 git format-patch --stdout --cover-letter --cover-from-description none main >actual &&
1752 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1753 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1754 ! grep "^config subject$" actual &&
1755 ! grep "^body$" actual
1758 test_expect_success 'cover letter with format.coverFromDescription = message' '
1759 test_config branch.rebuild-1.description "config subject
1761 body" &&
1762 test_config format.coverFromDescription message &&
1763 git checkout rebuild-1 &&
1764 git format-patch --stdout --cover-letter main >actual &&
1765 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1766 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1767 grep "^config subject$" actual &&
1768 grep "^body$" actual
1771 test_expect_success 'cover letter with --cover-from-description message' '
1772 test_config branch.rebuild-1.description "config subject
1774 body" &&
1775 git checkout rebuild-1 &&
1776 git format-patch --stdout --cover-letter --cover-from-description message main >actual &&
1777 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1778 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1779 grep "^config subject$" actual &&
1780 grep "^body$" actual
1783 test_expect_success 'cover letter with format.coverFromDescription = subject' '
1784 test_config branch.rebuild-1.description "config subject
1786 body" &&
1787 test_config format.coverFromDescription subject &&
1788 git checkout rebuild-1 &&
1789 git format-patch --stdout --cover-letter main >actual &&
1790 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1791 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1792 ! grep "^config subject$" actual &&
1793 grep "^body$" actual
1796 test_expect_success 'cover letter with --cover-from-description subject' '
1797 test_config branch.rebuild-1.description "config subject
1799 body" &&
1800 git checkout rebuild-1 &&
1801 git format-patch --stdout --cover-letter --cover-from-description subject main >actual &&
1802 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1803 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1804 ! grep "^config subject$" actual &&
1805 grep "^body$" actual
1808 test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' '
1809 test_config branch.rebuild-1.description "config subject
1811 body" &&
1812 test_config format.coverFromDescription auto &&
1813 git checkout rebuild-1 &&
1814 git format-patch --stdout --cover-letter main >actual &&
1815 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1816 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1817 ! grep "^config subject$" actual &&
1818 grep "^body$" actual
1821 test_expect_success 'cover letter with --cover-from-description auto (short subject line)' '
1822 test_config branch.rebuild-1.description "config subject
1824 body" &&
1825 git checkout rebuild-1 &&
1826 git format-patch --stdout --cover-letter --cover-from-description auto main >actual &&
1827 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1828 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1829 ! grep "^config subject$" actual &&
1830 grep "^body$" actual
1833 test_expect_success 'cover letter with format.coverFromDescription = auto (long subject line)' '
1834 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
1836 body" &&
1837 test_config format.coverFromDescription auto &&
1838 git checkout rebuild-1 &&
1839 git format-patch --stdout --cover-letter main >actual &&
1840 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1841 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1842 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1843 grep "^body$" actual
1846 test_expect_success 'cover letter with --cover-from-description auto (long subject line)' '
1847 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
1849 body" &&
1850 git checkout rebuild-1 &&
1851 git format-patch --stdout --cover-letter --cover-from-description auto main >actual &&
1852 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1853 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1854 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1855 grep "^body$" actual
1858 test_expect_success 'cover letter with command-line --cover-from-description overrides config' '
1859 test_config branch.rebuild-1.description "config subject
1861 body" &&
1862 test_config format.coverFromDescription none &&
1863 git checkout rebuild-1 &&
1864 git format-patch --stdout --cover-letter --cover-from-description subject main >actual &&
1865 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1866 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1867 ! grep "^config subject$" actual &&
1868 grep "^body$" actual
1871 test_expect_success 'cover letter using branch description (1)' '
1872 git checkout rebuild-1 &&
1873 test_config branch.rebuild-1.description hello &&
1874 git format-patch --stdout --cover-letter main >actual &&
1875 grep hello actual
1878 test_expect_success 'cover letter using branch description (2)' '
1879 git checkout rebuild-1 &&
1880 test_config branch.rebuild-1.description hello &&
1881 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1882 grep hello actual
1885 test_expect_success 'cover letter using branch description (3)' '
1886 git checkout rebuild-1 &&
1887 test_config branch.rebuild-1.description hello &&
1888 git format-patch --stdout --cover-letter ^main rebuild-1 >actual &&
1889 grep hello actual
1892 test_expect_success 'cover letter using branch description (4)' '
1893 git checkout rebuild-1 &&
1894 test_config branch.rebuild-1.description hello &&
1895 git format-patch --stdout --cover-letter main.. >actual &&
1896 grep hello actual
1899 test_expect_success 'cover letter using branch description (5)' '
1900 git checkout rebuild-1 &&
1901 test_config branch.rebuild-1.description hello &&
1902 git format-patch --stdout --cover-letter -2 HEAD >actual &&
1903 grep hello actual
1906 test_expect_success 'cover letter using branch description (6)' '
1907 git checkout rebuild-1 &&
1908 test_config branch.rebuild-1.description hello &&
1909 git format-patch --stdout --cover-letter -2 >actual &&
1910 grep hello actual
1913 test_expect_success 'cover letter with nothing' '
1914 git format-patch --stdout --cover-letter >actual &&
1915 test_line_count = 0 actual
1918 test_expect_success 'cover letter auto' '
1919 mkdir -p tmp &&
1920 test_when_finished "rm -rf tmp;
1921 git config --unset format.coverletter" &&
1923 git config format.coverletter auto &&
1924 git format-patch -o tmp -1 >list &&
1925 test_line_count = 1 list &&
1926 git format-patch -o tmp -2 >list &&
1927 test_line_count = 3 list
1930 test_expect_success 'cover letter auto user override' '
1931 mkdir -p tmp &&
1932 test_when_finished "rm -rf tmp;
1933 git config --unset format.coverletter" &&
1935 git config format.coverletter auto &&
1936 git format-patch -o tmp --cover-letter -1 >list &&
1937 test_line_count = 2 list &&
1938 git format-patch -o tmp --cover-letter -2 >list &&
1939 test_line_count = 3 list &&
1940 git format-patch -o tmp --no-cover-letter -1 >list &&
1941 test_line_count = 1 list &&
1942 git format-patch -o tmp --no-cover-letter -2 >list &&
1943 test_line_count = 2 list
1946 test_expect_success 'format-patch --zero-commit' '
1947 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1948 grep "^From " patch2 | sort | uniq >actual &&
1949 echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
1950 test_cmp expect actual
1953 test_expect_success 'From line has expected format' '
1954 git format-patch --stdout v2..v1 >patch2 &&
1955 grep "^From " patch2 >from &&
1956 grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1957 test_cmp from filtered
1960 test_expect_success 'format-patch -o with no leading directories' '
1961 rm -fr patches &&
1962 git format-patch -o patches main..side &&
1963 count=$(git rev-list --count main..side) &&
1964 ls patches >list &&
1965 test_line_count = $count list
1968 test_expect_success 'format-patch -o with leading existing directories' '
1969 rm -rf existing-dir &&
1970 mkdir existing-dir &&
1971 git format-patch -o existing-dir/patches main..side &&
1972 count=$(git rev-list --count main..side) &&
1973 ls existing-dir/patches >list &&
1974 test_line_count = $count list
1977 test_expect_success 'format-patch -o with leading non-existing directories' '
1978 rm -rf non-existing-dir &&
1979 git format-patch -o non-existing-dir/patches main..side &&
1980 count=$(git rev-list --count main..side) &&
1981 test_path_is_dir non-existing-dir &&
1982 ls non-existing-dir/patches >list &&
1983 test_line_count = $count list
1986 test_expect_success 'format-patch format.outputDirectory option' '
1987 test_config format.outputDirectory patches &&
1988 rm -fr patches &&
1989 git format-patch main..side &&
1990 count=$(git rev-list --count main..side) &&
1991 ls patches >list &&
1992 test_line_count = $count list
1995 test_expect_success 'format-patch -o overrides format.outputDirectory' '
1996 test_config format.outputDirectory patches &&
1997 rm -fr patches patchset &&
1998 git format-patch main..side -o patchset &&
1999 test_path_is_missing patches &&
2000 test_path_is_dir patchset
2003 test_expect_success 'format-patch forbids multiple outputs' '
2004 rm -fr outfile outdir &&
2005 test_must_fail \
2006 git format-patch --stdout --output-directory=outdir &&
2007 test_must_fail \
2008 git format-patch --stdout --output=outfile &&
2009 test_must_fail \
2010 git format-patch --output=outfile --output-directory=outdir
2013 test_expect_success 'configured outdir does not conflict with output options' '
2014 rm -fr outfile outdir &&
2015 test_config format.outputDirectory outdir &&
2016 git format-patch --stdout &&
2017 test_path_is_missing outdir &&
2018 git format-patch --output=outfile &&
2019 test_path_is_missing outdir
2022 test_expect_success 'format-patch --output' '
2023 rm -fr outfile &&
2024 git format-patch -3 --stdout HEAD >expect &&
2025 git format-patch -3 --output=outfile HEAD &&
2026 test_cmp expect outfile
2029 test_expect_success 'format-patch --cover-letter --output' '
2030 rm -fr outfile &&
2031 git format-patch --cover-letter -3 --stdout HEAD >expect &&
2032 git format-patch --cover-letter -3 --output=outfile HEAD &&
2033 test_cmp expect outfile
2036 test_expect_success 'format-patch --base' '
2037 git checkout patchid &&
2039 git format-patch --stdout --base=HEAD~3 -1 >patch &&
2040 tail -n 7 patch >actual1 &&
2042 git format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&
2043 tail -n 7 patch >actual2 &&
2045 echo >expect &&
2046 git rev-parse HEAD~3 >commit-id-base &&
2047 echo "base-commit: $(cat commit-id-base)" >>expect &&
2049 git show --patch HEAD~2 >patch &&
2050 git patch-id --stable <patch >patch.id.raw &&
2051 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2053 git show --patch HEAD~1 >patch &&
2054 git patch-id --stable <patch >patch.id.raw &&
2055 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2057 signature >>expect &&
2058 test_cmp expect actual1 &&
2059 test_cmp expect actual2 &&
2061 echo >fail &&
2062 echo "base-commit: $(cat commit-id-base)" >>fail &&
2064 git show --patch HEAD~2 >patch &&
2065 git patch-id --unstable <patch >patch.id.raw &&
2066 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2068 git show --patch HEAD~1 >patch &&
2069 git patch-id --unstable <patch >patch.id.raw &&
2070 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2072 signature >>fail &&
2073 ! test_cmp fail actual1 &&
2074 ! test_cmp fail actual2
2077 test_expect_success 'format-patch --base errors out when base commit is in revision list' '
2078 test_must_fail git format-patch --base=HEAD -2 &&
2079 test_must_fail git format-patch --base=HEAD~1 -2 &&
2080 git format-patch --stdout --base=HEAD~2 -2 >patch &&
2081 grep "^base-commit:" patch >actual &&
2082 git rev-parse HEAD~2 >commit-id-base &&
2083 echo "base-commit: $(cat commit-id-base)" >expect &&
2084 test_cmp expect actual
2087 test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
2088 # For history as below:
2090 # ---Q---P---Z---Y---*---X
2091 # \ /
2092 # ------------W
2094 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
2095 git checkout -b topic1 main &&
2096 git rev-parse HEAD >commit-id-base &&
2097 test_commit P &&
2098 git rev-parse HEAD >commit-id-P &&
2099 test_commit Z &&
2100 git rev-parse HEAD >commit-id-Z &&
2101 test_commit Y &&
2102 git checkout -b topic2 main &&
2103 test_commit W &&
2104 git merge topic1 &&
2105 test_commit X &&
2106 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
2107 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
2108 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
2109 grep "^base-commit:" patch >actual &&
2110 echo "base-commit: $(cat commit-id-base)" >expect &&
2111 test_cmp expect actual
2114 test_expect_success 'format-patch --base=auto' '
2115 git checkout -b upstream main &&
2116 git checkout -b local upstream &&
2117 git branch --set-upstream-to=upstream &&
2118 test_commit N1 &&
2119 test_commit N2 &&
2120 git format-patch --stdout --base=auto -2 >patch &&
2121 grep "^base-commit:" patch >actual &&
2122 git rev-parse upstream >commit-id-base &&
2123 echo "base-commit: $(cat commit-id-base)" >expect &&
2124 test_cmp expect actual
2127 test_expect_success 'format-patch errors out when history involves criss-cross' '
2128 # setup criss-cross history
2130 # B---M1---D
2131 # / \ /
2132 # A X
2133 # \ / \
2134 # C---M2---E
2136 git checkout main &&
2137 test_commit A &&
2138 git checkout -b xb main &&
2139 test_commit B &&
2140 git checkout -b xc main &&
2141 test_commit C &&
2142 git checkout -b xbc xb -- &&
2143 git merge xc &&
2144 git checkout -b xcb xc -- &&
2145 git branch --set-upstream-to=xbc &&
2146 git merge xb &&
2147 git checkout xbc &&
2148 test_commit D &&
2149 git checkout xcb &&
2150 test_commit E &&
2151 test_must_fail git format-patch --base=auto -1
2154 test_expect_success 'format-patch format.useAutoBase whenAble history involves criss-cross' '
2155 test_config format.useAutoBase whenAble &&
2156 git format-patch -1 >patch &&
2157 ! grep "^base-commit:" patch
2160 test_expect_success 'format-patch format.useAutoBase option' '
2161 git checkout local &&
2162 test_config format.useAutoBase true &&
2163 git format-patch --stdout -1 >patch &&
2164 grep "^base-commit:" patch >actual &&
2165 git rev-parse upstream >commit-id-base &&
2166 echo "base-commit: $(cat commit-id-base)" >expect &&
2167 test_cmp expect actual
2170 test_expect_success 'format-patch format.useAutoBase option with whenAble' '
2171 git checkout local &&
2172 test_config format.useAutoBase whenAble &&
2173 git format-patch --stdout -1 >patch &&
2174 grep "^base-commit:" patch >actual &&
2175 git rev-parse upstream >commit-id-base &&
2176 echo "base-commit: $(cat commit-id-base)" >expect &&
2177 test_cmp expect actual
2180 test_expect_success 'format-patch --base overrides format.useAutoBase' '
2181 test_config format.useAutoBase true &&
2182 git format-patch --stdout --base=HEAD~1 -1 >patch &&
2183 grep "^base-commit:" patch >actual &&
2184 git rev-parse HEAD~1 >commit-id-base &&
2185 echo "base-commit: $(cat commit-id-base)" >expect &&
2186 test_cmp expect actual
2189 test_expect_success 'format-patch --no-base overrides format.useAutoBase' '
2190 test_config format.useAutoBase true &&
2191 git format-patch --stdout --no-base -1 >patch &&
2192 ! grep "^base-commit:" patch
2195 test_expect_success 'format-patch --no-base overrides format.useAutoBase whenAble' '
2196 test_config format.useAutoBase whenAble &&
2197 git format-patch --stdout --no-base -1 >patch &&
2198 ! grep "^base-commit:" patch
2201 test_expect_success 'format-patch --base with --attach' '
2202 git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
2203 sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
2204 patch >actual &&
2205 test_write_lines 1 2 >expect &&
2206 test_cmp expect actual
2208 test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
2209 test_when_finished "rm -fr patches" &&
2210 git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
2211 ! egrep "^--+mimemime" patches/0000*.patch &&
2212 egrep "^--+mimemime$" patches/0001*.patch >output &&
2213 test_line_count = 2 output &&
2214 egrep "^--+mimemime--$" patches/0001*.patch >output &&
2215 test_line_count = 1 output
2218 test_expect_success 'format-patch --pretty=mboxrd' '
2219 sp=" " &&
2220 cat >msg <<-INPUT_END &&
2221 mboxrd should escape the body
2223 From could trip up a loose mbox parser
2224 >From extra escape for reversibility
2225 >>From extra escape for reversibility 2
2226 from lower case not escaped
2227 Fromm bad speling not escaped
2228 From with leading space not escaped
2231 From
2232 From$sp
2233 From $sp
2234 From $sp
2235 INPUT_END
2237 cat >expect <<-INPUT_END &&
2238 >From could trip up a loose mbox parser
2239 >>From extra escape for reversibility
2240 >>>From extra escape for reversibility 2
2241 from lower case not escaped
2242 Fromm bad speling not escaped
2243 From with leading space not escaped
2246 From
2247 From
2248 From
2249 From
2250 INPUT_END
2252 C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
2253 git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
2254 git grep -h --no-index -A11 \
2255 "^>From could trip up a loose mbox parser" patch >actual &&
2256 test_cmp expect actual
2259 test_expect_success 'interdiff: setup' '
2260 git checkout -b boop main &&
2261 test_commit fnorp blorp &&
2262 test_commit fleep blorp
2265 test_expect_success 'interdiff: cover-letter' '
2266 sed "y/q/ /" >expect <<-\EOF &&
2267 +fleep
2270 git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
2271 test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch &&
2272 test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch &&
2273 sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual &&
2274 test_cmp expect actual
2277 test_expect_success 'interdiff: reroll-count' '
2278 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2279 test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2282 test_expect_success 'interdiff: reroll-count with a non-integer' '
2283 git format-patch --cover-letter --interdiff=boop~2 -v2.2 -1 boop &&
2284 test_i18ngrep "^Interdiff:$" v2.2-0000-cover-letter.patch
2287 test_expect_success 'interdiff: reroll-count with a integer' '
2288 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2289 test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2292 test_expect_success 'interdiff: solo-patch' '
2293 cat >expect <<-\EOF &&
2294 +fleep
2297 git format-patch --interdiff=boop~2 -1 boop &&
2298 test_i18ngrep "^Interdiff:$" 0001-fleep.patch &&
2299 sed "1,/^ @@ /d; /^$/q" 0001-fleep.patch >actual &&
2300 test_cmp expect actual
2303 test_done