Merge branch 'ag/sequencer-todo-updates'
[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 slave master &&
85         echo "Another line" >>file &&
86         test_tick &&
87         git commit -am "Slave change #1" &&
88         echo "Yet another line" >>file &&
89         test_tick &&
90         git commit -am "Slave change #2" &&
91         git checkout -b merger master &&
92         test_tick &&
93         git merge --no-ff slave &&
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 echo "fatal: --name-only does not make sense" >expect.name-only
797 echo "fatal: --name-status does not make sense" >expect.name-status
798 echo "fatal: --check does not make sense" >expect.check
799
800 test_expect_success 'options no longer allowed for format-patch' '
801         test_must_fail git format-patch --name-only 2>output &&
802         test_i18ncmp expect.name-only output &&
803         test_must_fail git format-patch --name-status 2>output &&
804         test_i18ncmp expect.name-status output &&
805         test_must_fail git format-patch --check 2>output &&
806         test_i18ncmp expect.check output
807 '
808
809 test_expect_success 'format-patch --numstat should produce a patch' '
810         git format-patch --numstat --stdout master..side >output &&
811         grep "^diff --git a/" output >diff &&
812         test_line_count = 5 diff
813 '
814
815 test_expect_success 'format-patch -- <path>' '
816         git format-patch master..side -- file 2>error &&
817         ! grep "Use .--" error
818 '
819
820 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
821         git format-patch --ignore-if-in-upstream HEAD
822 '
823
824 test_expect_success 'get git version' '
825         git_version=$(git --version) &&
826         git_version=${git_version##* }
827 '
828
829 signature() {
830         printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
831 }
832
833 test_expect_success 'format-patch default signature' '
834         git format-patch --stdout -1 >patch &&
835         tail -n 3 patch >output &&
836         signature >expect &&
837         test_cmp expect output
838 '
839
840 test_expect_success 'format-patch --signature' '
841         git format-patch --stdout --signature="my sig" -1 >patch &&
842         tail -n 3 patch >output &&
843         signature "my sig" >expect &&
844         test_cmp expect output
845 '
846
847 test_expect_success 'format-patch with format.signature config' '
848         git config format.signature "config sig" &&
849         git format-patch --stdout -1 >output &&
850         grep "config sig" output
851 '
852
853 test_expect_success 'format-patch --signature overrides format.signature' '
854         git config format.signature "config sig" &&
855         git format-patch --stdout --signature="overrides" -1 >output &&
856         ! grep "config sig" output &&
857         grep "overrides" output
858 '
859
860 test_expect_success 'format-patch --no-signature ignores format.signature' '
861         git config format.signature "config sig" &&
862         git format-patch --stdout --signature="my sig" --no-signature \
863                 -1 >output &&
864         check_patch output &&
865         ! grep "config sig" output &&
866         ! grep "my sig" output &&
867         ! grep "^-- \$" output
868 '
869
870 test_expect_success 'format-patch --signature --cover-letter' '
871         git config --unset-all format.signature &&
872         git format-patch --stdout --signature="my sig" --cover-letter \
873                 -1 >output &&
874         grep "my sig" output >sig &&
875         test_line_count = 2 sig
876 '
877
878 test_expect_success 'format.signature="" suppresses signatures' '
879         git config format.signature "" &&
880         git format-patch --stdout -1 >output &&
881         check_patch output &&
882         ! grep "^-- \$" output
883 '
884
885 test_expect_success 'format-patch --no-signature suppresses signatures' '
886         git config --unset-all format.signature &&
887         git format-patch --stdout --no-signature -1 >output &&
888         check_patch output &&
889         ! grep "^-- \$" output
890 '
891
892 test_expect_success 'format-patch --signature="" suppresses signatures' '
893         git format-patch --stdout --signature="" -1 >output &&
894         check_patch output &&
895         ! grep "^-- \$" output
896 '
897
898 test_expect_success 'prepare mail-signature input' '
899         cat >mail-signature <<-\EOF
900
901         Test User <test.email@kernel.org>
902         http://git.kernel.org/cgit/git/git.git
903
904         git.kernel.org/?p=git/git.git;a=summary
905
906         EOF
907 '
908
909 test_expect_success '--signature-file=file works' '
910         git format-patch --stdout --signature-file=mail-signature -1 >output &&
911         check_patch output &&
912         sed -e "1,/^-- \$/d" output >actual &&
913         {
914                 cat mail-signature && echo
915         } >expect &&
916         test_cmp expect actual
917 '
918
919 test_expect_success 'format.signaturefile works' '
920         test_config format.signaturefile mail-signature &&
921         git format-patch --stdout -1 >output &&
922         check_patch output &&
923         sed -e "1,/^-- \$/d" output >actual &&
924         {
925                 cat mail-signature && echo
926         } >expect &&
927         test_cmp expect actual
928 '
929
930 test_expect_success '--no-signature suppresses format.signaturefile ' '
931         test_config format.signaturefile mail-signature &&
932         git format-patch --stdout --no-signature -1 >output &&
933         check_patch output &&
934         ! grep "^-- \$" output
935 '
936
937 test_expect_success '--signature-file overrides format.signaturefile' '
938         cat >other-mail-signature <<-\EOF &&
939         Use this other signature instead of mail-signature.
940         EOF
941         test_config format.signaturefile mail-signature &&
942         git format-patch --stdout \
943                         --signature-file=other-mail-signature -1 >output &&
944         check_patch output &&
945         sed -e "1,/^-- \$/d" output >actual &&
946         {
947                 cat other-mail-signature && echo
948         } >expect &&
949         test_cmp expect actual
950 '
951
952 test_expect_success '--signature overrides format.signaturefile' '
953         test_config format.signaturefile mail-signature &&
954         git format-patch --stdout --signature="my sig" -1 >output &&
955         check_patch output &&
956         grep "my sig" output
957 '
958
959 test_expect_success TTY 'format-patch --stdout paginates' '
960         rm -f pager_used &&
961         test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
962         test_path_is_file pager_used
963 '
964
965  test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
966         rm -f pager_used &&
967         test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
968         test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
969         test_path_is_missing pager_used &&
970         test_path_is_missing .git/pager_used
971 '
972
973 test_expect_success 'format-patch handles multi-line subjects' '
974         rm -rf patches/ &&
975         echo content >>file &&
976         for i in one two three; do echo $i; done >msg &&
977         git add file &&
978         git commit -F msg &&
979         git format-patch -o patches -1 &&
980         grep ^Subject: patches/0001-one.patch >actual &&
981         echo "Subject: [PATCH] one two three" >expect &&
982         test_cmp expect actual
983 '
984
985 test_expect_success 'format-patch handles multi-line encoded subjects' '
986         rm -rf patches/ &&
987         echo content >>file &&
988         for i in en två tre; do echo $i; done >msg &&
989         git add file &&
990         git commit -F msg &&
991         git format-patch -o patches -1 &&
992         grep ^Subject: patches/0001-en.patch >actual &&
993         echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
994         test_cmp expect actual
995 '
996
997 M8="foo bar "
998 M64=$M8$M8$M8$M8$M8$M8$M8$M8
999 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1000 cat >expect <<'EOF'
1001 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1002  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1003  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1004  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1005  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1006  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1007  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1008 EOF
1009 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
1010         echo content >>file &&
1011         git add file &&
1012         git commit -m "$M512" &&
1013         git format-patch --stdout -1 >patch &&
1014         sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1015         test_cmp expect subject
1016 '
1017
1018 M8="föö bar "
1019 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1020 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1021 cat >expect <<'EOF'
1022 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1023  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1024  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1025  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1026  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1027  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1028  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1029  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1030  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1031  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1032  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1033  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1034  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1035  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1036  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1037  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1038  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1039  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1040  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1041  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1042  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1043  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1044  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1045  =?UTF-8?q?bar?=
1046 EOF
1047 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
1048         rm -rf patches/ &&
1049         echo content >>file &&
1050         git add file &&
1051         git commit -m "$M512" &&
1052         git format-patch --stdout -1 >patch &&
1053         sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1054         test_cmp expect subject
1055 '
1056
1057 check_author() {
1058         echo content >>file &&
1059         git add file &&
1060         GIT_AUTHOR_NAME=$1 git commit -m author-check &&
1061         git format-patch --stdout -1 >patch &&
1062         sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1063         test_cmp expect actual
1064 }
1065
1066 cat >expect <<'EOF'
1067 From: "Foo B. Bar" <author@example.com>
1068 EOF
1069 test_expect_success 'format-patch quotes dot in from-headers' '
1070         check_author "Foo B. Bar"
1071 '
1072
1073 cat >expect <<'EOF'
1074 From: "Foo \"The Baz\" Bar" <author@example.com>
1075 EOF
1076 test_expect_success 'format-patch quotes double-quote in from-headers' '
1077         check_author "Foo \"The Baz\" Bar"
1078 '
1079
1080 cat >expect <<'EOF'
1081 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1082 EOF
1083 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1084         check_author "Föo Bar"
1085 '
1086
1087 cat >expect <<'EOF'
1088 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1089 EOF
1090 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1091         check_author "Föo B. Bar"
1092 '
1093
1094 cat >expect <<EOF
1095 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1096  <author@example.com>
1097 EOF
1098 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1099         check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1100 '
1101
1102 cat >expect <<'EOF'
1103 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1104  Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1105  Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1106 EOF
1107 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1108         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"
1109 '
1110
1111 cat >expect <<'EOF'
1112 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1113  Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1114  Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1115 EOF
1116 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1117         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"
1118 '
1119
1120 cat >expect <<'EOF'
1121 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1122  =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1123  =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1124  =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1125  =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1126 EOF
1127 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1128         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"
1129 '
1130
1131 cat >expect <<'EOF'
1132 Subject: header with . in it
1133 EOF
1134 test_expect_success 'subject lines do not have 822 atom-quoting' '
1135         echo content >>file &&
1136         git add file &&
1137         git commit -m "header with . in it" &&
1138         git format-patch -k -1 --stdout >patch &&
1139         grep ^Subject: patch >actual &&
1140         test_cmp expect actual
1141 '
1142
1143 cat >expect <<'EOF'
1144 Subject: [PREFIX 1/1] header with . in it
1145 EOF
1146 test_expect_success 'subject prefixes have space prepended' '
1147         git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1148         grep ^Subject: patch >actual &&
1149         test_cmp expect actual
1150 '
1151
1152 cat >expect <<'EOF'
1153 Subject: [1/1] header with . in it
1154 EOF
1155 test_expect_success 'empty subject prefix does not have extra space' '
1156         git format-patch -n -1 --stdout --subject-prefix= >patch &&
1157         grep ^Subject: patch >actual &&
1158         test_cmp expect actual
1159 '
1160
1161 test_expect_success '--rfc' '
1162         cat >expect <<-\EOF &&
1163         Subject: [RFC PATCH 1/1] header with . in it
1164         EOF
1165         git format-patch -n -1 --stdout --rfc >patch &&
1166         grep ^Subject: patch >actual &&
1167         test_cmp expect actual
1168 '
1169
1170 test_expect_success '--from=ident notices bogus ident' '
1171         test_must_fail git format-patch -1 --stdout --from=foo >patch
1172 '
1173
1174 test_expect_success '--from=ident replaces author' '
1175         git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1176         cat >expect <<-\EOF &&
1177         From: Me <me@example.com>
1178
1179         From: A U Thor <author@example.com>
1180
1181         EOF
1182         sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1183         test_cmp expect patch.head
1184 '
1185
1186 test_expect_success '--from uses committer ident' '
1187         git format-patch -1 --stdout --from >patch &&
1188         cat >expect <<-\EOF &&
1189         From: C O Mitter <committer@example.com>
1190
1191         From: A U Thor <author@example.com>
1192
1193         EOF
1194         sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1195         test_cmp expect patch.head
1196 '
1197
1198 test_expect_success '--from omits redundant in-body header' '
1199         git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1200         cat >expect <<-\EOF &&
1201         From: A U Thor <author@example.com>
1202
1203         EOF
1204         sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1205         test_cmp expect patch.head
1206 '
1207
1208 test_expect_success 'in-body headers trigger content encoding' '
1209         test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1210         test_when_finished "git reset --hard HEAD^" &&
1211         git format-patch -1 --stdout --from >patch &&
1212         cat >expect <<-\EOF &&
1213         From: C O Mitter <committer@example.com>
1214         Content-Type: text/plain; charset=UTF-8
1215
1216         From: éxötìc <author@example.com>
1217
1218         EOF
1219         sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" patch >patch.head &&
1220         test_cmp expect patch.head
1221 '
1222
1223 append_signoff()
1224 {
1225         C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1226         git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1227         sed -n -e "1,/^---$/p" append_signoff.patch |
1228                 egrep -n "^Subject|Sign|^$"
1229 }
1230
1231 test_expect_success 'signoff: commit with no body' '
1232         append_signoff </dev/null >actual &&
1233         cat <<-\EOF | sed "s/EOL$//" >expect &&
1234         4:Subject: [PATCH] EOL
1235         8:
1236         9:Signed-off-by: C O Mitter <committer@example.com>
1237         EOF
1238         test_cmp expect actual
1239 '
1240
1241 test_expect_success 'signoff: commit with only subject' '
1242         echo subject | append_signoff >actual &&
1243         cat >expect <<-\EOF &&
1244         4:Subject: [PATCH] subject
1245         8:
1246         9:Signed-off-by: C O Mitter <committer@example.com>
1247         EOF
1248         test_cmp expect actual
1249 '
1250
1251 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1252         printf subject | append_signoff >actual &&
1253         cat >expect <<-\EOF &&
1254         4:Subject: [PATCH] subject
1255         8:
1256         9:Signed-off-by: C O Mitter <committer@example.com>
1257         EOF
1258         test_cmp expect actual
1259 '
1260
1261 test_expect_success 'signoff: no existing signoffs' '
1262         append_signoff <<-\EOF >actual &&
1263         subject
1264
1265         body
1266         EOF
1267         cat >expect <<-\EOF &&
1268         4:Subject: [PATCH] subject
1269         8:
1270         10:
1271         11:Signed-off-by: C O Mitter <committer@example.com>
1272         EOF
1273         test_cmp expect actual
1274 '
1275
1276 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1277         printf "subject\n\nbody" | append_signoff >actual &&
1278         cat >expect <<-\EOF &&
1279         4:Subject: [PATCH] subject
1280         8:
1281         10:
1282         11:Signed-off-by: C O Mitter <committer@example.com>
1283         EOF
1284         test_cmp expect actual
1285 '
1286
1287 test_expect_success 'signoff: some random signoff' '
1288         append_signoff <<-\EOF >actual &&
1289         subject
1290
1291         body
1292
1293         Signed-off-by: my@house
1294         EOF
1295         cat >expect <<-\EOF &&
1296         4:Subject: [PATCH] subject
1297         8:
1298         10:
1299         11:Signed-off-by: my@house
1300         12:Signed-off-by: C O Mitter <committer@example.com>
1301         EOF
1302         test_cmp expect actual
1303 '
1304
1305 test_expect_success 'signoff: misc conforming footer elements' '
1306         append_signoff <<-\EOF >actual &&
1307         subject
1308
1309         body
1310
1311         Signed-off-by: my@house
1312         (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1313         Tested-by: Some One <someone@example.com>
1314         Bug: 1234
1315         EOF
1316         cat >expect <<-\EOF &&
1317         4:Subject: [PATCH] subject
1318         8:
1319         10:
1320         11:Signed-off-by: my@house
1321         15:Signed-off-by: C O Mitter <committer@example.com>
1322         EOF
1323         test_cmp expect actual
1324 '
1325
1326 test_expect_success 'signoff: some random signoff-alike' '
1327         append_signoff <<-\EOF >actual &&
1328         subject
1329
1330         body
1331         Fooled-by-me: my@house
1332         EOF
1333         cat >expect <<-\EOF &&
1334         4:Subject: [PATCH] subject
1335         8:
1336         11:
1337         12:Signed-off-by: C O Mitter <committer@example.com>
1338         EOF
1339         test_cmp expect actual
1340 '
1341
1342 test_expect_success 'signoff: not really a signoff' '
1343         append_signoff <<-\EOF >actual &&
1344         subject
1345
1346         I want to mention about Signed-off-by: here.
1347         EOF
1348         cat >expect <<-\EOF &&
1349         4:Subject: [PATCH] subject
1350         8:
1351         9:I want to mention about Signed-off-by: here.
1352         10:
1353         11:Signed-off-by: C O Mitter <committer@example.com>
1354         EOF
1355         test_cmp expect actual
1356 '
1357
1358 test_expect_success 'signoff: not really a signoff (2)' '
1359         append_signoff <<-\EOF >actual &&
1360         subject
1361
1362         My unfortunate
1363         Signed-off-by: example happens to be wrapped here.
1364         EOF
1365         cat >expect <<-\EOF &&
1366         4:Subject: [PATCH] subject
1367         8:
1368         10:Signed-off-by: example happens to be wrapped here.
1369         11:Signed-off-by: C O Mitter <committer@example.com>
1370         EOF
1371         test_cmp expect actual
1372 '
1373
1374 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1375         append_signoff <<-\EOF >actual &&
1376         subject
1377
1378         Signed-off-by: my@house
1379         Signed-off-by: your@house
1380
1381         A lot of houses.
1382         EOF
1383         cat >expect <<-\EOF &&
1384         4:Subject: [PATCH] subject
1385         8:
1386         9:Signed-off-by: my@house
1387         10:Signed-off-by: your@house
1388         11:
1389         13:
1390         14:Signed-off-by: C O Mitter <committer@example.com>
1391         EOF
1392         test_cmp expect actual
1393 '
1394
1395 test_expect_success 'signoff: the same signoff at the end' '
1396         append_signoff <<-\EOF >actual &&
1397         subject
1398
1399         body
1400
1401         Signed-off-by: C O Mitter <committer@example.com>
1402         EOF
1403         cat >expect <<-\EOF &&
1404         4:Subject: [PATCH] subject
1405         8:
1406         10:
1407         11:Signed-off-by: C O Mitter <committer@example.com>
1408         EOF
1409         test_cmp expect actual
1410 '
1411
1412 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1413         printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1414                 append_signoff >actual &&
1415         cat >expect <<-\EOF &&
1416         4:Subject: [PATCH] subject
1417         8:
1418         9:Signed-off-by: C O Mitter <committer@example.com>
1419         EOF
1420         test_cmp expect actual
1421 '
1422
1423 test_expect_success 'signoff: the same signoff NOT at the end' '
1424         append_signoff <<-\EOF >actual &&
1425         subject
1426
1427         body
1428
1429         Signed-off-by: C O Mitter <committer@example.com>
1430         Signed-off-by: my@house
1431         EOF
1432         cat >expect <<-\EOF &&
1433         4:Subject: [PATCH] subject
1434         8:
1435         10:
1436         11:Signed-off-by: C O Mitter <committer@example.com>
1437         12:Signed-off-by: my@house
1438         EOF
1439         test_cmp expect actual
1440 '
1441
1442 test_expect_success 'signoff: tolerate garbage in conforming footer' '
1443         append_signoff <<-\EOF >actual &&
1444         subject
1445
1446         body
1447
1448         Tested-by: my@house
1449         Some Trash
1450         Signed-off-by: C O Mitter <committer@example.com>
1451         EOF
1452         cat >expect <<-\EOF &&
1453         4:Subject: [PATCH] subject
1454         8:
1455         10:
1456         13:Signed-off-by: C O Mitter <committer@example.com>
1457         EOF
1458         test_cmp expect actual
1459 '
1460
1461 test_expect_success 'signoff: respect trailer config' '
1462         append_signoff <<-\EOF >actual &&
1463         subject
1464
1465         Myfooter: x
1466         Some Trash
1467         EOF
1468         cat >expect <<-\EOF &&
1469         4:Subject: [PATCH] subject
1470         8:
1471         11:
1472         12:Signed-off-by: C O Mitter <committer@example.com>
1473         EOF
1474         test_cmp expect actual &&
1475
1476         test_config trailer.Myfooter.ifexists add &&
1477         append_signoff <<-\EOF >actual &&
1478         subject
1479
1480         Myfooter: x
1481         Some Trash
1482         EOF
1483         cat >expect <<-\EOF &&
1484         4:Subject: [PATCH] subject
1485         8:
1486         11:Signed-off-by: C O Mitter <committer@example.com>
1487         EOF
1488         test_cmp expect actual
1489 '
1490
1491 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1492         append_signoff <<-\EOF >actual &&
1493         subject
1494
1495         body
1496
1497         Reviewed-id: Noone
1498         Tested-by: my@house
1499         Change-id: Ideadbeef
1500         Signed-off-by: C O Mitter <committer@example.com>
1501         Bug: 1234
1502         EOF
1503         cat >expect <<-\EOF &&
1504         4:Subject: [PATCH] subject
1505         8:
1506         10:
1507         14:Signed-off-by: C O Mitter <committer@example.com>
1508         EOF
1509         test_cmp expect actual
1510 '
1511
1512 test_expect_success 'format patch ignores color.ui' '
1513         test_unconfig color.ui &&
1514         git format-patch --stdout -1 >expect &&
1515         test_config color.ui always &&
1516         git format-patch --stdout -1 >actual &&
1517         test_cmp expect actual
1518 '
1519
1520 test_expect_success 'cover letter with invalid --cover-from-description and config' '
1521         test_config branch.rebuild-1.description "config subject
1522
1523 body" &&
1524         test_must_fail git format-patch --cover-letter --cover-from-description garbage master &&
1525         test_config format.coverFromDescription garbage &&
1526         test_must_fail git format-patch --cover-letter master
1527 '
1528
1529 test_expect_success 'cover letter with format.coverFromDescription = default' '
1530         test_config branch.rebuild-1.description "config subject
1531
1532 body" &&
1533         test_config format.coverFromDescription default &&
1534         git checkout rebuild-1 &&
1535         git format-patch --stdout --cover-letter master >actual &&
1536         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1537         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1538         grep "^config subject$" actual &&
1539         grep "^body$" actual
1540 '
1541
1542 test_expect_success 'cover letter with --cover-from-description default' '
1543         test_config branch.rebuild-1.description "config subject
1544
1545 body" &&
1546         git checkout rebuild-1 &&
1547         git format-patch --stdout --cover-letter --cover-from-description default master >actual &&
1548         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1549         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1550         grep "^config subject$" actual &&
1551         grep "^body$" actual
1552 '
1553
1554 test_expect_success 'cover letter with format.coverFromDescription = none' '
1555         test_config branch.rebuild-1.description "config subject
1556
1557 body" &&
1558         test_config format.coverFromDescription none &&
1559         git checkout rebuild-1 &&
1560         git format-patch --stdout --cover-letter master >actual &&
1561         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1562         grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1563         ! grep "^config subject$" actual &&
1564         ! grep "^body$" actual
1565 '
1566
1567 test_expect_success 'cover letter with --cover-from-description none' '
1568         test_config branch.rebuild-1.description "config subject
1569
1570 body" &&
1571         git checkout rebuild-1 &&
1572         git format-patch --stdout --cover-letter --cover-from-description none master >actual &&
1573         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1574         grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1575         ! grep "^config subject$" actual &&
1576         ! grep "^body$" actual
1577 '
1578
1579 test_expect_success 'cover letter with format.coverFromDescription = message' '
1580         test_config branch.rebuild-1.description "config subject
1581
1582 body" &&
1583         test_config format.coverFromDescription message &&
1584         git checkout rebuild-1 &&
1585         git format-patch --stdout --cover-letter master >actual &&
1586         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1587         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1588         grep "^config subject$" actual &&
1589         grep "^body$" actual
1590 '
1591
1592 test_expect_success 'cover letter with --cover-from-description message' '
1593         test_config branch.rebuild-1.description "config subject
1594
1595 body" &&
1596         git checkout rebuild-1 &&
1597         git format-patch --stdout --cover-letter --cover-from-description message master >actual &&
1598         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1599         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1600         grep "^config subject$" actual &&
1601         grep "^body$" actual
1602 '
1603
1604 test_expect_success 'cover letter with format.coverFromDescription = subject' '
1605         test_config branch.rebuild-1.description "config subject
1606
1607 body" &&
1608         test_config format.coverFromDescription subject &&
1609         git checkout rebuild-1 &&
1610         git format-patch --stdout --cover-letter master >actual &&
1611         grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1612         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1613         ! grep "^config subject$" actual &&
1614         grep "^body$" actual
1615 '
1616
1617 test_expect_success 'cover letter with --cover-from-description subject' '
1618         test_config branch.rebuild-1.description "config subject
1619
1620 body" &&
1621         git checkout rebuild-1 &&
1622         git format-patch --stdout --cover-letter --cover-from-description subject master >actual &&
1623         grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1624         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1625         ! grep "^config subject$" actual &&
1626         grep "^body$" actual
1627 '
1628
1629 test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' '
1630         test_config branch.rebuild-1.description "config subject
1631
1632 body" &&
1633         test_config format.coverFromDescription auto &&
1634         git checkout rebuild-1 &&
1635         git format-patch --stdout --cover-letter master >actual &&
1636         grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1637         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1638         ! grep "^config subject$" actual &&
1639         grep "^body$" actual
1640 '
1641
1642 test_expect_success 'cover letter with --cover-from-description auto (short subject line)' '
1643         test_config branch.rebuild-1.description "config subject
1644
1645 body" &&
1646         git checkout rebuild-1 &&
1647         git format-patch --stdout --cover-letter --cover-from-description auto master >actual &&
1648         grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1649         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1650         ! grep "^config subject$" actual &&
1651         grep "^body$" actual
1652 '
1653
1654 test_expect_success 'cover letter with format.coverFromDescription = auto (long subject line)' '
1655         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
1656
1657 body" &&
1658         test_config format.coverFromDescription auto &&
1659         git checkout rebuild-1 &&
1660         git format-patch --stdout --cover-letter master >actual &&
1661         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1662         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1663         grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1664         grep "^body$" actual
1665 '
1666
1667 test_expect_success 'cover letter with --cover-from-description auto (long subject line)' '
1668         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
1669
1670 body" &&
1671         git checkout rebuild-1 &&
1672         git format-patch --stdout --cover-letter --cover-from-description auto master >actual &&
1673         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1674         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1675         grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1676         grep "^body$" actual
1677 '
1678
1679 test_expect_success 'cover letter with command-line --cover-from-description overrides config' '
1680         test_config branch.rebuild-1.description "config subject
1681
1682 body" &&
1683         test_config format.coverFromDescription none &&
1684         git checkout rebuild-1 &&
1685         git format-patch --stdout --cover-letter --cover-from-description subject master >actual &&
1686         grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1687         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1688         ! grep "^config subject$" actual &&
1689         grep "^body$" actual
1690 '
1691
1692 test_expect_success 'cover letter using branch description (1)' '
1693         git checkout rebuild-1 &&
1694         test_config branch.rebuild-1.description hello &&
1695         git format-patch --stdout --cover-letter master >actual &&
1696         grep hello actual
1697 '
1698
1699 test_expect_success 'cover letter using branch description (2)' '
1700         git checkout rebuild-1 &&
1701         test_config branch.rebuild-1.description hello &&
1702         git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1703         grep hello actual
1704 '
1705
1706 test_expect_success 'cover letter using branch description (3)' '
1707         git checkout rebuild-1 &&
1708         test_config branch.rebuild-1.description hello &&
1709         git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1710         grep hello actual
1711 '
1712
1713 test_expect_success 'cover letter using branch description (4)' '
1714         git checkout rebuild-1 &&
1715         test_config branch.rebuild-1.description hello &&
1716         git format-patch --stdout --cover-letter master.. >actual &&
1717         grep hello actual
1718 '
1719
1720 test_expect_success 'cover letter using branch description (5)' '
1721         git checkout rebuild-1 &&
1722         test_config branch.rebuild-1.description hello &&
1723         git format-patch --stdout --cover-letter -2 HEAD >actual &&
1724         grep hello actual
1725 '
1726
1727 test_expect_success 'cover letter using branch description (6)' '
1728         git checkout rebuild-1 &&
1729         test_config branch.rebuild-1.description hello &&
1730         git format-patch --stdout --cover-letter -2 >actual &&
1731         grep hello actual
1732 '
1733
1734 test_expect_success 'cover letter with nothing' '
1735         git format-patch --stdout --cover-letter >actual &&
1736         test_line_count = 0 actual
1737 '
1738
1739 test_expect_success 'cover letter auto' '
1740         mkdir -p tmp &&
1741         test_when_finished "rm -rf tmp;
1742                 git config --unset format.coverletter" &&
1743
1744         git config format.coverletter auto &&
1745         git format-patch -o tmp -1 >list &&
1746         test_line_count = 1 list &&
1747         git format-patch -o tmp -2 >list &&
1748         test_line_count = 3 list
1749 '
1750
1751 test_expect_success 'cover letter auto user override' '
1752         mkdir -p tmp &&
1753         test_when_finished "rm -rf tmp;
1754                 git config --unset format.coverletter" &&
1755
1756         git config format.coverletter auto &&
1757         git format-patch -o tmp --cover-letter -1 >list &&
1758         test_line_count = 2 list &&
1759         git format-patch -o tmp --cover-letter -2 >list &&
1760         test_line_count = 3 list &&
1761         git format-patch -o tmp --no-cover-letter -1 >list &&
1762         test_line_count = 1 list &&
1763         git format-patch -o tmp --no-cover-letter -2 >list &&
1764         test_line_count = 2 list
1765 '
1766
1767 test_expect_success 'format-patch --zero-commit' '
1768         git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1769         grep "^From " patch2 | sort | uniq >actual &&
1770         echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
1771         test_cmp expect actual
1772 '
1773
1774 test_expect_success 'From line has expected format' '
1775         git format-patch --stdout v2..v1 >patch2 &&
1776         grep "^From " patch2 >from &&
1777         grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1778         test_cmp from filtered
1779 '
1780
1781 test_expect_success 'format-patch -o with no leading directories' '
1782         rm -fr patches &&
1783         git format-patch -o patches master..side &&
1784         count=$(git rev-list --count master..side) &&
1785         ls patches >list &&
1786         test_line_count = $count list
1787 '
1788
1789 test_expect_success 'format-patch -o with leading existing directories' '
1790         rm -rf existing-dir &&
1791         mkdir existing-dir &&
1792         git format-patch -o existing-dir/patches master..side &&
1793         count=$(git rev-list --count master..side) &&
1794         ls existing-dir/patches >list &&
1795         test_line_count = $count list
1796 '
1797
1798 test_expect_success 'format-patch -o with leading non-existing directories' '
1799         rm -rf non-existing-dir &&
1800         git format-patch -o non-existing-dir/patches master..side &&
1801         count=$(git rev-list --count master..side) &&
1802         test_path_is_dir non-existing-dir &&
1803         ls non-existing-dir/patches >list &&
1804         test_line_count = $count list
1805 '
1806
1807 test_expect_success 'format-patch format.outputDirectory option' '
1808         test_config format.outputDirectory patches &&
1809         rm -fr patches &&
1810         git format-patch master..side &&
1811         count=$(git rev-list --count master..side) &&
1812         ls patches >list &&
1813         test_line_count = $count list
1814 '
1815
1816 test_expect_success 'format-patch -o overrides format.outputDirectory' '
1817         test_config format.outputDirectory patches &&
1818         rm -fr patches patchset &&
1819         git format-patch master..side -o patchset &&
1820         test_path_is_missing patches &&
1821         test_path_is_dir patchset
1822 '
1823
1824 test_expect_success 'format-patch --base' '
1825         git checkout patchid &&
1826
1827         git format-patch --stdout --base=HEAD~3 -1 >patch &&
1828         tail -n 7 patch >actual1 &&
1829
1830         git format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&
1831         tail -n 7 patch >actual2 &&
1832
1833         echo >expect &&
1834         git rev-parse HEAD~3 >commit-id-base &&
1835         echo "base-commit: $(cat commit-id-base)" >>expect &&
1836
1837         git show --patch HEAD~2 >patch &&
1838         git patch-id --stable <patch >patch.id.raw &&
1839         awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
1840
1841         git show --patch HEAD~1 >patch &&
1842         git patch-id --stable <patch >patch.id.raw &&
1843         awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
1844
1845         signature >>expect &&
1846         test_cmp expect actual1 &&
1847         test_cmp expect actual2 &&
1848
1849         echo >fail &&
1850         echo "base-commit: $(cat commit-id-base)" >>fail &&
1851
1852         git show --patch HEAD~2 >patch &&
1853         git patch-id --unstable <patch >patch.id.raw &&
1854         awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
1855
1856         git show --patch HEAD~1 >patch &&
1857         git patch-id --unstable <patch >patch.id.raw &&
1858         awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
1859
1860         signature >>fail &&
1861         ! test_cmp fail actual1 &&
1862         ! test_cmp fail actual2
1863 '
1864
1865 test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1866         test_must_fail git format-patch --base=HEAD -2 &&
1867         test_must_fail git format-patch --base=HEAD~1 -2 &&
1868         git format-patch --stdout --base=HEAD~2 -2 >patch &&
1869         grep "^base-commit:" patch >actual &&
1870         git rev-parse HEAD~2 >commit-id-base &&
1871         echo "base-commit: $(cat commit-id-base)" >expect &&
1872         test_cmp expect actual
1873 '
1874
1875 test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1876         # For history as below:
1877         #
1878         #    ---Q---P---Z---Y---*---X
1879         #        \             /
1880         #         ------------W
1881         #
1882         # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1883         git checkout -b topic1 master &&
1884         git rev-parse HEAD >commit-id-base &&
1885         test_commit P &&
1886         git rev-parse HEAD >commit-id-P &&
1887         test_commit Z &&
1888         git rev-parse HEAD >commit-id-Z &&
1889         test_commit Y &&
1890         git checkout -b topic2 master &&
1891         test_commit W &&
1892         git merge topic1 &&
1893         test_commit X &&
1894         test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1895         test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1896         git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1897         grep "^base-commit:" patch >actual &&
1898         echo "base-commit: $(cat commit-id-base)" >expect &&
1899         test_cmp expect actual
1900 '
1901
1902 test_expect_success 'format-patch --base=auto' '
1903         git checkout -b upstream master &&
1904         git checkout -b local upstream &&
1905         git branch --set-upstream-to=upstream &&
1906         test_commit N1 &&
1907         test_commit N2 &&
1908         git format-patch --stdout --base=auto -2 >patch &&
1909         grep "^base-commit:" patch >actual &&
1910         git rev-parse upstream >commit-id-base &&
1911         echo "base-commit: $(cat commit-id-base)" >expect &&
1912         test_cmp expect actual
1913 '
1914
1915 test_expect_success 'format-patch errors out when history involves criss-cross' '
1916         # setup criss-cross history
1917         #
1918         #   B---M1---D
1919         #  / \ /
1920         # A   X
1921         #  \ / \
1922         #   C---M2---E
1923         #
1924         git checkout master &&
1925         test_commit A &&
1926         git checkout -b xb master &&
1927         test_commit B &&
1928         git checkout -b xc master &&
1929         test_commit C &&
1930         git checkout -b xbc xb -- &&
1931         git merge xc &&
1932         git checkout -b xcb xc -- &&
1933         git branch --set-upstream-to=xbc &&
1934         git merge xb &&
1935         git checkout xbc &&
1936         test_commit D &&
1937         git checkout xcb &&
1938         test_commit E &&
1939         test_must_fail  git format-patch --base=auto -1
1940 '
1941
1942 test_expect_success 'format-patch format.useAutoBaseoption' '
1943         test_when_finished "git config --unset format.useAutoBase" &&
1944         git checkout local &&
1945         git config format.useAutoBase true &&
1946         git format-patch --stdout -1 >patch &&
1947         grep "^base-commit:" patch >actual &&
1948         git rev-parse upstream >commit-id-base &&
1949         echo "base-commit: $(cat commit-id-base)" >expect &&
1950         test_cmp expect actual
1951 '
1952
1953 test_expect_success 'format-patch --base overrides format.useAutoBase' '
1954         test_when_finished "git config --unset format.useAutoBase" &&
1955         git config format.useAutoBase true &&
1956         git format-patch --stdout --base=HEAD~1 -1 >patch &&
1957         grep "^base-commit:" patch >actual &&
1958         git rev-parse HEAD~1 >commit-id-base &&
1959         echo "base-commit: $(cat commit-id-base)" >expect &&
1960         test_cmp expect actual
1961 '
1962
1963 test_expect_success 'format-patch --base with --attach' '
1964         git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
1965         sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
1966                 patch >actual &&
1967         test_write_lines 1 2 >expect &&
1968         test_cmp expect actual
1969 '
1970 test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
1971         test_when_finished "rm -fr patches" &&
1972         git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
1973         ! egrep "^--+mimemime" patches/0000*.patch &&
1974         egrep "^--+mimemime$" patches/0001*.patch >output &&
1975         test_line_count = 2 output &&
1976         egrep "^--+mimemime--$" patches/0001*.patch >output &&
1977         test_line_count = 1 output
1978 '
1979
1980 test_expect_success 'format-patch --pretty=mboxrd' '
1981         sp=" " &&
1982         cat >msg <<-INPUT_END &&
1983         mboxrd should escape the body
1984
1985         From could trip up a loose mbox parser
1986         >From extra escape for reversibility
1987         >>From extra escape for reversibility 2
1988         from lower case not escaped
1989         Fromm bad speling not escaped
1990          From with leading space not escaped
1991
1992         F
1993         From
1994         From$sp
1995         From    $sp
1996         From    $sp
1997         INPUT_END
1998
1999         cat >expect <<-INPUT_END &&
2000         >From could trip up a loose mbox parser
2001         >>From extra escape for reversibility
2002         >>>From extra escape for reversibility 2
2003         from lower case not escaped
2004         Fromm bad speling not escaped
2005          From with leading space not escaped
2006
2007         F
2008         From
2009         From
2010         From
2011         From
2012         INPUT_END
2013
2014         C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
2015         git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
2016         git grep -h --no-index -A11 \
2017                 "^>From could trip up a loose mbox parser" patch >actual &&
2018         test_cmp expect actual
2019 '
2020
2021 test_expect_success 'interdiff: setup' '
2022         git checkout -b boop master &&
2023         test_commit fnorp blorp &&
2024         test_commit fleep blorp
2025 '
2026
2027 test_expect_success 'interdiff: cover-letter' '
2028         sed "y/q/ /" >expect <<-\EOF &&
2029         +fleep
2030         --q
2031         EOF
2032         git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
2033         test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch &&
2034         test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch &&
2035         sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual &&
2036         test_cmp expect actual
2037 '
2038
2039 test_expect_success 'interdiff: reroll-count' '
2040         git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2041         test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2042 '
2043
2044 test_expect_success 'interdiff: solo-patch' '
2045         cat >expect <<-\EOF &&
2046           +fleep
2047
2048         EOF
2049         git format-patch --interdiff=boop~2 -1 boop &&
2050         test_i18ngrep "^Interdiff:$" 0001-fleep.patch &&
2051         sed "1,/^  @@ /d; /^$/q" 0001-fleep.patch >actual &&
2052         test_cmp expect actual
2053 '
2054
2055 test_done