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