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