]> git.ipfire.org Git - thirdparty/git.git/blob - t/t4014-format-patch.sh
format-patch: "--rfc=-(WIP)" appends to produce [PATCH (WIP)]
[thirdparty/git.git] / t / t4014-format-patch.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2006 Junio C Hamano
4 #
5
6 test_description='various format-patch tests'
7
8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
10
11 . ./test-lib.sh
12 . "$TEST_DIRECTORY"/lib-terminal.sh
13
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 &&
21
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" &&
26
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 &&
32
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." &&
37
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" &&
43
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" &&
61
62 git checkout -b empty main &&
63 test_tick &&
64 git commit --allow-empty -m "empty commit" &&
65
66 git checkout main
67 '
68
69 test_expect_success 'format-patch --ignore-if-in-upstream' '
70 git format-patch --stdout main..side >patch0 &&
71 grep "^From " patch0 >from0 &&
72 test_line_count = 3 from0
73 '
74
75 test_expect_success 'format-patch --ignore-if-in-upstream' '
76 git format-patch --stdout \
77 --ignore-if-in-upstream main..side >patch1 &&
78 grep "^From " patch1 >from1 &&
79 test_line_count = 2 from1
80 '
81
82 test_expect_success 'format-patch --ignore-if-in-upstream handles tags' '
83 git tag -a v1 -m tag side &&
84 git tag -a v2 -m tag main &&
85 git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
86 grep "^From " patch1 >from1 &&
87 test_line_count = 2 from1
88 '
89
90 test_expect_success "format-patch doesn't consider merge commits" '
91 git checkout -b feature main &&
92 echo "Another line" >>file &&
93 test_tick &&
94 git commit -am "Feature branch change #1" &&
95 echo "Yet another line" >>file &&
96 test_tick &&
97 git commit -am "Feature branch change #2" &&
98 git checkout -b merger main &&
99 test_tick &&
100 git merge --no-ff feature &&
101 git format-patch -3 --stdout >patch &&
102 grep "^From " patch >from &&
103 test_line_count = 3 from
104 '
105
106 test_expect_success 'format-patch result applies' '
107 git checkout -b rebuild-0 main &&
108 git am -3 patch0 &&
109 git rev-list main.. >list &&
110 test_line_count = 2 list
111 '
112
113 test_expect_success 'format-patch --ignore-if-in-upstream result applies' '
114 git checkout -b rebuild-1 main &&
115 git am -3 patch1 &&
116 git rev-list main.. >list &&
117 test_line_count = 2 list
118 '
119
120 test_expect_success 'commit did not screw up the log message' '
121 git cat-file commit side >actual &&
122 grep "^Side .* with .* backslash-n" actual
123 '
124
125 test_expect_success 'format-patch did not screw up the log message' '
126 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
127 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
128 '
129
130 test_expect_success 'replay did not screw up the log message' '
131 git cat-file commit rebuild-1 >actual &&
132 grep "^Side .* with .* backslash-n" actual
133 '
134
135 test_expect_success 'format-patch empty commit' '
136 git format-patch --stdout main..empty >empty &&
137 grep "^From " empty >from &&
138 test_line_count = 1 from
139 '
140
141 test_expect_success 'extra headers' '
142 git config format.headers "To: R E Cipient <rcipient@example.com>
143 " &&
144 git config --add format.headers "Cc: S E Cipient <scipient@example.com>
145 " &&
146 git format-patch --stdout main..side >patch2 &&
147 sed -e "/^\$/q" patch2 >hdrs2 &&
148 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
149 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
150 '
151
152 test_expect_success 'extra headers without newlines' '
153 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
154 git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
155 git format-patch --stdout main..side >patch3 &&
156 sed -e "/^\$/q" patch3 >hdrs3 &&
157 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
158 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
159 '
160
161 test_expect_success 'extra headers with multiple To:s' '
162 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
163 git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
164 git format-patch --stdout main..side >patch4 &&
165 sed -e "/^\$/q" patch4 >hdrs4 &&
166 grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
167 grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
168 '
169
170 test_expect_success 'additional command line cc (ascii)' '
171 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
172 git format-patch --cc="S E Cipient <scipient@example.com>" --stdout main..side >patch5 &&
173 sed -e "/^\$/q" patch5 >hdrs5 &&
174 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
175 grep "^ *S E Cipient <scipient@example.com>\$" hdrs5
176 '
177
178 test_expect_failure 'additional command line cc (rfc822)' '
179 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
180 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout main..side >patch5 &&
181 sed -e "/^\$/q" patch5 >hdrs5 &&
182 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
183 grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" hdrs5
184 '
185
186 test_expect_success 'command line headers' '
187 git config --unset-all format.headers &&
188 git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout main..side >patch6 &&
189 sed -e "/^\$/q" patch6 >hdrs6 &&
190 grep "^Cc: R E Cipient <rcipient@example.com>\$" hdrs6
191 '
192
193 test_expect_success 'configuration headers and command line headers' '
194 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
195 git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout main..side >patch7 &&
196 sed -e "/^\$/q" patch7 >hdrs7 &&
197 grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs7 &&
198 grep "^ *S E Cipient <scipient@example.com>\$" hdrs7
199 '
200
201 test_expect_success 'command line To: header (ascii)' '
202 git config --unset-all format.headers &&
203 git format-patch --to="R E Cipient <rcipient@example.com>" --stdout main..side >patch8 &&
204 sed -e "/^\$/q" patch8 >hdrs8 &&
205 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs8
206 '
207
208 test_expect_failure 'command line To: header (rfc822)' '
209 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout main..side >patch8 &&
210 sed -e "/^\$/q" patch8 >hdrs8 &&
211 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs8
212 '
213
214 test_expect_failure 'command line To: header (rfc2047)' '
215 git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout main..side >patch8 &&
216 sed -e "/^\$/q" patch8 >hdrs8 &&
217 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs8
218 '
219
220 test_expect_success 'configuration To: header (ascii)' '
221 git config format.to "R E Cipient <rcipient@example.com>" &&
222 git format-patch --stdout main..side >patch9 &&
223 sed -e "/^\$/q" patch9 >hdrs9 &&
224 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs9
225 '
226
227 test_expect_failure 'configuration To: header (rfc822)' '
228 git config format.to "R. E. Cipient <rcipient@example.com>" &&
229 git format-patch --stdout main..side >patch9 &&
230 sed -e "/^\$/q" patch9 >hdrs9 &&
231 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs9
232 '
233
234 test_expect_failure 'configuration To: header (rfc2047)' '
235 git config format.to "R Ä Cipient <rcipient@example.com>" &&
236 git format-patch --stdout main..side >patch9 &&
237 sed -e "/^\$/q" patch9 >hdrs9 &&
238 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs9
239 '
240
241 # check_patch <patch>: Verify that <patch> looks like a half-sane
242 # patch email to avoid a false positive with !grep
243 check_patch () {
244 grep -e "^From:" "$1" &&
245 grep -e "^Date:" "$1" &&
246 grep -e "^Subject:" "$1"
247 }
248
249 test_expect_success 'format.from=false' '
250 git -c format.from=false format-patch --stdout main..side >patch &&
251 sed -e "/^\$/q" patch >hdrs &&
252 check_patch patch &&
253 ! grep "^From: C O Mitter <committer@example.com>\$" hdrs
254 '
255
256 test_expect_success 'format.from=true' '
257 git -c format.from=true format-patch --stdout main..side >patch &&
258 sed -e "/^\$/q" patch >hdrs &&
259 check_patch hdrs &&
260 grep "^From: C O Mitter <committer@example.com>\$" hdrs
261 '
262
263 test_expect_success 'format.from with address' '
264 git -c format.from="F R Om <from@example.com>" format-patch --stdout main..side >patch &&
265 sed -e "/^\$/q" patch >hdrs &&
266 check_patch hdrs &&
267 grep "^From: F R Om <from@example.com>\$" hdrs
268 '
269
270 test_expect_success '--no-from overrides format.from' '
271 git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout main..side >patch &&
272 sed -e "/^\$/q" patch >hdrs &&
273 check_patch hdrs &&
274 ! grep "^From: F R Om <from@example.com>\$" hdrs
275 '
276
277 test_expect_success '--from overrides format.from' '
278 git -c format.from="F R Om <from@example.com>" format-patch --from --stdout main..side >patch &&
279 sed -e "/^\$/q" patch >hdrs &&
280 check_patch hdrs &&
281 ! grep "^From: F R Om <from@example.com>\$" hdrs
282 '
283
284 test_expect_success '--no-to overrides config.to' '
285 git config --replace-all format.to \
286 "R E Cipient <rcipient@example.com>" &&
287 git format-patch --no-to --stdout main..side >patch10 &&
288 sed -e "/^\$/q" patch10 >hdrs10 &&
289 check_patch hdrs10 &&
290 ! grep "^To: R E Cipient <rcipient@example.com>\$" hdrs10
291 '
292
293 test_expect_success '--no-to and --to replaces config.to' '
294 git config --replace-all format.to \
295 "Someone <someone@out.there>" &&
296 git format-patch --no-to --to="Someone Else <else@out.there>" \
297 --stdout main..side >patch11 &&
298 sed -e "/^\$/q" patch11 >hdrs11 &&
299 check_patch hdrs11 &&
300 ! grep "^To: Someone <someone@out.there>\$" hdrs11 &&
301 grep "^To: Someone Else <else@out.there>\$" hdrs11
302 '
303
304 test_expect_success '--no-cc overrides config.cc' '
305 git config --replace-all format.cc \
306 "C E Cipient <rcipient@example.com>" &&
307 git format-patch --no-cc --stdout main..side >patch12 &&
308 sed -e "/^\$/q" patch12 >hdrs12 &&
309 check_patch hdrs12 &&
310 ! grep "^Cc: C E Cipient <rcipient@example.com>\$" hdrs12
311 '
312
313 test_expect_success '--no-add-header overrides config.headers' '
314 git config --replace-all format.headers \
315 "Header1: B E Cipient <rcipient@example.com>" &&
316 git format-patch --no-add-header --stdout main..side >patch13 &&
317 sed -e "/^\$/q" patch13 >hdrs13 &&
318 check_patch hdrs13 &&
319 ! grep "^Header1: B E Cipient <rcipient@example.com>\$" hdrs13
320 '
321
322 test_expect_success 'multiple files' '
323 rm -rf patches/ &&
324 git checkout side &&
325 git format-patch -o patches/ main &&
326 ls patches/0001-Side-changes-1.patch patches/0002-Side-changes-2.patch patches/0003-Side-changes-3-with-n-backslash-n-in-it.patch
327 '
328
329 test_expect_success 'filename length limit' '
330 test_when_finished "rm -f 000*" &&
331 rm -rf 000[1-9]-*.patch &&
332 for len in 15 25 35
333 do
334 git format-patch --filename-max-length=$len -3 side &&
335 max=$(
336 for patch in 000[1-9]-*.patch
337 do
338 echo "$patch" | wc -c || exit 1
339 done |
340 sort -nr |
341 head -n 1
342 ) &&
343 test $max -le $len || return 1
344 done
345 '
346
347 test_expect_success 'filename length limit from config' '
348 test_when_finished "rm -f 000*" &&
349 rm -rf 000[1-9]-*.patch &&
350 for len in 15 25 35
351 do
352 git -c format.filenameMaxLength=$len format-patch -3 side &&
353 max=$(
354 for patch in 000[1-9]-*.patch
355 do
356 echo "$patch" | wc -c || exit 1
357 done |
358 sort -nr |
359 head -n 1
360 ) &&
361 test $max -le $len || return 1
362 done
363 '
364
365 test_expect_success 'filename limit applies only to basename' '
366 test_when_finished "rm -rf patches/" &&
367 rm -rf patches/ &&
368 for len in 15 25 35
369 do
370 git format-patch -o patches --filename-max-length=$len -3 side &&
371 max=$(
372 for patch in patches/000[1-9]-*.patch
373 do
374 echo "${patch#patches/}" | wc -c || exit 1
375 done |
376 sort -nr |
377 head -n 1
378 ) &&
379 test $max -le $len || return 1
380 done
381 '
382
383 test_expect_success 'reroll count' '
384 rm -fr patches &&
385 git format-patch -o patches --cover-letter --reroll-count 4 main..side >list &&
386 ! grep -v "^patches/v4-000[0-3]-" list &&
387 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
388 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
389 '
390
391 test_expect_success 'reroll count (-v)' '
392 rm -fr patches &&
393 git format-patch -o patches --cover-letter -v4 main..side >list &&
394 ! grep -v "^patches/v4-000[0-3]-" list &&
395 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
396 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
397 '
398
399 test_expect_success 'reroll count (-v) with a fractional number' '
400 rm -fr patches &&
401 git format-patch -o patches --cover-letter -v4.4 main..side >list &&
402 ! grep -v "^patches/v4.4-000[0-3]-" list &&
403 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
404 ! grep -v "^Subject: \[PATCH v4.4 [0-3]/3\] " subjects
405 '
406
407 test_expect_success 'reroll (-v) count with a non number' '
408 rm -fr patches &&
409 git format-patch -o patches --cover-letter -v4rev2 main..side >list &&
410 ! grep -v "^patches/v4rev2-000[0-3]-" list &&
411 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
412 ! grep -v "^Subject: \[PATCH v4rev2 [0-3]/3\] " subjects
413 '
414
415 test_expect_success 'reroll (-v) count with a non-pathname character' '
416 rm -fr patches &&
417 git format-patch -o patches --cover-letter -v4---..././../--1/.2// main..side >list &&
418 ! grep -v "patches/v4-\.-\.-\.-1-\.2-000[0-3]-" list &&
419 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
420 ! grep -v "^Subject: \[PATCH v4---\.\.\./\./\.\./--1/\.2// [0-3]/3\] " subjects
421 '
422
423 check_threading () {
424 expect="$1" &&
425 shift &&
426 git format-patch --stdout "$@" >patch &&
427 # Prints everything between the Message-ID and In-Reply-To,
428 # and replaces all Message-ID-lookalikes by a sequence number
429 perl -ne '
430 if (/^(message-id|references|in-reply-to)/i) {
431 $printing = 1;
432 } elsif (/^\S/) {
433 $printing = 0;
434 }
435 if ($printing) {
436 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
437 for $k (keys %h) {s/$k/$h{$k}/};
438 print;
439 }
440 print "---\n" if /^From /i;
441 ' <patch >actual &&
442 test_cmp "$expect" actual
443 }
444
445 cat >>expect.no-threading <<EOF
446 ---
447 ---
448 ---
449 EOF
450
451 test_expect_success 'no threading' '
452 git checkout side &&
453 check_threading expect.no-threading main
454 '
455
456 cat >expect.thread <<EOF
457 ---
458 Message-ID: <0>
459 ---
460 Message-ID: <1>
461 In-Reply-To: <0>
462 References: <0>
463 ---
464 Message-ID: <2>
465 In-Reply-To: <0>
466 References: <0>
467 EOF
468
469 test_expect_success 'thread' '
470 check_threading expect.thread --thread main
471 '
472
473 test_expect_success '--thread overrides format.thread=deep' '
474 test_config format.thread deep &&
475 check_threading expect.thread --thread main
476 '
477
478 cat >expect.in-reply-to <<EOF
479 ---
480 Message-ID: <0>
481 In-Reply-To: <1>
482 References: <1>
483 ---
484 Message-ID: <2>
485 In-Reply-To: <1>
486 References: <1>
487 ---
488 Message-ID: <3>
489 In-Reply-To: <1>
490 References: <1>
491 EOF
492
493 test_expect_success 'thread in-reply-to' '
494 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
495 --thread main
496 '
497
498 cat >expect.cover-letter <<EOF
499 ---
500 Message-ID: <0>
501 ---
502 Message-ID: <1>
503 In-Reply-To: <0>
504 References: <0>
505 ---
506 Message-ID: <2>
507 In-Reply-To: <0>
508 References: <0>
509 ---
510 Message-ID: <3>
511 In-Reply-To: <0>
512 References: <0>
513 EOF
514
515 test_expect_success 'thread cover-letter' '
516 check_threading expect.cover-letter --cover-letter --thread main
517 '
518
519 cat >expect.cl-irt <<EOF
520 ---
521 Message-ID: <0>
522 In-Reply-To: <1>
523 References: <1>
524 ---
525 Message-ID: <2>
526 In-Reply-To: <0>
527 References: <1>
528 <0>
529 ---
530 Message-ID: <3>
531 In-Reply-To: <0>
532 References: <1>
533 <0>
534 ---
535 Message-ID: <4>
536 In-Reply-To: <0>
537 References: <1>
538 <0>
539 EOF
540
541 test_expect_success 'thread cover-letter in-reply-to' '
542 check_threading expect.cl-irt --cover-letter \
543 --in-reply-to="<test.message>" --thread main
544 '
545
546 test_expect_success 'thread explicit shallow' '
547 check_threading expect.cl-irt --cover-letter \
548 --in-reply-to="<test.message>" --thread=shallow main
549 '
550
551 cat >expect.deep <<EOF
552 ---
553 Message-ID: <0>
554 ---
555 Message-ID: <1>
556 In-Reply-To: <0>
557 References: <0>
558 ---
559 Message-ID: <2>
560 In-Reply-To: <1>
561 References: <0>
562 <1>
563 EOF
564
565 test_expect_success 'thread deep' '
566 check_threading expect.deep --thread=deep main
567 '
568
569 cat >expect.deep-irt <<EOF
570 ---
571 Message-ID: <0>
572 In-Reply-To: <1>
573 References: <1>
574 ---
575 Message-ID: <2>
576 In-Reply-To: <0>
577 References: <1>
578 <0>
579 ---
580 Message-ID: <3>
581 In-Reply-To: <2>
582 References: <1>
583 <0>
584 <2>
585 EOF
586
587 test_expect_success 'thread deep in-reply-to' '
588 check_threading expect.deep-irt --thread=deep \
589 --in-reply-to="<test.message>" main
590 '
591
592 cat >expect.deep-cl <<EOF
593 ---
594 Message-ID: <0>
595 ---
596 Message-ID: <1>
597 In-Reply-To: <0>
598 References: <0>
599 ---
600 Message-ID: <2>
601 In-Reply-To: <1>
602 References: <0>
603 <1>
604 ---
605 Message-ID: <3>
606 In-Reply-To: <2>
607 References: <0>
608 <1>
609 <2>
610 EOF
611
612 test_expect_success 'thread deep cover-letter' '
613 check_threading expect.deep-cl --cover-letter --thread=deep main
614 '
615
616 cat >expect.deep-cl-irt <<EOF
617 ---
618 Message-ID: <0>
619 In-Reply-To: <1>
620 References: <1>
621 ---
622 Message-ID: <2>
623 In-Reply-To: <0>
624 References: <1>
625 <0>
626 ---
627 Message-ID: <3>
628 In-Reply-To: <2>
629 References: <1>
630 <0>
631 <2>
632 ---
633 Message-ID: <4>
634 In-Reply-To: <3>
635 References: <1>
636 <0>
637 <2>
638 <3>
639 EOF
640
641 test_expect_success 'thread deep cover-letter in-reply-to' '
642 check_threading expect.deep-cl-irt --cover-letter \
643 --in-reply-to="<test.message>" --thread=deep main
644 '
645
646 test_expect_success 'thread via config' '
647 test_config format.thread true &&
648 check_threading expect.thread main
649 '
650
651 test_expect_success 'thread deep via config' '
652 test_config format.thread deep &&
653 check_threading expect.deep main
654 '
655
656 test_expect_success 'thread config + override' '
657 test_config format.thread deep &&
658 check_threading expect.thread --thread main
659 '
660
661 test_expect_success 'thread config + --no-thread' '
662 test_config format.thread deep &&
663 check_threading expect.no-threading --no-thread main
664 '
665
666 test_expect_success 'excessive subject' '
667 rm -rf patches/ &&
668 git checkout side &&
669 before=$(git hash-object file) &&
670 before=$(git rev-parse --short $before) &&
671 test_write_lines 5 6 1 2 3 A 4 B C 7 8 9 10 D E F >>file &&
672 after=$(git hash-object file) &&
673 after=$(git rev-parse --short $after) &&
674 git update-index file &&
675 git commit -m "This is an excessively long subject line for a message due to the habit some projects have of not having a short, one-line subject at the start of the commit message, but rather sticking a whole paragraph right at the start as the only thing in the commit message. It had better not become the filename for the patch." &&
676 git format-patch -o patches/ main..side &&
677 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
678 '
679
680 test_expect_success 'failure to write cover-letter aborts gracefully' '
681 test_when_finished "rmdir 0000-cover-letter.patch" &&
682 mkdir 0000-cover-letter.patch &&
683 test_must_fail git format-patch --no-renames --cover-letter -1
684 '
685
686 test_expect_success 'cover-letter inherits diff options' '
687 git mv file foo &&
688 git commit -m foo &&
689 git format-patch --no-renames --cover-letter -1 &&
690 check_patch 0000-cover-letter.patch &&
691 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
692 git format-patch --cover-letter -1 -M &&
693 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
694 '
695
696 cat >expect <<EOF
697 This is an excessively long subject line for a message due to the
698 habit some projects have of not having a short, one-line subject at
699 the start of the commit message, but rather sticking a whole
700 paragraph right at the start as the only thing in the commit
701 message. It had better not become the filename for the patch.
702 foo
703
704 EOF
705
706 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
707 git format-patch --cover-letter -2 &&
708 sed -e "1,/A U Thor/d" -e "/^\$/q" 0000-cover-letter.patch >output &&
709 test_cmp expect output
710 '
711
712 cat >expect <<EOF
713 index $before..$after 100644
714 --- a/file
715 +++ b/file
716 @@ -13,4 +13,20 @@ C
717 10
718 D
719 E
720 F
721 +5
722 EOF
723
724 test_expect_success 'format-patch respects -U' '
725 git format-patch -U4 -2 &&
726 sed -e "1,/^diff/d" -e "/^+5/q" \
727 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
728 >output &&
729 test_cmp expect output
730 '
731
732 cat >expect <<EOF
733
734 diff --git a/file b/file
735 index $before..$after 100644
736 --- a/file
737 +++ b/file
738 @@ -14,3 +14,19 @@ C
739 D
740 E
741 F
742 +5
743 EOF
744
745 test_expect_success 'format-patch -p suppresses stat' '
746 git format-patch -p -2 &&
747 sed -e "1,/^\$/d" -e "/^+5/q" 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&
748 test_cmp expect output
749 '
750
751 test_expect_success 'format-patch from a subdirectory (1)' '
752 filename=$(
753 rm -rf sub &&
754 mkdir -p sub/dir &&
755 cd sub/dir &&
756 git format-patch -1
757 ) &&
758 case "$filename" in
759 0*)
760 ;; # ok
761 *)
762 echo "Oops? $filename"
763 false
764 ;;
765 esac &&
766 test -f "$filename"
767 '
768
769 test_expect_success 'format-patch from a subdirectory (2)' '
770 filename=$(
771 rm -rf sub &&
772 mkdir -p sub/dir &&
773 cd sub/dir &&
774 git format-patch -1 -o ..
775 ) &&
776 case "$filename" in
777 ../0*)
778 ;; # ok
779 *)
780 echo "Oops? $filename"
781 false
782 ;;
783 esac &&
784 basename=$(expr "$filename" : ".*/\(.*\)") &&
785 test -f "sub/$basename"
786 '
787
788 test_expect_success 'format-patch from a subdirectory (3)' '
789 rm -f 0* &&
790 filename=$(
791 rm -rf sub &&
792 mkdir -p sub/dir &&
793 cd sub/dir &&
794 git format-patch -1 -o "$TRASH_DIRECTORY"
795 ) &&
796 basename=$(expr "$filename" : ".*/\(.*\)") &&
797 test -f "$basename"
798 '
799
800 test_expect_success 'format-patch --in-reply-to' '
801 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" >patch8 &&
802 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
803 grep "^References: <baz@foo.bar>" patch8
804 '
805
806 test_expect_success 'format-patch --signoff' '
807 git format-patch -1 --signoff --stdout >out &&
808 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
809 '
810
811 test_expect_success 'format-patch --notes --signoff' '
812 git notes --ref test add -m "test message" HEAD &&
813 git format-patch -1 --signoff --stdout --notes=test >out &&
814 # Three dashes must come after S-o-b
815 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
816 sed "1,/^Signed-off-by: /d" out | grep "test message" &&
817 # Notes message must come after three dashes
818 ! sed "/^---$/q" out | grep "test message" &&
819 sed "1,/^---$/d" out | grep "test message"
820 '
821
822 test_expect_success 'format-patch notes output control' '
823 git notes add -m "notes config message" HEAD &&
824 test_when_finished git notes remove HEAD &&
825
826 git format-patch -1 --stdout >out &&
827 ! grep "notes config message" out &&
828 git format-patch -1 --stdout --notes >out &&
829 grep "notes config message" out &&
830 git format-patch -1 --stdout --no-notes >out &&
831 ! grep "notes config message" out &&
832 git format-patch -1 --stdout --notes --no-notes >out &&
833 ! grep "notes config message" out &&
834 git format-patch -1 --stdout --no-notes --notes >out &&
835 grep "notes config message" out &&
836
837 test_config format.notes true &&
838 git format-patch -1 --stdout >out &&
839 grep "notes config message" out &&
840 git format-patch -1 --stdout --notes >out &&
841 grep "notes config message" out &&
842 git format-patch -1 --stdout --no-notes >out &&
843 ! grep "notes config message" out &&
844 git format-patch -1 --stdout --notes --no-notes >out &&
845 ! grep "notes config message" out &&
846 git format-patch -1 --stdout --no-notes --notes >out &&
847 grep "notes config message" out
848 '
849
850 test_expect_success 'format-patch with multiple notes refs' '
851 git notes --ref note1 add -m "this is note 1" HEAD &&
852 test_when_finished git notes --ref note1 remove HEAD &&
853 git notes --ref note2 add -m "this is note 2" HEAD &&
854 test_when_finished git notes --ref note2 remove HEAD &&
855
856 git format-patch -1 --stdout >out &&
857 ! grep "this is note 1" out &&
858 ! grep "this is note 2" out &&
859 git format-patch -1 --stdout --notes=note1 >out &&
860 grep "this is note 1" out &&
861 ! grep "this is note 2" out &&
862 git format-patch -1 --stdout --notes=note2 >out &&
863 ! grep "this is note 1" out &&
864 grep "this is note 2" out &&
865 git format-patch -1 --stdout --notes=note1 --notes=note2 >out &&
866 grep "this is note 1" out &&
867 grep "this is note 2" out &&
868
869 test_config format.notes note1 &&
870 git format-patch -1 --stdout >out &&
871 grep "this is note 1" out &&
872 ! grep "this is note 2" out &&
873 git format-patch -1 --stdout --no-notes >out &&
874 ! grep "this is note 1" out &&
875 ! grep "this is note 2" out &&
876 git format-patch -1 --stdout --notes=note2 >out &&
877 grep "this is note 1" out &&
878 grep "this is note 2" out &&
879 git format-patch -1 --stdout --no-notes --notes=note2 >out &&
880 ! grep "this is note 1" out &&
881 grep "this is note 2" out &&
882
883 git config --add format.notes note2 &&
884 git format-patch -1 --stdout >out &&
885 grep "this is note 1" out &&
886 grep "this is note 2" out &&
887 git format-patch -1 --stdout --no-notes >out &&
888 ! grep "this is note 1" out &&
889 ! grep "this is note 2" out
890 '
891
892 test_expect_success 'format-patch with multiple notes refs in config' '
893 test_when_finished "test_unconfig format.notes" &&
894
895 git notes --ref note1 add -m "this is note 1" HEAD &&
896 test_when_finished git notes --ref note1 remove HEAD &&
897 git notes --ref note2 add -m "this is note 2" HEAD &&
898 test_when_finished git notes --ref note2 remove HEAD &&
899
900 git config format.notes note1 &&
901 git format-patch -1 --stdout >out &&
902 grep "this is note 1" out &&
903 ! grep "this is note 2" out &&
904 git config format.notes note2 &&
905 git format-patch -1 --stdout >out &&
906 ! grep "this is note 1" out &&
907 grep "this is note 2" out &&
908 git config --add format.notes note1 &&
909 git format-patch -1 --stdout >out &&
910 grep "this is note 1" out &&
911 grep "this is note 2" out &&
912
913 git config --replace-all format.notes note1 &&
914 git config --add format.notes false &&
915 git format-patch -1 --stdout >out &&
916 ! grep "this is note 1" out &&
917 ! grep "this is note 2" out &&
918 git config --add format.notes note2 &&
919 git format-patch -1 --stdout >out &&
920 ! grep "this is note 1" out &&
921 grep "this is note 2" out
922 '
923
924 echo "fatal: --name-only does not make sense" >expect.name-only
925 echo "fatal: --name-status does not make sense" >expect.name-status
926 echo "fatal: --check does not make sense" >expect.check
927
928 test_expect_success 'options no longer allowed for format-patch' '
929 test_must_fail git format-patch --name-only 2>output &&
930 test_cmp expect.name-only output &&
931 test_must_fail git format-patch --name-status 2>output &&
932 test_cmp expect.name-status output &&
933 test_must_fail git format-patch --check 2>output &&
934 test_cmp expect.check output
935 '
936
937 test_expect_success 'format-patch --numstat should produce a patch' '
938 git format-patch --numstat --stdout main..side >output &&
939 grep "^diff --git a/" output >diff &&
940 test_line_count = 5 diff
941 '
942
943 test_expect_success 'format-patch -- <path>' '
944 rm -f *.patch &&
945 git checkout -b pathspec main &&
946
947 echo file_a 1 >file_a &&
948 echo file_b 1 >file_b &&
949 git add file_a file_b &&
950 git commit -m pathspec_initial &&
951
952 echo file_a 2 >>file_a &&
953 git add file_a &&
954 git commit -m pathspec_a &&
955
956 echo file_b 2 >>file_b &&
957 git add file_b &&
958 git commit -m pathspec_b &&
959
960 echo file_a 3 >>file_a &&
961 echo file_b 3 >>file_b &&
962 git add file_a file_b &&
963 git commit -m pathspec_ab &&
964
965 cat >expect <<-\EOF &&
966 0001-pathspec_initial.patch
967 0002-pathspec_a.patch
968 0003-pathspec_ab.patch
969 EOF
970
971 git format-patch main..pathspec -- file_a >output &&
972 test_cmp expect output &&
973 ! grep file_b *.patch
974 '
975
976 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
977 git checkout side &&
978 git format-patch --ignore-if-in-upstream HEAD
979 '
980
981 test_expect_success 'get git version' '
982 git_version=$(git --version) &&
983 git_version=${git_version##* }
984 '
985
986 signature() {
987 printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
988 }
989
990 test_expect_success 'format-patch default signature' '
991 git format-patch --stdout -1 >patch &&
992 tail -n 3 patch >output &&
993 signature >expect &&
994 test_cmp expect output
995 '
996
997 test_expect_success 'format-patch --signature' '
998 git format-patch --stdout --signature="my sig" -1 >patch &&
999 tail -n 3 patch >output &&
1000 signature "my sig" >expect &&
1001 test_cmp expect output
1002 '
1003
1004 test_expect_success 'format-patch with format.signature config' '
1005 git config format.signature "config sig" &&
1006 git format-patch --stdout -1 >output &&
1007 grep "config sig" output
1008 '
1009
1010 test_expect_success 'format-patch --signature overrides format.signature' '
1011 git config format.signature "config sig" &&
1012 git format-patch --stdout --signature="overrides" -1 >output &&
1013 ! grep "config sig" output &&
1014 grep "overrides" output
1015 '
1016
1017 test_expect_success 'format-patch --no-signature ignores format.signature' '
1018 git config format.signature "config sig" &&
1019 git format-patch --stdout --signature="my sig" --no-signature \
1020 -1 >output &&
1021 check_patch output &&
1022 ! grep "config sig" output &&
1023 ! grep "my sig" output &&
1024 ! grep "^-- \$" output
1025 '
1026
1027 test_expect_success 'format-patch --signature --cover-letter' '
1028 git config --unset-all format.signature &&
1029 git format-patch --stdout --signature="my sig" --cover-letter \
1030 -1 >output &&
1031 grep "my sig" output >sig &&
1032 test_line_count = 2 sig
1033 '
1034
1035 test_expect_success 'format.signature="" suppresses signatures' '
1036 git config format.signature "" &&
1037 git format-patch --stdout -1 >output &&
1038 check_patch output &&
1039 ! grep "^-- \$" output
1040 '
1041
1042 test_expect_success 'format-patch --no-signature suppresses signatures' '
1043 git config --unset-all format.signature &&
1044 git format-patch --stdout --no-signature -1 >output &&
1045 check_patch output &&
1046 ! grep "^-- \$" output
1047 '
1048
1049 test_expect_success 'format-patch --signature="" suppresses signatures' '
1050 git format-patch --stdout --signature="" -1 >output &&
1051 check_patch output &&
1052 ! grep "^-- \$" output
1053 '
1054
1055 test_expect_success 'prepare mail-signature input' '
1056 cat >mail-signature <<-\EOF
1057
1058 Test User <test.email@kernel.org>
1059 http://git.kernel.org/cgit/git/git.git
1060
1061 git.kernel.org/?p=git/git.git;a=summary
1062
1063 EOF
1064 '
1065
1066 test_expect_success '--signature-file=file works' '
1067 git format-patch --stdout --signature-file=mail-signature -1 >output &&
1068 check_patch output &&
1069 sed -e "1,/^-- \$/d" output >actual &&
1070 {
1071 cat mail-signature && echo
1072 } >expect &&
1073 test_cmp expect actual
1074 '
1075
1076 test_expect_success 'format.signaturefile works' '
1077 test_config format.signaturefile mail-signature &&
1078 git format-patch --stdout -1 >output &&
1079 check_patch output &&
1080 sed -e "1,/^-- \$/d" output >actual &&
1081 {
1082 cat mail-signature && echo
1083 } >expect &&
1084 test_cmp expect actual
1085 '
1086
1087 test_expect_success '--no-signature suppresses format.signaturefile ' '
1088 test_config format.signaturefile mail-signature &&
1089 git format-patch --stdout --no-signature -1 >output &&
1090 check_patch output &&
1091 ! grep "^-- \$" output
1092 '
1093
1094 test_expect_success '--signature-file overrides format.signaturefile' '
1095 cat >other-mail-signature <<-\EOF &&
1096 Use this other signature instead of mail-signature.
1097 EOF
1098 test_config format.signaturefile mail-signature &&
1099 git format-patch --stdout \
1100 --signature-file=other-mail-signature -1 >output &&
1101 check_patch output &&
1102 sed -e "1,/^-- \$/d" output >actual &&
1103 {
1104 cat other-mail-signature && echo
1105 } >expect &&
1106 test_cmp expect actual
1107 '
1108
1109 test_expect_success '--signature overrides format.signaturefile' '
1110 test_config format.signaturefile mail-signature &&
1111 git format-patch --stdout --signature="my sig" -1 >output &&
1112 check_patch output &&
1113 grep "my sig" output
1114 '
1115
1116 test_expect_success TTY 'format-patch --stdout paginates' '
1117 rm -f pager_used &&
1118 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
1119 test_path_is_file pager_used
1120 '
1121
1122 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
1123 rm -f pager_used &&
1124 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
1125 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
1126 test_path_is_missing pager_used &&
1127 test_path_is_missing .git/pager_used
1128 '
1129
1130 test_expect_success 'format-patch handles multi-line subjects' '
1131 rm -rf patches/ &&
1132 echo content >>file &&
1133 test_write_lines one two three >msg &&
1134 git add file &&
1135 git commit -F msg &&
1136 git format-patch -o patches -1 &&
1137 grep ^Subject: patches/0001-one.patch >actual &&
1138 echo "Subject: [PATCH] one two three" >expect &&
1139 test_cmp expect actual
1140 '
1141
1142 test_expect_success 'format-patch handles multi-line encoded subjects' '
1143 rm -rf patches/ &&
1144 echo content >>file &&
1145 test_write_lines en två tre >msg &&
1146 git add file &&
1147 git commit -F msg &&
1148 git format-patch -o patches -1 &&
1149 grep ^Subject: patches/0001-en.patch >actual &&
1150 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
1151 test_cmp expect actual
1152 '
1153
1154 M8="foo bar "
1155 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1156 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1157 cat >expect <<'EOF'
1158 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1159 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1160 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1161 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1162 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1163 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1164 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1165 EOF
1166 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
1167 echo content >>file &&
1168 git add file &&
1169 git commit -m "$M512" &&
1170 git format-patch --stdout -1 >patch &&
1171 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1172 test_cmp expect subject
1173 '
1174
1175 M8="föö bar "
1176 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1177 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1178 cat >expect <<'EOF'
1179 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1180 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1181 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1182 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1183 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1184 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1185 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1186 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1187 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1188 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1189 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1190 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1191 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1192 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1193 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1194 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1195 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1196 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1197 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1198 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1199 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1200 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1201 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1202 =?UTF-8?q?bar?=
1203 EOF
1204 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
1205 rm -rf patches/ &&
1206 echo content >>file &&
1207 git add file &&
1208 git commit -m "$M512" &&
1209 git format-patch --stdout -1 >patch &&
1210 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1211 test_cmp expect subject
1212 '
1213
1214 check_author() {
1215 echo content >>file &&
1216 git add file &&
1217 GIT_AUTHOR_NAME=$1 git commit -m author-check &&
1218 git format-patch --stdout -1 >patch &&
1219 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1220 test_cmp expect actual
1221 }
1222
1223 cat >expect <<'EOF'
1224 From: "Foo B. Bar" <author@example.com>
1225 EOF
1226 test_expect_success 'format-patch quotes dot in from-headers' '
1227 check_author "Foo B. Bar"
1228 '
1229
1230 cat >expect <<'EOF'
1231 From: "Foo \"The Baz\" Bar" <author@example.com>
1232 EOF
1233 test_expect_success 'format-patch quotes double-quote in from-headers' '
1234 check_author "Foo \"The Baz\" Bar"
1235 '
1236
1237 cat >expect <<'EOF'
1238 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1239 EOF
1240 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1241 check_author "Föo Bar"
1242 '
1243
1244 cat >expect <<'EOF'
1245 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1246 EOF
1247 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1248 check_author "Föo B. Bar"
1249 '
1250
1251 cat >expect <<EOF
1252 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1253 <author@example.com>
1254 EOF
1255 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1256 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1257 '
1258
1259 cat >expect <<'EOF'
1260 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1261 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1262 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1263 EOF
1264 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1265 check_author "Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
1266 '
1267
1268 cat >expect <<'EOF'
1269 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1270 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1271 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1272 EOF
1273 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1274 check_author "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
1275 '
1276
1277 cat >expect <<'EOF'
1278 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1279 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1280 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1281 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1282 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1283 EOF
1284 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1285 check_author "Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
1286 '
1287
1288 cat >expect <<'EOF'
1289 From: Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1290 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1291 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1292 EOF
1293 test_expect_success 'format-patch wraps extremely long from-header (non-ASCII without Q-encoding)' '
1294 echo content >>file &&
1295 git add file &&
1296 GIT_AUTHOR_NAME="Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar" \
1297 git commit -m author-check &&
1298 git format-patch --no-encode-email-headers --stdout -1 >patch &&
1299 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1300 test_cmp expect actual
1301 '
1302
1303 cat >expect <<'EOF'
1304 Subject: [PATCH] Foö
1305 EOF
1306 test_expect_success 'subject lines are unencoded with --no-encode-email-headers' '
1307 echo content >>file &&
1308 git add file &&
1309 git commit -m "Foö" &&
1310 git format-patch --no-encode-email-headers -1 --stdout >patch &&
1311 grep ^Subject: patch >actual &&
1312 test_cmp expect actual
1313 '
1314
1315 cat >expect <<'EOF'
1316 Subject: [PATCH] Foö
1317 EOF
1318 test_expect_success 'subject lines are unencoded with format.encodeEmailHeaders=false' '
1319 echo content >>file &&
1320 git add file &&
1321 git commit -m "Foö" &&
1322 git config format.encodeEmailHeaders false &&
1323 git format-patch -1 --stdout >patch &&
1324 grep ^Subject: patch >actual &&
1325 test_cmp expect actual
1326 '
1327
1328 cat >expect <<'EOF'
1329 Subject: [PATCH] =?UTF-8?q?Fo=C3=B6?=
1330 EOF
1331 test_expect_success '--encode-email-headers overrides format.encodeEmailHeaders' '
1332 echo content >>file &&
1333 git add file &&
1334 git commit -m "Foö" &&
1335 git config format.encodeEmailHeaders false &&
1336 git format-patch --encode-email-headers -1 --stdout >patch &&
1337 grep ^Subject: patch >actual &&
1338 test_cmp expect actual
1339 '
1340
1341 cat >expect <<'EOF'
1342 Subject: header with . in it
1343 EOF
1344 test_expect_success 'subject lines do not have 822 atom-quoting' '
1345 echo content >>file &&
1346 git add file &&
1347 git commit -m "header with . in it" &&
1348 git format-patch -k -1 --stdout >patch &&
1349 grep ^Subject: patch >actual &&
1350 test_cmp expect actual
1351 '
1352
1353 cat >expect <<'EOF'
1354 Subject: [PREFIX 1/1] header with . in it
1355 EOF
1356 test_expect_success 'subject prefixes have space prepended' '
1357 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1358 grep ^Subject: patch >actual &&
1359 test_cmp expect actual
1360 '
1361
1362 cat >expect <<'EOF'
1363 Subject: [1/1] header with . in it
1364 EOF
1365 test_expect_success 'empty subject prefix does not have extra space' '
1366 git format-patch -n -1 --stdout --subject-prefix= >patch &&
1367 grep ^Subject: patch >actual &&
1368 test_cmp expect actual
1369 '
1370
1371 test_expect_success '--rfc and --no-rfc' '
1372 cat >expect <<-\EOF &&
1373 Subject: [RFC PATCH 1/1] header with . in it
1374 EOF
1375 git format-patch -n -1 --stdout --rfc >patch &&
1376 grep "^Subject:" patch >actual &&
1377 test_cmp expect actual &&
1378 git format-patch -n -1 --stdout --rfc --no-rfc >patch &&
1379 sed -e "s/RFC //" expect >expect-raw &&
1380 grep "^Subject:" patch >actual &&
1381 test_cmp expect-raw actual
1382 '
1383
1384 test_expect_success '--rfc=WIP and --rfc=' '
1385 cat >expect <<-\EOF &&
1386 Subject: [WIP PATCH 1/1] header with . in it
1387 EOF
1388 git format-patch -n -1 --stdout --rfc=WIP >patch &&
1389 grep "^Subject:" patch >actual &&
1390 test_cmp expect actual &&
1391 git format-patch -n -1 --stdout --rfc --rfc= >patch &&
1392 sed -e "s/WIP //" expect >expect-raw &&
1393 grep "^Subject:" patch >actual &&
1394 test_cmp expect-raw actual
1395 '
1396
1397 test_expect_success '--rfc=-(WIP) appends' '
1398 cat >expect <<-\EOF &&
1399 Subject: [PATCH (WIP) 1/1] header with . in it
1400 EOF
1401 git format-patch -n -1 --stdout --rfc="-(WIP)" >patch &&
1402 grep "^Subject:" patch >actual &&
1403 test_cmp expect actual
1404 '
1405
1406 test_expect_success '--rfc does not overwrite prefix' '
1407 cat >expect <<-\EOF &&
1408 Subject: [RFC PATCH foobar 1/1] header with . in it
1409 EOF
1410 git -c format.subjectPrefix="PATCH foobar" \
1411 format-patch -n -1 --stdout --rfc >patch &&
1412 grep "^Subject:" patch >actual &&
1413 test_cmp expect actual
1414 '
1415
1416 test_expect_success '--rfc is argument order independent' '
1417 cat >expect <<-\EOF &&
1418 Subject: [RFC PATCH foobar 1/1] header with . in it
1419 EOF
1420 git format-patch -n -1 --stdout --rfc \
1421 --subject-prefix="PATCH foobar" >patch &&
1422 grep "^Subject:" patch >actual &&
1423 test_cmp expect actual
1424 '
1425
1426 test_expect_success '--from=ident notices bogus ident' '
1427 test_must_fail git format-patch -1 --stdout --from=foo >patch
1428 '
1429
1430 test_expect_success '--from=ident replaces author' '
1431 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1432 cat >expect <<-\EOF &&
1433 From: Me <me@example.com>
1434
1435 From: A U Thor <author@example.com>
1436
1437 EOF
1438 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1439 test_cmp expect patch.head
1440 '
1441
1442 test_expect_success '--from uses committer ident' '
1443 git format-patch -1 --stdout --from >patch &&
1444 cat >expect <<-\EOF &&
1445 From: C O Mitter <committer@example.com>
1446
1447 From: A U Thor <author@example.com>
1448
1449 EOF
1450 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1451 test_cmp expect patch.head
1452 '
1453
1454 test_expect_success '--from omits redundant in-body header' '
1455 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1456 cat >expect <<-\EOF &&
1457 From: A U Thor <author@example.com>
1458
1459 EOF
1460 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1461 test_cmp expect patch.head
1462 '
1463
1464 test_expect_success 'with --force-in-body-from, redundant in-body from is kept' '
1465 git format-patch --force-in-body-from \
1466 -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1467 cat >expect <<-\EOF &&
1468 From: A U Thor <author@example.com>
1469
1470 From: A U Thor <author@example.com>
1471
1472 EOF
1473 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1474 test_cmp expect patch.head
1475 '
1476
1477 test_expect_success 'format.forceInBodyFrom, equivalent to --force-in-body-from' '
1478 git -c format.forceInBodyFrom=yes format-patch \
1479 -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1480 cat >expect <<-\EOF &&
1481 From: A U Thor <author@example.com>
1482
1483 From: A U Thor <author@example.com>
1484
1485 EOF
1486 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1487 test_cmp expect patch.head
1488 '
1489
1490 test_expect_success 'format.forceInBodyFrom, equivalent to --force-in-body-from' '
1491 git -c format.forceInBodyFrom=yes format-patch --no-force-in-body-from \
1492 -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1493 cat >expect <<-\EOF &&
1494 From: A U Thor <author@example.com>
1495
1496 EOF
1497 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1498 test_cmp expect patch.head
1499 '
1500
1501 test_expect_success 'in-body headers trigger content encoding' '
1502 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1503 test_when_finished "git reset --hard HEAD^" &&
1504 git format-patch -1 --stdout --from >patch &&
1505 cat >expect <<-\EOF &&
1506 From: C O Mitter <committer@example.com>
1507 Content-Type: text/plain; charset=UTF-8
1508
1509 From: éxötìc <author@example.com>
1510
1511 EOF
1512 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" patch >patch.head &&
1513 test_cmp expect patch.head
1514 '
1515
1516 append_signoff()
1517 {
1518 C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1519 git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1520 sed -n -e "1,/^---$/p" append_signoff.patch |
1521 grep -E -n "^Subject|Sign|^$"
1522 }
1523
1524 test_expect_success 'signoff: commit with no body' '
1525 append_signoff </dev/null >actual &&
1526 cat <<-\EOF | sed "s/EOL$//" >expect &&
1527 4:Subject: [PATCH] EOL
1528 8:
1529 9:Signed-off-by: C O Mitter <committer@example.com>
1530 EOF
1531 test_cmp expect actual
1532 '
1533
1534 test_expect_success 'signoff: commit with only subject' '
1535 echo subject | append_signoff >actual &&
1536 cat >expect <<-\EOF &&
1537 4:Subject: [PATCH] subject
1538 8:
1539 9:Signed-off-by: C O Mitter <committer@example.com>
1540 EOF
1541 test_cmp expect actual
1542 '
1543
1544 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1545 printf subject | append_signoff >actual &&
1546 cat >expect <<-\EOF &&
1547 4:Subject: [PATCH] subject
1548 8:
1549 9:Signed-off-by: C O Mitter <committer@example.com>
1550 EOF
1551 test_cmp expect actual
1552 '
1553
1554 test_expect_success 'signoff: no existing signoffs' '
1555 append_signoff <<-\EOF >actual &&
1556 subject
1557
1558 body
1559 EOF
1560 cat >expect <<-\EOF &&
1561 4:Subject: [PATCH] subject
1562 8:
1563 10:
1564 11:Signed-off-by: C O Mitter <committer@example.com>
1565 EOF
1566 test_cmp expect actual
1567 '
1568
1569 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1570 printf "subject\n\nbody" | append_signoff >actual &&
1571 cat >expect <<-\EOF &&
1572 4:Subject: [PATCH] subject
1573 8:
1574 10:
1575 11:Signed-off-by: C O Mitter <committer@example.com>
1576 EOF
1577 test_cmp expect actual
1578 '
1579
1580 test_expect_success 'signoff: some random signoff' '
1581 append_signoff <<-\EOF >actual &&
1582 subject
1583
1584 body
1585
1586 Signed-off-by: my@house
1587 EOF
1588 cat >expect <<-\EOF &&
1589 4:Subject: [PATCH] subject
1590 8:
1591 10:
1592 11:Signed-off-by: my@house
1593 12:Signed-off-by: C O Mitter <committer@example.com>
1594 EOF
1595 test_cmp expect actual
1596 '
1597
1598 test_expect_success 'signoff: misc conforming footer elements' '
1599 append_signoff <<-\EOF >actual &&
1600 subject
1601
1602 body
1603
1604 Signed-off-by: my@house
1605 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1606 Tested-by: Some One <someone@example.com>
1607 Bug: 1234
1608 EOF
1609 cat >expect <<-\EOF &&
1610 4:Subject: [PATCH] subject
1611 8:
1612 10:
1613 11:Signed-off-by: my@house
1614 15:Signed-off-by: C O Mitter <committer@example.com>
1615 EOF
1616 test_cmp expect actual
1617 '
1618
1619 test_expect_success 'signoff: some random signoff-alike' '
1620 append_signoff <<-\EOF >actual &&
1621 subject
1622
1623 body
1624 Fooled-by-me: my@house
1625 EOF
1626 cat >expect <<-\EOF &&
1627 4:Subject: [PATCH] subject
1628 8:
1629 11:
1630 12:Signed-off-by: C O Mitter <committer@example.com>
1631 EOF
1632 test_cmp expect actual
1633 '
1634
1635 test_expect_success 'signoff: not really a signoff' '
1636 append_signoff <<-\EOF >actual &&
1637 subject
1638
1639 I want to mention about Signed-off-by: here.
1640 EOF
1641 cat >expect <<-\EOF &&
1642 4:Subject: [PATCH] subject
1643 8:
1644 9:I want to mention about Signed-off-by: here.
1645 10:
1646 11:Signed-off-by: C O Mitter <committer@example.com>
1647 EOF
1648 test_cmp expect actual
1649 '
1650
1651 test_expect_success 'signoff: not really a signoff (2)' '
1652 append_signoff <<-\EOF >actual &&
1653 subject
1654
1655 My unfortunate
1656 Signed-off-by: example happens to be wrapped here.
1657 EOF
1658 cat >expect <<-\EOF &&
1659 4:Subject: [PATCH] subject
1660 8:
1661 10:Signed-off-by: example happens to be wrapped here.
1662 11:Signed-off-by: C O Mitter <committer@example.com>
1663 EOF
1664 test_cmp expect actual
1665 '
1666
1667 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1668 append_signoff <<-\EOF >actual &&
1669 subject
1670
1671 Signed-off-by: my@house
1672 Signed-off-by: your@house
1673
1674 A lot of houses.
1675 EOF
1676 cat >expect <<-\EOF &&
1677 4:Subject: [PATCH] subject
1678 8:
1679 9:Signed-off-by: my@house
1680 10:Signed-off-by: your@house
1681 11:
1682 13:
1683 14:Signed-off-by: C O Mitter <committer@example.com>
1684 EOF
1685 test_cmp expect actual
1686 '
1687
1688 test_expect_success 'signoff: the same signoff at the end' '
1689 append_signoff <<-\EOF >actual &&
1690 subject
1691
1692 body
1693
1694 Signed-off-by: C O Mitter <committer@example.com>
1695 EOF
1696 cat >expect <<-\EOF &&
1697 4:Subject: [PATCH] subject
1698 8:
1699 10:
1700 11:Signed-off-by: C O Mitter <committer@example.com>
1701 EOF
1702 test_cmp expect actual
1703 '
1704
1705 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1706 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1707 append_signoff >actual &&
1708 cat >expect <<-\EOF &&
1709 4:Subject: [PATCH] subject
1710 8:
1711 9:Signed-off-by: C O Mitter <committer@example.com>
1712 EOF
1713 test_cmp expect actual
1714 '
1715
1716 test_expect_success 'signoff: the same signoff NOT at the end' '
1717 append_signoff <<-\EOF >actual &&
1718 subject
1719
1720 body
1721
1722 Signed-off-by: C O Mitter <committer@example.com>
1723 Signed-off-by: my@house
1724 EOF
1725 cat >expect <<-\EOF &&
1726 4:Subject: [PATCH] subject
1727 8:
1728 10:
1729 11:Signed-off-by: C O Mitter <committer@example.com>
1730 12:Signed-off-by: my@house
1731 EOF
1732 test_cmp expect actual
1733 '
1734
1735 test_expect_success 'signoff: tolerate garbage in conforming footer' '
1736 append_signoff <<-\EOF >actual &&
1737 subject
1738
1739 body
1740
1741 Tested-by: my@house
1742 Some Trash
1743 Signed-off-by: C O Mitter <committer@example.com>
1744 EOF
1745 cat >expect <<-\EOF &&
1746 4:Subject: [PATCH] subject
1747 8:
1748 10:
1749 13:Signed-off-by: C O Mitter <committer@example.com>
1750 EOF
1751 test_cmp expect actual
1752 '
1753
1754 test_expect_success 'signoff: respect trailer config' '
1755 append_signoff <<-\EOF >actual &&
1756 subject
1757
1758 Myfooter: x
1759 Some Trash
1760 EOF
1761 cat >expect <<-\EOF &&
1762 4:Subject: [PATCH] subject
1763 8:
1764 11:
1765 12:Signed-off-by: C O Mitter <committer@example.com>
1766 EOF
1767 test_cmp expect actual &&
1768
1769 test_config trailer.Myfooter.ifexists add &&
1770 append_signoff <<-\EOF >actual &&
1771 subject
1772
1773 Myfooter: x
1774 Some Trash
1775 EOF
1776 cat >expect <<-\EOF &&
1777 4:Subject: [PATCH] subject
1778 8:
1779 11:Signed-off-by: C O Mitter <committer@example.com>
1780 EOF
1781 test_cmp expect actual
1782 '
1783
1784 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1785 append_signoff <<-\EOF >actual &&
1786 subject
1787
1788 body
1789
1790 Reviewed-id: Noone
1791 Tested-by: my@house
1792 Change-id: Ideadbeef
1793 Signed-off-by: C O Mitter <committer@example.com>
1794 Bug: 1234
1795 EOF
1796 cat >expect <<-\EOF &&
1797 4:Subject: [PATCH] subject
1798 8:
1799 10:
1800 14:Signed-off-by: C O Mitter <committer@example.com>
1801 EOF
1802 test_cmp expect actual
1803 '
1804
1805 test_expect_success 'format patch ignores color.ui' '
1806 test_unconfig color.ui &&
1807 git format-patch --stdout -1 >expect &&
1808 test_config color.ui always &&
1809 git format-patch --stdout -1 >actual &&
1810 test_cmp expect actual
1811 '
1812
1813 test_expect_success 'format patch respects diff.relative' '
1814 rm -rf subdir &&
1815 mkdir subdir &&
1816 echo other content >subdir/file2 &&
1817 git add subdir/file2 &&
1818 git commit -F msg &&
1819 test_unconfig diff.relative &&
1820 git format-patch --relative=subdir --stdout -1 >expect &&
1821 test_config diff.relative true &&
1822 git -C subdir format-patch --stdout -1 >actual &&
1823 test_cmp expect actual
1824 '
1825
1826 test_expect_success 'cover letter with invalid --cover-from-description and config' '
1827 test_config branch.rebuild-1.description "config subject
1828
1829 body" &&
1830 test_must_fail git format-patch --cover-letter --cover-from-description garbage main &&
1831 test_config format.coverFromDescription garbage &&
1832 test_must_fail git format-patch --cover-letter main
1833 '
1834
1835 test_expect_success 'cover letter with format.coverFromDescription = default' '
1836 test_config branch.rebuild-1.description "config subject
1837
1838 body" &&
1839 test_config format.coverFromDescription default &&
1840 git checkout rebuild-1 &&
1841 git format-patch --stdout --cover-letter main >actual &&
1842 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1843 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1844 grep "^config subject$" actual &&
1845 grep "^body$" actual
1846 '
1847
1848 test_expect_success 'cover letter with --cover-from-description default' '
1849 test_config branch.rebuild-1.description "config subject
1850
1851 body" &&
1852 git checkout rebuild-1 &&
1853 git format-patch --stdout --cover-letter --cover-from-description default main >actual &&
1854 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1855 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1856 grep "^config subject$" actual &&
1857 grep "^body$" actual
1858 '
1859
1860 test_expect_success 'cover letter with format.coverFromDescription = none' '
1861 test_config branch.rebuild-1.description "config subject
1862
1863 body" &&
1864 test_config format.coverFromDescription none &&
1865 git checkout rebuild-1 &&
1866 git format-patch --stdout --cover-letter main >actual &&
1867 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1868 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1869 ! grep "^config subject$" actual &&
1870 ! grep "^body$" actual
1871 '
1872
1873 test_expect_success 'cover letter with --cover-from-description none' '
1874 test_config branch.rebuild-1.description "config subject
1875
1876 body" &&
1877 git checkout rebuild-1 &&
1878 git format-patch --stdout --cover-letter --cover-from-description none main >actual &&
1879 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1880 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1881 ! grep "^config subject$" actual &&
1882 ! grep "^body$" actual
1883 '
1884
1885 test_expect_success 'cover letter with format.coverFromDescription = message' '
1886 test_config branch.rebuild-1.description "config subject
1887
1888 body" &&
1889 test_config format.coverFromDescription message &&
1890 git checkout rebuild-1 &&
1891 git format-patch --stdout --cover-letter main >actual &&
1892 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1893 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1894 grep "^config subject$" actual &&
1895 grep "^body$" actual
1896 '
1897
1898 test_expect_success 'cover letter with --cover-from-description message' '
1899 test_config branch.rebuild-1.description "config subject
1900
1901 body" &&
1902 git checkout rebuild-1 &&
1903 git format-patch --stdout --cover-letter --cover-from-description message main >actual &&
1904 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1905 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1906 grep "^config subject$" actual &&
1907 grep "^body$" actual
1908 '
1909
1910 test_expect_success 'cover letter with format.coverFromDescription = subject' '
1911 test_config branch.rebuild-1.description "config subject
1912
1913 body" &&
1914 test_config format.coverFromDescription subject &&
1915 git checkout rebuild-1 &&
1916 git format-patch --stdout --cover-letter main >actual &&
1917 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1918 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1919 ! grep "^config subject$" actual &&
1920 grep "^body$" actual
1921 '
1922
1923 test_expect_success 'cover letter with --cover-from-description subject' '
1924 test_config branch.rebuild-1.description "config subject
1925
1926 body" &&
1927 git checkout rebuild-1 &&
1928 git format-patch --stdout --cover-letter --cover-from-description subject main >actual &&
1929 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1930 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1931 ! grep "^config subject$" actual &&
1932 grep "^body$" actual
1933 '
1934
1935 test_expect_success 'cover letter with --cover-from-description subject (UTF-8 subject line)' '
1936 test_config branch.rebuild-1.description "Café?
1937
1938 body" &&
1939 git checkout rebuild-1 &&
1940 git format-patch --stdout --cover-letter --cover-from-description subject --encode-email-headers main >actual &&
1941 grep "^Subject: \[PATCH 0/2\] =?UTF-8?q?Caf=C3=A9=3F?=$" actual &&
1942 ! grep "Café" actual
1943 '
1944
1945 test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' '
1946 test_config branch.rebuild-1.description "config subject
1947
1948 body" &&
1949 test_config format.coverFromDescription auto &&
1950 git checkout rebuild-1 &&
1951 git format-patch --stdout --cover-letter main >actual &&
1952 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1953 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1954 ! grep "^config subject$" actual &&
1955 grep "^body$" actual
1956 '
1957
1958 test_expect_success 'cover letter with --cover-from-description auto (short subject line)' '
1959 test_config branch.rebuild-1.description "config subject
1960
1961 body" &&
1962 git checkout rebuild-1 &&
1963 git format-patch --stdout --cover-letter --cover-from-description auto main >actual &&
1964 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1965 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1966 ! grep "^config subject$" actual &&
1967 grep "^body$" actual
1968 '
1969
1970 test_expect_success 'cover letter with format.coverFromDescription = auto (long subject line)' '
1971 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
1972
1973 body" &&
1974 test_config format.coverFromDescription auto &&
1975 git checkout rebuild-1 &&
1976 git format-patch --stdout --cover-letter main >actual &&
1977 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1978 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1979 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1980 grep "^body$" actual
1981 '
1982
1983 test_expect_success 'cover letter with --cover-from-description auto (long subject line)' '
1984 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
1985
1986 body" &&
1987 git checkout rebuild-1 &&
1988 git format-patch --stdout --cover-letter --cover-from-description auto main >actual &&
1989 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1990 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1991 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1992 grep "^body$" actual
1993 '
1994
1995 test_expect_success 'cover letter with command-line --cover-from-description overrides config' '
1996 test_config branch.rebuild-1.description "config subject
1997
1998 body" &&
1999 test_config format.coverFromDescription none &&
2000 git checkout rebuild-1 &&
2001 git format-patch --stdout --cover-letter --cover-from-description subject main >actual &&
2002 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
2003 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
2004 ! grep "^config subject$" actual &&
2005 grep "^body$" actual
2006 '
2007
2008 test_expect_success 'cover letter using branch description (1)' '
2009 git checkout rebuild-1 &&
2010 test_config branch.rebuild-1.description hello &&
2011 git format-patch --stdout --cover-letter main >actual &&
2012 grep hello actual
2013 '
2014
2015 test_expect_success 'cover letter using branch description (2)' '
2016 git checkout rebuild-1 &&
2017 test_config branch.rebuild-1.description hello &&
2018 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
2019 grep hello actual
2020 '
2021
2022 test_expect_success 'cover letter using branch description (3)' '
2023 git checkout rebuild-1 &&
2024 test_config branch.rebuild-1.description hello &&
2025 git format-patch --stdout --cover-letter ^main rebuild-1 >actual &&
2026 grep hello actual
2027 '
2028
2029 test_expect_success 'cover letter using branch description (4)' '
2030 git checkout rebuild-1 &&
2031 test_config branch.rebuild-1.description hello &&
2032 git format-patch --stdout --cover-letter main.. >actual &&
2033 grep hello actual
2034 '
2035
2036 test_expect_success 'cover letter using branch description (5)' '
2037 git checkout rebuild-1 &&
2038 test_config branch.rebuild-1.description hello &&
2039 git format-patch --stdout --cover-letter -2 HEAD >actual &&
2040 grep hello actual
2041 '
2042
2043 test_expect_success 'cover letter using branch description (6)' '
2044 git checkout rebuild-1 &&
2045 test_config branch.rebuild-1.description hello &&
2046 git format-patch --stdout --cover-letter -2 >actual &&
2047 grep hello actual
2048 '
2049
2050 test_expect_success 'cover letter with --description-file' '
2051 test_when_finished "rm -f description.txt" &&
2052 cat >description.txt <<-\EOF &&
2053 subject from file
2054
2055 body from file
2056 EOF
2057 git checkout rebuild-1 &&
2058 git format-patch --stdout --cover-letter --cover-from-description auto \
2059 --description-file description.txt main >actual &&
2060 grep "^Subject: \[PATCH 0/2\] subject from file$" actual &&
2061 grep "^body from file$" actual
2062 '
2063
2064 test_expect_success 'cover letter with nothing' '
2065 git format-patch --stdout --cover-letter >actual &&
2066 test_line_count = 0 actual
2067 '
2068
2069 test_expect_success 'cover letter auto' '
2070 mkdir -p tmp &&
2071 test_when_finished "rm -rf tmp;
2072 git config --unset format.coverletter" &&
2073
2074 git config format.coverletter auto &&
2075 git format-patch -o tmp -1 >list &&
2076 test_line_count = 1 list &&
2077 git format-patch -o tmp -2 >list &&
2078 test_line_count = 3 list
2079 '
2080
2081 test_expect_success 'cover letter auto user override' '
2082 mkdir -p tmp &&
2083 test_when_finished "rm -rf tmp;
2084 git config --unset format.coverletter" &&
2085
2086 git config format.coverletter auto &&
2087 git format-patch -o tmp --cover-letter -1 >list &&
2088 test_line_count = 2 list &&
2089 git format-patch -o tmp --cover-letter -2 >list &&
2090 test_line_count = 3 list &&
2091 git format-patch -o tmp --no-cover-letter -1 >list &&
2092 test_line_count = 1 list &&
2093 git format-patch -o tmp --no-cover-letter -2 >list &&
2094 test_line_count = 2 list
2095 '
2096
2097 test_expect_success 'format-patch --zero-commit' '
2098 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
2099 grep "^From " patch2 | sort | uniq >actual &&
2100 echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
2101 test_cmp expect actual
2102 '
2103
2104 test_expect_success 'From line has expected format' '
2105 git format-patch --stdout v2..v1 >patch2 &&
2106 grep "^From " patch2 >from &&
2107 grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
2108 test_cmp from filtered
2109 '
2110
2111 test_expect_success 'format-patch -o with no leading directories' '
2112 rm -fr patches &&
2113 git format-patch -o patches main..side &&
2114 count=$(git rev-list --count main..side) &&
2115 ls patches >list &&
2116 test_line_count = $count list
2117 '
2118
2119 test_expect_success 'format-patch -o with leading existing directories' '
2120 rm -rf existing-dir &&
2121 mkdir existing-dir &&
2122 git format-patch -o existing-dir/patches main..side &&
2123 count=$(git rev-list --count main..side) &&
2124 ls existing-dir/patches >list &&
2125 test_line_count = $count list
2126 '
2127
2128 test_expect_success 'format-patch -o with leading non-existing directories' '
2129 rm -rf non-existing-dir &&
2130 git format-patch -o non-existing-dir/patches main..side &&
2131 count=$(git rev-list --count main..side) &&
2132 test_path_is_dir non-existing-dir &&
2133 ls non-existing-dir/patches >list &&
2134 test_line_count = $count list
2135 '
2136
2137 test_expect_success 'format-patch format.outputDirectory option' '
2138 test_config format.outputDirectory patches &&
2139 rm -fr patches &&
2140 git format-patch main..side &&
2141 count=$(git rev-list --count main..side) &&
2142 ls patches >list &&
2143 test_line_count = $count list
2144 '
2145
2146 test_expect_success 'format-patch -o overrides format.outputDirectory' '
2147 test_config format.outputDirectory patches &&
2148 rm -fr patches patchset &&
2149 git format-patch main..side -o patchset &&
2150 test_path_is_missing patches &&
2151 test_path_is_dir patchset
2152 '
2153
2154 test_expect_success 'format-patch forbids multiple outputs' '
2155 rm -fr outfile outdir &&
2156 test_must_fail \
2157 git format-patch --stdout --output-directory=outdir &&
2158 test_must_fail \
2159 git format-patch --stdout --output=outfile &&
2160 test_must_fail \
2161 git format-patch --output=outfile --output-directory=outdir
2162 '
2163
2164 test_expect_success 'configured outdir does not conflict with output options' '
2165 rm -fr outfile outdir &&
2166 test_config format.outputDirectory outdir &&
2167 git format-patch --stdout &&
2168 test_path_is_missing outdir &&
2169 git format-patch --output=outfile &&
2170 test_path_is_missing outdir
2171 '
2172
2173 test_expect_success 'format-patch --output' '
2174 rm -fr outfile &&
2175 git format-patch -3 --stdout HEAD >expect &&
2176 git format-patch -3 --output=outfile HEAD &&
2177 test_cmp expect outfile
2178 '
2179
2180 test_expect_success 'format-patch --cover-letter --output' '
2181 rm -fr outfile &&
2182 git format-patch --cover-letter -3 --stdout HEAD >expect &&
2183 git format-patch --cover-letter -3 --output=outfile HEAD &&
2184 test_cmp expect outfile
2185 '
2186
2187 test_expect_success 'format-patch --base' '
2188 git checkout patchid &&
2189
2190 git format-patch --stdout --base=HEAD~3 -1 >patch &&
2191 tail -n 7 patch >actual1 &&
2192
2193 git format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&
2194 tail -n 7 patch >actual2 &&
2195
2196 echo >expect &&
2197 git rev-parse HEAD~3 >commit-id-base &&
2198 echo "base-commit: $(cat commit-id-base)" >>expect &&
2199
2200 git show --patch HEAD~2 >patch &&
2201 git patch-id --stable <patch >patch.id.raw &&
2202 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2203
2204 git show --patch HEAD~1 >patch &&
2205 git patch-id --stable <patch >patch.id.raw &&
2206 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2207
2208 signature >>expect &&
2209 test_cmp expect actual1 &&
2210 test_cmp expect actual2 &&
2211
2212 echo >fail &&
2213 echo "base-commit: $(cat commit-id-base)" >>fail &&
2214
2215 git show --patch HEAD~2 >patch &&
2216 git patch-id --unstable <patch >patch.id.raw &&
2217 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2218
2219 git show --patch HEAD~1 >patch &&
2220 git patch-id --unstable <patch >patch.id.raw &&
2221 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2222
2223 signature >>fail &&
2224 ! test_cmp fail actual1 &&
2225 ! test_cmp fail actual2
2226 '
2227
2228 test_expect_success 'format-patch --base errors out when base commit is in revision list' '
2229 test_must_fail git format-patch --base=HEAD -2 &&
2230 test_must_fail git format-patch --base=HEAD~1 -2 &&
2231 git format-patch --stdout --base=HEAD~2 -2 >patch &&
2232 grep "^base-commit:" patch >actual &&
2233 git rev-parse HEAD~2 >commit-id-base &&
2234 echo "base-commit: $(cat commit-id-base)" >expect &&
2235 test_cmp expect actual
2236 '
2237
2238 test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
2239 # For history as below:
2240 #
2241 # ---Q---P---Z---Y---*---X
2242 # \ /
2243 # ------------W
2244 #
2245 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
2246 git checkout -b topic1 main &&
2247 git rev-parse HEAD >commit-id-base &&
2248 test_commit P &&
2249 git rev-parse HEAD >commit-id-P &&
2250 test_commit Z &&
2251 git rev-parse HEAD >commit-id-Z &&
2252 test_commit Y &&
2253 git checkout -b topic2 main &&
2254 test_commit W &&
2255 git merge topic1 &&
2256 test_commit X &&
2257 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
2258 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
2259 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
2260 grep "^base-commit:" patch >actual &&
2261 echo "base-commit: $(cat commit-id-base)" >expect &&
2262 test_cmp expect actual
2263 '
2264
2265 test_expect_success 'format-patch --base=auto' '
2266 git checkout -b upstream main &&
2267 git checkout -b local upstream &&
2268 git branch --set-upstream-to=upstream &&
2269 test_commit N1 &&
2270 test_commit N2 &&
2271 git format-patch --stdout --base=auto -2 >patch &&
2272 grep "^base-commit:" patch >actual &&
2273 git rev-parse upstream >commit-id-base &&
2274 echo "base-commit: $(cat commit-id-base)" >expect &&
2275 test_cmp expect actual
2276 '
2277
2278 test_expect_success 'format-patch errors out when history involves criss-cross' '
2279 # setup criss-cross history
2280 #
2281 # B---M1---D
2282 # / \ /
2283 # A X
2284 # \ / \
2285 # C---M2---E
2286 #
2287 git checkout main &&
2288 test_commit A &&
2289 git checkout -b xb main &&
2290 test_commit B &&
2291 git checkout -b xc main &&
2292 test_commit C &&
2293 git checkout -b xbc xb -- &&
2294 git merge xc &&
2295 git checkout -b xcb xc -- &&
2296 git branch --set-upstream-to=xbc &&
2297 git merge xb &&
2298 git checkout xbc &&
2299 test_commit D &&
2300 git checkout xcb &&
2301 test_commit E &&
2302 test_must_fail git format-patch --base=auto -1
2303 '
2304
2305 test_expect_success 'format-patch format.useAutoBase whenAble history involves criss-cross' '
2306 test_config format.useAutoBase whenAble &&
2307 git format-patch -1 >patch &&
2308 ! grep "^base-commit:" patch
2309 '
2310
2311 test_expect_success 'format-patch format.useAutoBase option' '
2312 git checkout local &&
2313 test_config format.useAutoBase true &&
2314 git format-patch --stdout -1 >patch &&
2315 grep "^base-commit:" patch >actual &&
2316 git rev-parse upstream >commit-id-base &&
2317 echo "base-commit: $(cat commit-id-base)" >expect &&
2318 test_cmp expect actual
2319 '
2320
2321 test_expect_success 'format-patch format.useAutoBase option with whenAble' '
2322 git checkout local &&
2323 test_config format.useAutoBase whenAble &&
2324 git format-patch --stdout -1 >patch &&
2325 grep "^base-commit:" patch >actual &&
2326 git rev-parse upstream >commit-id-base &&
2327 echo "base-commit: $(cat commit-id-base)" >expect &&
2328 test_cmp expect actual
2329 '
2330
2331 test_expect_success 'format-patch --base overrides format.useAutoBase' '
2332 test_config format.useAutoBase true &&
2333 git format-patch --stdout --base=HEAD~1 -1 >patch &&
2334 grep "^base-commit:" patch >actual &&
2335 git rev-parse HEAD~1 >commit-id-base &&
2336 echo "base-commit: $(cat commit-id-base)" >expect &&
2337 test_cmp expect actual
2338 '
2339
2340 test_expect_success 'format-patch --no-base overrides format.useAutoBase' '
2341 test_config format.useAutoBase true &&
2342 git format-patch --stdout --no-base -1 >patch &&
2343 ! grep "^base-commit:" patch
2344 '
2345
2346 test_expect_success 'format-patch --no-base overrides format.useAutoBase whenAble' '
2347 test_config format.useAutoBase whenAble &&
2348 git format-patch --stdout --no-base -1 >patch &&
2349 ! grep "^base-commit:" patch
2350 '
2351
2352 test_expect_success 'format-patch --base with --attach' '
2353 git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
2354 sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
2355 patch >actual &&
2356 test_write_lines 1 2 >expect &&
2357 test_cmp expect actual
2358 '
2359 test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
2360 test_when_finished "rm -fr patches" &&
2361 git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
2362 ! grep -E "^--+mimemime" patches/0000*.patch &&
2363 grep -E "^--+mimemime$" patches/0001*.patch >output &&
2364 test_line_count = 2 output &&
2365 grep -E "^--+mimemime--$" patches/0001*.patch >output &&
2366 test_line_count = 1 output
2367 '
2368
2369 test_expect_success 'format-patch with format.attach' '
2370 test_when_finished "rm -fr patches" &&
2371 separator=attachment-separator &&
2372 test_config format.attach "$separator" &&
2373 filename=$(git format-patch -o patches -1) &&
2374 grep "^Content-Type: multipart/.*$separator" "$filename"
2375 '
2376
2377 test_expect_success 'format-patch with format.attach=disabled' '
2378 test_when_finished "rm -fr patches" &&
2379 separator=attachment-separator &&
2380 test_config_global format.attach "$separator" &&
2381 test_config format.attach "" &&
2382 filename=$(git format-patch -o patches -1) &&
2383 # The output should not even declare content type for text/plain.
2384 ! grep "^Content-Type: multipart/" "$filename"
2385 '
2386
2387 test_expect_success '-c format.mboxrd format-patch' '
2388 sp=" " &&
2389 cat >msg <<-INPUT_END &&
2390 mboxrd should escape the body
2391
2392 From could trip up a loose mbox parser
2393 >From extra escape for reversibility
2394 >>From extra escape for reversibility 2
2395 from lower case not escaped
2396 Fromm bad speling not escaped
2397 From with leading space not escaped
2398
2399 F
2400 From
2401 From$sp
2402 From $sp
2403 From $sp
2404 INPUT_END
2405
2406 cat >expect <<-INPUT_END &&
2407 >From could trip up a loose mbox parser
2408 >>From extra escape for reversibility
2409 >>>From extra escape for reversibility 2
2410 from lower case not escaped
2411 Fromm bad speling not escaped
2412 From with leading space not escaped
2413
2414 F
2415 From
2416 From
2417 From
2418 From
2419 INPUT_END
2420
2421 C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
2422 git -c format.mboxrd format-patch --stdout -1 $C~1..$C >patch &&
2423 git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >compat &&
2424 test_cmp patch compat &&
2425 git grep -h --no-index -A11 \
2426 "^>From could trip up a loose mbox parser" patch >actual &&
2427 test_cmp expect actual
2428 '
2429
2430 test_expect_success 'interdiff: setup' '
2431 git checkout -b boop main &&
2432 test_commit fnorp blorp &&
2433 test_commit fleep blorp
2434 '
2435
2436 test_expect_success 'interdiff: cover-letter' '
2437 sed "y/q/ /" >expect <<-\EOF &&
2438 +fleep
2439 --q
2440 EOF
2441 git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
2442 test_grep "^Interdiff:$" 0000-cover-letter.patch &&
2443 test_grep ! "^Interdiff:$" 0001-fleep.patch &&
2444 sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual &&
2445 test_cmp expect actual
2446 '
2447
2448 test_expect_success 'interdiff: reroll-count' '
2449 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2450 test_grep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2451 '
2452
2453 test_expect_success 'interdiff: reroll-count with a non-integer' '
2454 git format-patch --cover-letter --interdiff=boop~2 -v2.2 -1 boop &&
2455 test_grep "^Interdiff:$" v2.2-0000-cover-letter.patch
2456 '
2457
2458 test_expect_success 'interdiff: reroll-count with a integer' '
2459 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2460 test_grep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2461 '
2462
2463 test_expect_success 'interdiff: solo-patch' '
2464 cat >expect <<-\EOF &&
2465 +fleep
2466
2467 EOF
2468 git format-patch --interdiff=boop~2 -1 boop &&
2469 test_grep "^Interdiff:$" 0001-fleep.patch &&
2470 sed "1,/^ @@ /d; /^$/q" 0001-fleep.patch >actual &&
2471 test_cmp expect actual
2472 '
2473
2474 test_expect_success 'format-patch does not respect diff.noprefix' '
2475 git -c diff.noprefix format-patch -1 --stdout >actual &&
2476 grep "^--- a/blorp" actual
2477 '
2478
2479 test_expect_success 'format-patch respects format.noprefix' '
2480 git -c format.noprefix format-patch -1 --stdout >actual &&
2481 grep "^--- blorp" actual
2482 '
2483
2484 test_expect_success 'format-patch --default-prefix overrides format.noprefix' '
2485 git -c format.noprefix \
2486 format-patch -1 --default-prefix --stdout >actual &&
2487 grep "^--- a/blorp" actual
2488 '
2489
2490 test_done