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