execv_dashed_external: stop exiting with negative code
[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
13         for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
14         cat file >elif &&
15         git add file elif &&
16         test_tick &&
17         git commit -m Initial &&
18         git checkout -b side &&
19
20         for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
21         test_chmod +x elif &&
22         test_tick &&
23         git commit -m "Side changes #1" &&
24
25         for i in D E F; do echo "$i"; done >>file &&
26         git update-index file &&
27         test_tick &&
28         git commit -m "Side changes #2" &&
29         git tag C2 &&
30
31         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
32         git update-index file &&
33         test_tick &&
34         git commit -m "Side changes #3 with \\n backslash-n in it." &&
35
36         git checkout master &&
37         git diff-tree -p C2 | git apply --index &&
38         test_tick &&
39         git commit -m "Master accepts moral equivalent of #2"
40
41 '
42
43 test_expect_success "format-patch --ignore-if-in-upstream" '
44
45         git format-patch --stdout master..side >patch0 &&
46         cnt=$(grep "^From " patch0 | wc -l) &&
47         test $cnt = 3
48
49 '
50
51 test_expect_success "format-patch --ignore-if-in-upstream" '
52
53         git format-patch --stdout \
54                 --ignore-if-in-upstream master..side >patch1 &&
55         cnt=$(grep "^From " patch1 | wc -l) &&
56         test $cnt = 2
57
58 '
59
60 test_expect_success "format-patch --ignore-if-in-upstream handles tags" '
61         git tag -a v1 -m tag side &&
62         git tag -a v2 -m tag master &&
63         git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
64         cnt=$(grep "^From " patch1 | wc -l) &&
65         test $cnt = 2
66 '
67
68 test_expect_success "format-patch doesn't consider merge commits" '
69
70         git checkout -b slave master &&
71         echo "Another line" >>file &&
72         test_tick &&
73         git commit -am "Slave change #1" &&
74         echo "Yet another line" >>file &&
75         test_tick &&
76         git commit -am "Slave change #2" &&
77         git checkout -b merger master &&
78         test_tick &&
79         git merge --no-ff slave &&
80         cnt=$(git format-patch -3 --stdout | grep "^From " | wc -l) &&
81         test $cnt = 3
82 '
83
84 test_expect_success "format-patch result applies" '
85
86         git checkout -b rebuild-0 master &&
87         git am -3 patch0 &&
88         cnt=$(git rev-list master.. | wc -l) &&
89         test $cnt = 2
90 '
91
92 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
93
94         git checkout -b rebuild-1 master &&
95         git am -3 patch1 &&
96         cnt=$(git rev-list master.. | wc -l) &&
97         test $cnt = 2
98 '
99
100 test_expect_success 'commit did not screw up the log message' '
101
102         git cat-file commit side | grep "^Side .* with .* backslash-n"
103
104 '
105
106 test_expect_success 'format-patch did not screw up the log message' '
107
108         grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
109         grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
110
111 '
112
113 test_expect_success 'replay did not screw up the log message' '
114
115         git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
116
117 '
118
119 test_expect_success 'extra headers' '
120
121         git config format.headers "To: R E Cipient <rcipient@example.com>
122 " &&
123         git config --add format.headers "Cc: S E Cipient <scipient@example.com>
124 " &&
125         git format-patch --stdout master..side > patch2 &&
126         sed -e "/^\$/q" patch2 > hdrs2 &&
127         grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
128         grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
129
130 '
131
132 test_expect_success 'extra headers without newlines' '
133
134         git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
135         git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
136         git format-patch --stdout master..side >patch3 &&
137         sed -e "/^\$/q" patch3 > hdrs3 &&
138         grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
139         grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
140
141 '
142
143 test_expect_success 'extra headers with multiple To:s' '
144
145         git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
146         git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
147         git format-patch --stdout master..side > patch4 &&
148         sed -e "/^\$/q" patch4 > hdrs4 &&
149         grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
150         grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
151 '
152
153 test_expect_success 'additional command line cc (ascii)' '
154
155         git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
156         git format-patch --cc="S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
157         grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
158         grep "^ *S E Cipient <scipient@example.com>\$" patch5
159 '
160
161 test_expect_failure 'additional command line cc (rfc822)' '
162
163         git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
164         git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
165         grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
166         grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" patch5
167 '
168
169 test_expect_success 'command line headers' '
170
171         git config --unset-all format.headers &&
172         git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
173         grep "^Cc: R E Cipient <rcipient@example.com>\$" patch6
174 '
175
176 test_expect_success 'configuration headers and command line headers' '
177
178         git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
179         git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
180         grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch7 &&
181         grep "^ *S E Cipient <scipient@example.com>\$" patch7
182 '
183
184 test_expect_success 'command line To: header (ascii)' '
185
186         git config --unset-all format.headers &&
187         git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
188         grep "^To: R E Cipient <rcipient@example.com>\$" patch8
189 '
190
191 test_expect_failure 'command line To: header (rfc822)' '
192
193         git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
194         grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch8
195 '
196
197 test_expect_failure 'command line To: header (rfc2047)' '
198
199         git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
200         grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch8
201 '
202
203 test_expect_success 'configuration To: header (ascii)' '
204
205         git config format.to "R E Cipient <rcipient@example.com>" &&
206         git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
207         grep "^To: R E Cipient <rcipient@example.com>\$" patch9
208 '
209
210 test_expect_failure 'configuration To: header (rfc822)' '
211
212         git config format.to "R. E. Cipient <rcipient@example.com>" &&
213         git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
214         grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch9
215 '
216
217 test_expect_failure 'configuration To: header (rfc2047)' '
218
219         git config format.to "R Ä Cipient <rcipient@example.com>" &&
220         git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
221         grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch9
222 '
223
224 # check_patch <patch>: Verify that <patch> looks like a half-sane
225 # patch email to avoid a false positive with !grep
226 check_patch () {
227         grep -e "^From:" "$1" &&
228         grep -e "^Date:" "$1" &&
229         grep -e "^Subject:" "$1"
230 }
231
232 test_expect_success 'format.from=false' '
233
234         git -c format.from=false format-patch --stdout master..side |
235         sed -e "/^\$/q" >patch &&
236         check_patch patch &&
237         ! grep "^From: C O Mitter <committer@example.com>\$" patch
238 '
239
240 test_expect_success 'format.from=true' '
241
242         git -c format.from=true format-patch --stdout master..side |
243         sed -e "/^\$/q" >patch &&
244         check_patch patch &&
245         grep "^From: C O Mitter <committer@example.com>\$" patch
246 '
247
248 test_expect_success 'format.from with address' '
249
250         git -c format.from="F R Om <from@example.com>" format-patch --stdout master..side |
251         sed -e "/^\$/q" >patch &&
252         check_patch patch &&
253         grep "^From: F R Om <from@example.com>\$" patch
254 '
255
256 test_expect_success '--no-from overrides format.from' '
257
258         git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout master..side |
259         sed -e "/^\$/q" >patch &&
260         check_patch patch &&
261         ! grep "^From: F R Om <from@example.com>\$" patch
262 '
263
264 test_expect_success '--from overrides format.from' '
265
266         git -c format.from="F R Om <from@example.com>" format-patch --from --stdout master..side |
267         sed -e "/^\$/q" >patch &&
268         check_patch patch &&
269         ! grep "^From: F R Om <from@example.com>\$" patch
270 '
271
272 test_expect_success '--no-to overrides config.to' '
273
274         git config --replace-all format.to \
275                 "R E Cipient <rcipient@example.com>" &&
276         git format-patch --no-to --stdout master..side |
277         sed -e "/^\$/q" >patch10 &&
278         check_patch patch10 &&
279         ! grep "^To: R E Cipient <rcipient@example.com>\$" patch10
280 '
281
282 test_expect_success '--no-to and --to replaces config.to' '
283
284         git config --replace-all format.to \
285                 "Someone <someone@out.there>" &&
286         git format-patch --no-to --to="Someone Else <else@out.there>" \
287                 --stdout master..side |
288         sed -e "/^\$/q" >patch11 &&
289         check_patch patch11 &&
290         ! grep "^To: Someone <someone@out.there>\$" patch11 &&
291         grep "^To: Someone Else <else@out.there>\$" patch11
292 '
293
294 test_expect_success '--no-cc overrides config.cc' '
295
296         git config --replace-all format.cc \
297                 "C E Cipient <rcipient@example.com>" &&
298         git format-patch --no-cc --stdout master..side |
299         sed -e "/^\$/q" >patch12 &&
300         check_patch patch12 &&
301         ! grep "^Cc: C E Cipient <rcipient@example.com>\$" patch12
302 '
303
304 test_expect_success '--no-add-header overrides config.headers' '
305
306         git config --replace-all format.headers \
307                 "Header1: B E Cipient <rcipient@example.com>" &&
308         git format-patch --no-add-header --stdout master..side |
309         sed -e "/^\$/q" >patch13 &&
310         check_patch patch13 &&
311         ! grep "^Header1: B E Cipient <rcipient@example.com>\$" patch13
312 '
313
314 test_expect_success 'multiple files' '
315
316         rm -rf patches/ &&
317         git checkout side &&
318         git format-patch -o patches/ master &&
319         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
320 '
321
322 test_expect_success 'reroll count' '
323         rm -fr patches &&
324         git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
325         ! grep -v "^patches/v4-000[0-3]-" list &&
326         sed -n -e "/^Subject: /p" $(cat list) >subjects &&
327         ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
328 '
329
330 test_expect_success 'reroll count (-v)' '
331         rm -fr patches &&
332         git format-patch -o patches --cover-letter -v4 master..side >list &&
333         ! grep -v "^patches/v4-000[0-3]-" list &&
334         sed -n -e "/^Subject: /p" $(cat list) >subjects &&
335         ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
336 '
337
338 check_threading () {
339         expect="$1" &&
340         shift &&
341         (git format-patch --stdout "$@"; echo $? > status.out) |
342         # Prints everything between the Message-ID and In-Reply-To,
343         # and replaces all Message-ID-lookalikes by a sequence number
344         perl -ne '
345                 if (/^(message-id|references|in-reply-to)/i) {
346                         $printing = 1;
347                 } elsif (/^\S/) {
348                         $printing = 0;
349                 }
350                 if ($printing) {
351                         $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
352                         for $k (keys %h) {s/$k/$h{$k}/};
353                         print;
354                 }
355                 print "---\n" if /^From /i;
356         ' > actual &&
357         test 0 = "$(cat status.out)" &&
358         test_cmp "$expect" actual
359 }
360
361 cat >> expect.no-threading <<EOF
362 ---
363 ---
364 ---
365 EOF
366
367 test_expect_success 'no threading' '
368         git checkout side &&
369         check_threading expect.no-threading master
370 '
371
372 cat > expect.thread <<EOF
373 ---
374 Message-Id: <0>
375 ---
376 Message-Id: <1>
377 In-Reply-To: <0>
378 References: <0>
379 ---
380 Message-Id: <2>
381 In-Reply-To: <0>
382 References: <0>
383 EOF
384
385 test_expect_success 'thread' '
386         check_threading expect.thread --thread master
387 '
388
389 cat > expect.in-reply-to <<EOF
390 ---
391 Message-Id: <0>
392 In-Reply-To: <1>
393 References: <1>
394 ---
395 Message-Id: <2>
396 In-Reply-To: <1>
397 References: <1>
398 ---
399 Message-Id: <3>
400 In-Reply-To: <1>
401 References: <1>
402 EOF
403
404 test_expect_success 'thread in-reply-to' '
405         check_threading expect.in-reply-to --in-reply-to="<test.message>" \
406                 --thread master
407 '
408
409 cat > expect.cover-letter <<EOF
410 ---
411 Message-Id: <0>
412 ---
413 Message-Id: <1>
414 In-Reply-To: <0>
415 References: <0>
416 ---
417 Message-Id: <2>
418 In-Reply-To: <0>
419 References: <0>
420 ---
421 Message-Id: <3>
422 In-Reply-To: <0>
423 References: <0>
424 EOF
425
426 test_expect_success 'thread cover-letter' '
427         check_threading expect.cover-letter --cover-letter --thread master
428 '
429
430 cat > expect.cl-irt <<EOF
431 ---
432 Message-Id: <0>
433 In-Reply-To: <1>
434 References: <1>
435 ---
436 Message-Id: <2>
437 In-Reply-To: <0>
438 References: <1>
439         <0>
440 ---
441 Message-Id: <3>
442 In-Reply-To: <0>
443 References: <1>
444         <0>
445 ---
446 Message-Id: <4>
447 In-Reply-To: <0>
448 References: <1>
449         <0>
450 EOF
451
452 test_expect_success 'thread cover-letter in-reply-to' '
453         check_threading expect.cl-irt --cover-letter \
454                 --in-reply-to="<test.message>" --thread master
455 '
456
457 test_expect_success 'thread explicit shallow' '
458         check_threading expect.cl-irt --cover-letter \
459                 --in-reply-to="<test.message>" --thread=shallow master
460 '
461
462 cat > expect.deep <<EOF
463 ---
464 Message-Id: <0>
465 ---
466 Message-Id: <1>
467 In-Reply-To: <0>
468 References: <0>
469 ---
470 Message-Id: <2>
471 In-Reply-To: <1>
472 References: <0>
473         <1>
474 EOF
475
476 test_expect_success 'thread deep' '
477         check_threading expect.deep --thread=deep master
478 '
479
480 cat > expect.deep-irt <<EOF
481 ---
482 Message-Id: <0>
483 In-Reply-To: <1>
484 References: <1>
485 ---
486 Message-Id: <2>
487 In-Reply-To: <0>
488 References: <1>
489         <0>
490 ---
491 Message-Id: <3>
492 In-Reply-To: <2>
493 References: <1>
494         <0>
495         <2>
496 EOF
497
498 test_expect_success 'thread deep in-reply-to' '
499         check_threading expect.deep-irt  --thread=deep \
500                 --in-reply-to="<test.message>" master
501 '
502
503 cat > expect.deep-cl <<EOF
504 ---
505 Message-Id: <0>
506 ---
507 Message-Id: <1>
508 In-Reply-To: <0>
509 References: <0>
510 ---
511 Message-Id: <2>
512 In-Reply-To: <1>
513 References: <0>
514         <1>
515 ---
516 Message-Id: <3>
517 In-Reply-To: <2>
518 References: <0>
519         <1>
520         <2>
521 EOF
522
523 test_expect_success 'thread deep cover-letter' '
524         check_threading expect.deep-cl --cover-letter --thread=deep master
525 '
526
527 cat > expect.deep-cl-irt <<EOF
528 ---
529 Message-Id: <0>
530 In-Reply-To: <1>
531 References: <1>
532 ---
533 Message-Id: <2>
534 In-Reply-To: <0>
535 References: <1>
536         <0>
537 ---
538 Message-Id: <3>
539 In-Reply-To: <2>
540 References: <1>
541         <0>
542         <2>
543 ---
544 Message-Id: <4>
545 In-Reply-To: <3>
546 References: <1>
547         <0>
548         <2>
549         <3>
550 EOF
551
552 test_expect_success 'thread deep cover-letter in-reply-to' '
553         check_threading expect.deep-cl-irt --cover-letter \
554                 --in-reply-to="<test.message>" --thread=deep master
555 '
556
557 test_expect_success 'thread via config' '
558         test_config format.thread true &&
559         check_threading expect.thread master
560 '
561
562 test_expect_success 'thread deep via config' '
563         test_config format.thread deep &&
564         check_threading expect.deep master
565 '
566
567 test_expect_success 'thread config + override' '
568         test_config format.thread deep &&
569         check_threading expect.thread --thread master
570 '
571
572 test_expect_success 'thread config + --no-thread' '
573         test_config format.thread deep &&
574         check_threading expect.no-threading --no-thread master
575 '
576
577 test_expect_success 'excessive subject' '
578
579         rm -rf patches/ &&
580         git checkout side &&
581         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
582         git update-index file &&
583         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." &&
584         git format-patch -o patches/ master..side &&
585         ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
586 '
587
588 test_expect_success 'cover-letter inherits diff options' '
589
590         git mv file foo &&
591         git commit -m foo &&
592         git format-patch --no-renames --cover-letter -1 &&
593         check_patch 0000-cover-letter.patch &&
594         ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
595         git format-patch --cover-letter -1 -M &&
596         grep "file => foo .* 0 *\$" 0000-cover-letter.patch
597
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
612         git format-patch --cover-letter -2 &&
613         sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
614         test_cmp expect output
615
616 '
617
618 cat > expect << EOF
619 index 40f36c6..2dc5c23 100644
620 --- a/file
621 +++ b/file
622 @@ -13,4 +13,20 @@ C
623  10
624  D
625  E
626  F
627 +5
628 EOF
629
630 test_expect_success 'format-patch respects -U' '
631
632         git format-patch -U4 -2 &&
633         sed -e "1,/^diff/d" -e "/^+5/q" \
634                 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
635                 >output &&
636         test_cmp expect output
637
638 '
639
640 cat > expect << EOF
641
642 diff --git a/file b/file
643 index 40f36c6..2dc5c23 100644
644 --- a/file
645 +++ b/file
646 @@ -14,3 +14,19 @@ C
647  D
648  E
649  F
650 +5
651 EOF
652
653 test_expect_success 'format-patch -p suppresses stat' '
654
655         git format-patch -p -2 &&
656         sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
657         test_cmp expect output
658
659 '
660
661 test_expect_success 'format-patch from a subdirectory (1)' '
662         filename=$(
663                 rm -rf sub &&
664                 mkdir -p sub/dir &&
665                 cd sub/dir &&
666                 git format-patch -1
667         ) &&
668         case "$filename" in
669         0*)
670                 ;; # ok
671         *)
672                 echo "Oops? $filename"
673                 false
674                 ;;
675         esac &&
676         test -f "$filename"
677 '
678
679 test_expect_success 'format-patch from a subdirectory (2)' '
680         filename=$(
681                 rm -rf sub &&
682                 mkdir -p sub/dir &&
683                 cd sub/dir &&
684                 git format-patch -1 -o ..
685         ) &&
686         case "$filename" in
687         ../0*)
688                 ;; # ok
689         *)
690                 echo "Oops? $filename"
691                 false
692                 ;;
693         esac &&
694         basename=$(expr "$filename" : ".*/\(.*\)") &&
695         test -f "sub/$basename"
696 '
697
698 test_expect_success 'format-patch from a subdirectory (3)' '
699         rm -f 0* &&
700         filename=$(
701                 rm -rf sub &&
702                 mkdir -p sub/dir &&
703                 cd sub/dir &&
704                 git format-patch -1 -o "$TRASH_DIRECTORY"
705         ) &&
706         basename=$(expr "$filename" : ".*/\(.*\)") &&
707         test -f "$basename"
708 '
709
710 test_expect_success 'format-patch --in-reply-to' '
711         git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
712         grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
713         grep "^References: <baz@foo.bar>" patch8
714 '
715
716 test_expect_success 'format-patch --signoff' '
717         git format-patch -1 --signoff --stdout >out &&
718         grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
719 '
720
721 test_expect_success 'format-patch --notes --signoff' '
722         git notes --ref test add -m "test message" HEAD &&
723         git format-patch -1 --signoff --stdout --notes=test >out &&
724         # Three dashes must come after S-o-b
725         ! sed "/^Signed-off-by: /q" out | grep "test message" &&
726         sed "1,/^Signed-off-by: /d" out | grep "test message" &&
727         # Notes message must come after three dashes
728         ! sed "/^---$/q" out | grep "test message" &&
729         sed "1,/^---$/d" out | grep "test message"
730 '
731
732 echo "fatal: --name-only does not make sense" > expect.name-only
733 echo "fatal: --name-status does not make sense" > expect.name-status
734 echo "fatal: --check does not make sense" > expect.check
735
736 test_expect_success 'options no longer allowed for format-patch' '
737         test_must_fail git format-patch --name-only 2> output &&
738         test_i18ncmp expect.name-only output &&
739         test_must_fail git format-patch --name-status 2> output &&
740         test_i18ncmp expect.name-status output &&
741         test_must_fail git format-patch --check 2> output &&
742         test_i18ncmp expect.check output'
743
744 test_expect_success 'format-patch --numstat should produce a patch' '
745         git format-patch --numstat --stdout master..side > output &&
746         test 5 = $(grep "^diff --git a/" output | wc -l)'
747
748 test_expect_success 'format-patch -- <path>' '
749         git format-patch master..side -- file 2>error &&
750         ! grep "Use .--" error
751 '
752
753 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
754         git format-patch --ignore-if-in-upstream HEAD
755 '
756
757 git_version="$(git --version | sed "s/.* //")"
758
759 signature() {
760         printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
761 }
762
763 test_expect_success 'format-patch default signature' '
764         git format-patch --stdout -1 | tail -n 3 >output &&
765         signature >expect &&
766         test_cmp expect output
767 '
768
769 test_expect_success 'format-patch --signature' '
770         git format-patch --stdout --signature="my sig" -1 | tail -n 3 >output &&
771         signature "my sig" >expect &&
772         test_cmp expect output
773 '
774
775 test_expect_success 'format-patch with format.signature config' '
776         git config format.signature "config sig" &&
777         git format-patch --stdout -1 >output &&
778         grep "config sig" output
779 '
780
781 test_expect_success 'format-patch --signature overrides format.signature' '
782         git config format.signature "config sig" &&
783         git format-patch --stdout --signature="overrides" -1 >output &&
784         ! grep "config sig" output &&
785         grep "overrides" output
786 '
787
788 test_expect_success 'format-patch --no-signature ignores format.signature' '
789         git config format.signature "config sig" &&
790         git format-patch --stdout --signature="my sig" --no-signature \
791                 -1 >output &&
792         check_patch output &&
793         ! grep "config sig" output &&
794         ! grep "my sig" output &&
795         ! grep "^-- \$" output
796 '
797
798 test_expect_success 'format-patch --signature --cover-letter' '
799         git config --unset-all format.signature &&
800         git format-patch --stdout --signature="my sig" --cover-letter \
801                 -1 >output &&
802         grep "my sig" output &&
803         test 2 = $(grep "my sig" output | wc -l)
804 '
805
806 test_expect_success 'format.signature="" suppresses signatures' '
807         git config format.signature "" &&
808         git format-patch --stdout -1 >output &&
809         check_patch output &&
810         ! grep "^-- \$" output
811 '
812
813 test_expect_success 'format-patch --no-signature suppresses signatures' '
814         git config --unset-all format.signature &&
815         git format-patch --stdout --no-signature -1 >output &&
816         check_patch output &&
817         ! grep "^-- \$" output
818 '
819
820 test_expect_success 'format-patch --signature="" suppresses signatures' '
821         git format-patch --stdout --signature="" -1 >output &&
822         check_patch output &&
823         ! grep "^-- \$" output
824 '
825
826 test_expect_success 'prepare mail-signature input' '
827         cat >mail-signature <<-\EOF
828
829         Test User <test.email@kernel.org>
830         http://git.kernel.org/cgit/git/git.git
831
832         git.kernel.org/?p=git/git.git;a=summary
833
834         EOF
835 '
836
837 test_expect_success '--signature-file=file works' '
838         git format-patch --stdout --signature-file=mail-signature -1 >output &&
839         check_patch output &&
840         sed -e "1,/^-- \$/d" <output >actual &&
841         {
842                 cat mail-signature && echo
843         } >expect &&
844         test_cmp expect actual
845 '
846
847 test_expect_success 'format.signaturefile works' '
848         test_config format.signaturefile mail-signature &&
849         git format-patch --stdout -1 >output &&
850         check_patch output &&
851         sed -e "1,/^-- \$/d" <output >actual &&
852         {
853                 cat mail-signature && echo
854         } >expect &&
855         test_cmp expect actual
856 '
857
858 test_expect_success '--no-signature suppresses format.signaturefile ' '
859         test_config format.signaturefile mail-signature &&
860         git format-patch --stdout --no-signature -1 >output &&
861         check_patch output &&
862         ! grep "^-- \$" output
863 '
864
865 test_expect_success '--signature-file overrides format.signaturefile' '
866         cat >other-mail-signature <<-\EOF &&
867         Use this other signature instead of mail-signature.
868         EOF
869         test_config format.signaturefile mail-signature &&
870         git format-patch --stdout \
871                         --signature-file=other-mail-signature -1 >output &&
872         check_patch output &&
873         sed -e "1,/^-- \$/d" <output >actual &&
874         {
875                 cat other-mail-signature && echo
876         } >expect &&
877         test_cmp expect actual
878 '
879
880 test_expect_success '--signature overrides format.signaturefile' '
881         test_config format.signaturefile mail-signature &&
882         git format-patch --stdout --signature="my sig" -1 >output &&
883         check_patch output &&
884         grep "my sig" output
885 '
886
887 test_expect_success TTY 'format-patch --stdout paginates' '
888         rm -f pager_used &&
889         test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
890         test_path_is_file pager_used
891 '
892
893  test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
894         rm -f pager_used &&
895         test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
896         test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
897         test_path_is_missing pager_used &&
898         test_path_is_missing .git/pager_used
899 '
900
901 test_expect_success 'format-patch handles multi-line subjects' '
902         rm -rf patches/ &&
903         echo content >>file &&
904         for i in one two three; do echo $i; done >msg &&
905         git add file &&
906         git commit -F msg &&
907         git format-patch -o patches -1 &&
908         grep ^Subject: patches/0001-one.patch >actual &&
909         echo "Subject: [PATCH] one two three" >expect &&
910         test_cmp expect actual
911 '
912
913 test_expect_success 'format-patch handles multi-line encoded subjects' '
914         rm -rf patches/ &&
915         echo content >>file &&
916         for i in en två tre; do echo $i; done >msg &&
917         git add file &&
918         git commit -F msg &&
919         git format-patch -o patches -1 &&
920         grep ^Subject: patches/0001-en.patch >actual &&
921         echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
922         test_cmp expect actual
923 '
924
925 M8="foo bar "
926 M64=$M8$M8$M8$M8$M8$M8$M8$M8
927 M512=$M64$M64$M64$M64$M64$M64$M64$M64
928 cat >expect <<'EOF'
929 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
930  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
931  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
932  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
933  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
934  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
935  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
936 EOF
937 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
938         echo content >>file &&
939         git add file &&
940         git commit -m "$M512" &&
941         git format-patch --stdout -1 >patch &&
942         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
943         test_cmp expect subject
944 '
945
946 M8="föö bar "
947 M64=$M8$M8$M8$M8$M8$M8$M8$M8
948 M512=$M64$M64$M64$M64$M64$M64$M64$M64
949 cat >expect <<'EOF'
950 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
951  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
952  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
953  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
954  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
955  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
956  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
957  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
958  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
959  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
960  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
961  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
962  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
963  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
964  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
965  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
966  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
967  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
968  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
969  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
970  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
971  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
972  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
973  =?UTF-8?q?bar?=
974 EOF
975 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
976         rm -rf patches/ &&
977         echo content >>file &&
978         git add file &&
979         git commit -m "$M512" &&
980         git format-patch --stdout -1 >patch &&
981         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
982         test_cmp expect subject
983 '
984
985 check_author() {
986         echo content >>file &&
987         git add file &&
988         GIT_AUTHOR_NAME=$1 git commit -m author-check &&
989         git format-patch --stdout -1 >patch &&
990         sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
991         test_cmp expect actual
992 }
993
994 cat >expect <<'EOF'
995 From: "Foo B. Bar" <author@example.com>
996 EOF
997 test_expect_success 'format-patch quotes dot in from-headers' '
998         check_author "Foo B. Bar"
999 '
1000
1001 cat >expect <<'EOF'
1002 From: "Foo \"The Baz\" Bar" <author@example.com>
1003 EOF
1004 test_expect_success 'format-patch quotes double-quote in from-headers' '
1005         check_author "Foo \"The Baz\" Bar"
1006 '
1007
1008 cat >expect <<'EOF'
1009 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1010 EOF
1011 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1012         check_author "Föo Bar"
1013 '
1014
1015 cat >expect <<'EOF'
1016 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1017 EOF
1018 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1019         check_author "Föo B. Bar"
1020 '
1021
1022 cat >expect <<EOF
1023 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1024  <author@example.com>
1025 EOF
1026 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1027         check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1028 '
1029
1030 cat >expect <<'EOF'
1031 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1032  Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1033  Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1034 EOF
1035 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1036         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"
1037 '
1038
1039 cat >expect <<'EOF'
1040 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1041  Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1042  Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1043 EOF
1044 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1045         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"
1046 '
1047
1048 cat >expect <<'EOF'
1049 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1050  =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1051  =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1052  =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1053  =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1054 EOF
1055 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1056         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"
1057 '
1058
1059 cat >expect <<'EOF'
1060 Subject: header with . in it
1061 EOF
1062 test_expect_success 'subject lines do not have 822 atom-quoting' '
1063         echo content >>file &&
1064         git add file &&
1065         git commit -m "header with . in it" &&
1066         git format-patch -k -1 --stdout >patch &&
1067         grep ^Subject: patch >actual &&
1068         test_cmp expect actual
1069 '
1070
1071 cat >expect <<'EOF'
1072 Subject: [PREFIX 1/1] header with . in it
1073 EOF
1074 test_expect_success 'subject prefixes have space prepended' '
1075         git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1076         grep ^Subject: patch >actual &&
1077         test_cmp expect actual
1078 '
1079
1080 cat >expect <<'EOF'
1081 Subject: [1/1] header with . in it
1082 EOF
1083 test_expect_success 'empty subject prefix does not have extra space' '
1084         git format-patch -n -1 --stdout --subject-prefix= >patch &&
1085         grep ^Subject: patch >actual &&
1086         test_cmp expect actual
1087 '
1088
1089 test_expect_success '--rfc' '
1090         cat >expect <<-\EOF &&
1091         Subject: [RFC PATCH 1/1] header with . in it
1092         EOF
1093         git format-patch -n -1 --stdout --rfc >patch &&
1094         grep ^Subject: patch >actual &&
1095         test_cmp expect actual
1096 '
1097
1098 test_expect_success '--from=ident notices bogus ident' '
1099         test_must_fail git format-patch -1 --stdout --from=foo >patch
1100 '
1101
1102 test_expect_success '--from=ident replaces author' '
1103         git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1104         cat >expect <<-\EOF &&
1105         From: Me <me@example.com>
1106
1107         From: A U Thor <author@example.com>
1108
1109         EOF
1110         sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1111         test_cmp expect patch.head
1112 '
1113
1114 test_expect_success '--from uses committer ident' '
1115         git format-patch -1 --stdout --from >patch &&
1116         cat >expect <<-\EOF &&
1117         From: C O Mitter <committer@example.com>
1118
1119         From: A U Thor <author@example.com>
1120
1121         EOF
1122         sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1123         test_cmp expect patch.head
1124 '
1125
1126 test_expect_success '--from omits redundant in-body header' '
1127         git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1128         cat >expect <<-\EOF &&
1129         From: A U Thor <author@example.com>
1130
1131         EOF
1132         sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1133         test_cmp expect patch.head
1134 '
1135
1136 test_expect_success 'in-body headers trigger content encoding' '
1137         test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1138         test_when_finished "git reset --hard HEAD^" &&
1139         git format-patch -1 --stdout --from >patch &&
1140         cat >expect <<-\EOF &&
1141         From: C O Mitter <committer@example.com>
1142         Content-Type: text/plain; charset=UTF-8
1143
1144         From: éxötìc <author@example.com>
1145
1146         EOF
1147         sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1148         test_cmp expect patch.head
1149 '
1150
1151 append_signoff()
1152 {
1153         C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1154         git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1155         sed -n -e "1,/^---$/p" append_signoff.patch |
1156                 egrep -n "^Subject|Sign|^$"
1157 }
1158
1159 test_expect_success 'signoff: commit with no body' '
1160         append_signoff </dev/null >actual &&
1161         cat <<\EOF | sed "s/EOL$//" >expected &&
1162 4:Subject: [PATCH] EOL
1163 8:
1164 9:Signed-off-by: C O Mitter <committer@example.com>
1165 EOF
1166         test_cmp expected actual
1167 '
1168
1169 test_expect_success 'signoff: commit with only subject' '
1170         echo subject | append_signoff >actual &&
1171         cat >expected <<\EOF &&
1172 4:Subject: [PATCH] subject
1173 8:
1174 9:Signed-off-by: C O Mitter <committer@example.com>
1175 EOF
1176         test_cmp expected actual
1177 '
1178
1179 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1180         printf subject | append_signoff >actual &&
1181         cat >expected <<\EOF &&
1182 4:Subject: [PATCH] subject
1183 8:
1184 9:Signed-off-by: C O Mitter <committer@example.com>
1185 EOF
1186         test_cmp expected actual
1187 '
1188
1189 test_expect_success 'signoff: no existing signoffs' '
1190         append_signoff <<\EOF >actual &&
1191 subject
1192
1193 body
1194 EOF
1195         cat >expected <<\EOF &&
1196 4:Subject: [PATCH] subject
1197 8:
1198 10:
1199 11:Signed-off-by: C O Mitter <committer@example.com>
1200 EOF
1201         test_cmp expected actual
1202 '
1203
1204 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1205         printf "subject\n\nbody" | append_signoff >actual &&
1206         cat >expected <<\EOF &&
1207 4:Subject: [PATCH] subject
1208 8:
1209 10:
1210 11:Signed-off-by: C O Mitter <committer@example.com>
1211 EOF
1212         test_cmp expected actual
1213 '
1214
1215 test_expect_success 'signoff: some random signoff' '
1216         append_signoff <<\EOF >actual &&
1217 subject
1218
1219 body
1220
1221 Signed-off-by: my@house
1222 EOF
1223         cat >expected <<\EOF &&
1224 4:Subject: [PATCH] subject
1225 8:
1226 10:
1227 11:Signed-off-by: my@house
1228 12:Signed-off-by: C O Mitter <committer@example.com>
1229 EOF
1230         test_cmp expected actual
1231 '
1232
1233 test_expect_success 'signoff: misc conforming footer elements' '
1234         append_signoff <<\EOF >actual &&
1235 subject
1236
1237 body
1238
1239 Signed-off-by: my@house
1240 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1241 Tested-by: Some One <someone@example.com>
1242 Bug: 1234
1243 EOF
1244         cat >expected <<\EOF &&
1245 4:Subject: [PATCH] subject
1246 8:
1247 10:
1248 11:Signed-off-by: my@house
1249 15:Signed-off-by: C O Mitter <committer@example.com>
1250 EOF
1251         test_cmp expected actual
1252 '
1253
1254 test_expect_success 'signoff: some random signoff-alike' '
1255         append_signoff <<\EOF >actual &&
1256 subject
1257
1258 body
1259 Fooled-by-me: my@house
1260 EOF
1261         cat >expected <<\EOF &&
1262 4:Subject: [PATCH] subject
1263 8:
1264 11:
1265 12:Signed-off-by: C O Mitter <committer@example.com>
1266 EOF
1267         test_cmp expected actual
1268 '
1269
1270 test_expect_success 'signoff: not really a signoff' '
1271         append_signoff <<\EOF >actual &&
1272 subject
1273
1274 I want to mention about Signed-off-by: here.
1275 EOF
1276         cat >expected <<\EOF &&
1277 4:Subject: [PATCH] subject
1278 8:
1279 9:I want to mention about Signed-off-by: here.
1280 10:
1281 11:Signed-off-by: C O Mitter <committer@example.com>
1282 EOF
1283         test_cmp expected actual
1284 '
1285
1286 test_expect_success 'signoff: not really a signoff (2)' '
1287         append_signoff <<\EOF >actual &&
1288 subject
1289
1290 My unfortunate
1291 Signed-off-by: example happens to be wrapped here.
1292 EOF
1293         cat >expected <<\EOF &&
1294 4:Subject: [PATCH] subject
1295 8:
1296 10:Signed-off-by: example happens to be wrapped here.
1297 11:
1298 12:Signed-off-by: C O Mitter <committer@example.com>
1299 EOF
1300         test_cmp expected actual
1301 '
1302
1303 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1304         append_signoff <<\EOF >actual &&
1305 subject
1306
1307 Signed-off-by: my@house
1308 Signed-off-by: your@house
1309
1310 A lot of houses.
1311 EOF
1312         cat >expected <<\EOF &&
1313 4:Subject: [PATCH] subject
1314 8:
1315 9:Signed-off-by: my@house
1316 10:Signed-off-by: your@house
1317 11:
1318 13:
1319 14:Signed-off-by: C O Mitter <committer@example.com>
1320 EOF
1321         test_cmp expected actual
1322 '
1323
1324 test_expect_success 'signoff: the same signoff at the end' '
1325         append_signoff <<\EOF >actual &&
1326 subject
1327
1328 body
1329
1330 Signed-off-by: C O Mitter <committer@example.com>
1331 EOF
1332         cat >expected <<\EOF &&
1333 4:Subject: [PATCH] subject
1334 8:
1335 10:
1336 11:Signed-off-by: C O Mitter <committer@example.com>
1337 EOF
1338         test_cmp expected actual
1339 '
1340
1341 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1342         printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1343                 append_signoff >actual &&
1344         cat >expected <<\EOF &&
1345 4:Subject: [PATCH] subject
1346 8:
1347 9:Signed-off-by: C O Mitter <committer@example.com>
1348 EOF
1349         test_cmp expected actual
1350 '
1351
1352 test_expect_success 'signoff: the same signoff NOT at the end' '
1353         append_signoff <<\EOF >actual &&
1354 subject
1355
1356 body
1357
1358 Signed-off-by: C O Mitter <committer@example.com>
1359 Signed-off-by: my@house
1360 EOF
1361         cat >expected <<\EOF &&
1362 4:Subject: [PATCH] subject
1363 8:
1364 10:
1365 11:Signed-off-by: C O Mitter <committer@example.com>
1366 12:Signed-off-by: my@house
1367 EOF
1368         test_cmp expected actual
1369 '
1370
1371 test_expect_success 'signoff: detect garbage in non-conforming footer' '
1372         append_signoff <<\EOF >actual &&
1373 subject
1374
1375 body
1376
1377 Tested-by: my@house
1378 Some Trash
1379 Signed-off-by: C O Mitter <committer@example.com>
1380 EOF
1381         cat >expected <<\EOF &&
1382 4:Subject: [PATCH] subject
1383 8:
1384 10:
1385 13:Signed-off-by: C O Mitter <committer@example.com>
1386 14:
1387 15:Signed-off-by: C O Mitter <committer@example.com>
1388 EOF
1389         test_cmp expected actual
1390 '
1391
1392 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1393         append_signoff <<\EOF >actual &&
1394 subject
1395
1396 body
1397
1398 Reviewed-id: Noone
1399 Tested-by: my@house
1400 Change-id: Ideadbeef
1401 Signed-off-by: C O Mitter <committer@example.com>
1402 Bug: 1234
1403 EOF
1404         cat >expected <<\EOF &&
1405 4:Subject: [PATCH] subject
1406 8:
1407 10:
1408 14:Signed-off-by: C O Mitter <committer@example.com>
1409 EOF
1410         test_cmp expected actual
1411 '
1412
1413 test_expect_success 'format patch ignores color.ui' '
1414         test_unconfig color.ui &&
1415         git format-patch --stdout -1 >expect &&
1416         test_config color.ui always &&
1417         git format-patch --stdout -1 >actual &&
1418         test_cmp expect actual
1419 '
1420
1421 test_expect_success 'cover letter using branch description (1)' '
1422         git checkout rebuild-1 &&
1423         test_config branch.rebuild-1.description hello &&
1424         git format-patch --stdout --cover-letter master >actual &&
1425         grep hello actual >/dev/null
1426 '
1427
1428 test_expect_success 'cover letter using branch description (2)' '
1429         git checkout rebuild-1 &&
1430         test_config branch.rebuild-1.description hello &&
1431         git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1432         grep hello actual >/dev/null
1433 '
1434
1435 test_expect_success 'cover letter using branch description (3)' '
1436         git checkout rebuild-1 &&
1437         test_config branch.rebuild-1.description hello &&
1438         git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1439         grep hello actual >/dev/null
1440 '
1441
1442 test_expect_success 'cover letter using branch description (4)' '
1443         git checkout rebuild-1 &&
1444         test_config branch.rebuild-1.description hello &&
1445         git format-patch --stdout --cover-letter master.. >actual &&
1446         grep hello actual >/dev/null
1447 '
1448
1449 test_expect_success 'cover letter using branch description (5)' '
1450         git checkout rebuild-1 &&
1451         test_config branch.rebuild-1.description hello &&
1452         git format-patch --stdout --cover-letter -2 HEAD >actual &&
1453         grep hello actual >/dev/null
1454 '
1455
1456 test_expect_success 'cover letter using branch description (6)' '
1457         git checkout rebuild-1 &&
1458         test_config branch.rebuild-1.description hello &&
1459         git format-patch --stdout --cover-letter -2 >actual &&
1460         grep hello actual >/dev/null
1461 '
1462
1463 test_expect_success 'cover letter with nothing' '
1464         git format-patch --stdout --cover-letter >actual &&
1465         test_line_count = 0 actual
1466 '
1467
1468 test_expect_success 'cover letter auto' '
1469         mkdir -p tmp &&
1470         test_when_finished "rm -rf tmp;
1471                 git config --unset format.coverletter" &&
1472
1473         git config format.coverletter auto &&
1474         git format-patch -o tmp -1 >list &&
1475         test_line_count = 1 list &&
1476         git format-patch -o tmp -2 >list &&
1477         test_line_count = 3 list
1478 '
1479
1480 test_expect_success 'cover letter auto user override' '
1481         mkdir -p tmp &&
1482         test_when_finished "rm -rf tmp;
1483                 git config --unset format.coverletter" &&
1484
1485         git config format.coverletter auto &&
1486         git format-patch -o tmp --cover-letter -1 >list &&
1487         test_line_count = 2 list &&
1488         git format-patch -o tmp --cover-letter -2 >list &&
1489         test_line_count = 3 list &&
1490         git format-patch -o tmp --no-cover-letter -1 >list &&
1491         test_line_count = 1 list &&
1492         git format-patch -o tmp --no-cover-letter -2 >list &&
1493         test_line_count = 2 list
1494 '
1495
1496 test_expect_success 'format-patch --zero-commit' '
1497         git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1498         grep "^From " patch2 | sort | uniq >actual &&
1499         echo "From $_z40 Mon Sep 17 00:00:00 2001" >expect &&
1500         test_cmp expect actual
1501 '
1502
1503 test_expect_success 'From line has expected format' '
1504         git format-patch --stdout v2..v1 >patch2 &&
1505         grep "^From " patch2 >from &&
1506         grep "^From $_x40 Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1507         test_cmp from filtered
1508 '
1509
1510 test_expect_success 'format-patch format.outputDirectory option' '
1511         test_config format.outputDirectory patches &&
1512         rm -fr patches &&
1513         git format-patch master..side &&
1514         test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
1515 '
1516
1517 test_expect_success 'format-patch -o overrides format.outputDirectory' '
1518         test_config format.outputDirectory patches &&
1519         rm -fr patches patchset &&
1520         git format-patch master..side -o patchset &&
1521         test_path_is_missing patches &&
1522         test_path_is_dir patchset
1523 '
1524
1525 test_expect_success 'format-patch --base' '
1526         git checkout side &&
1527         git format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual &&
1528         echo >expected &&
1529         echo "base-commit: $(git rev-parse HEAD~3)" >>expected &&
1530         echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1531         echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1532         signature >> expected &&
1533         test_cmp expected actual
1534 '
1535
1536 test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1537         test_must_fail git format-patch --base=HEAD -2 &&
1538         test_must_fail git format-patch --base=HEAD~1 -2 &&
1539         git format-patch --stdout --base=HEAD~2 -2 >patch &&
1540         grep "^base-commit:" patch >actual &&
1541         echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
1542         test_cmp expected actual
1543 '
1544
1545 test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1546         # For history as below:
1547         #
1548         #    ---Q---P---Z---Y---*---X
1549         #        \             /
1550         #         ------------W
1551         #
1552         # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1553         git checkout -b topic1 master &&
1554         git rev-parse HEAD >commit-id-base &&
1555         test_commit P &&
1556         git rev-parse HEAD >commit-id-P &&
1557         test_commit Z &&
1558         git rev-parse HEAD >commit-id-Z &&
1559         test_commit Y &&
1560         git checkout -b topic2 master &&
1561         test_commit W &&
1562         git merge topic1 &&
1563         test_commit X &&
1564         test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1565         test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1566         git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1567         grep "^base-commit:" patch >actual &&
1568         echo "base-commit: $(cat commit-id-base)" >expected &&
1569         test_cmp expected actual
1570 '
1571
1572 test_expect_success 'format-patch --base=auto' '
1573         git checkout -b upstream master &&
1574         git checkout -b local upstream &&
1575         git branch --set-upstream-to=upstream &&
1576         test_commit N1 &&
1577         test_commit N2 &&
1578         git format-patch --stdout --base=auto -2 >patch &&
1579         grep "^base-commit:" patch >actual &&
1580         echo "base-commit: $(git rev-parse upstream)" >expected &&
1581         test_cmp expected actual
1582 '
1583
1584 test_expect_success 'format-patch errors out when history involves criss-cross' '
1585         # setup criss-cross history
1586         #
1587         #   B---M1---D
1588         #  / \ /
1589         # A   X
1590         #  \ / \
1591         #   C---M2---E
1592         #
1593         git checkout master &&
1594         test_commit A &&
1595         git checkout -b xb master &&
1596         test_commit B &&
1597         git checkout -b xc master &&
1598         test_commit C &&
1599         git checkout -b xbc xb -- &&
1600         git merge xc &&
1601         git checkout -b xcb xc -- &&
1602         git branch --set-upstream-to=xbc &&
1603         git merge xb &&
1604         git checkout xbc &&
1605         test_commit D &&
1606         git checkout xcb &&
1607         test_commit E &&
1608         test_must_fail  git format-patch --base=auto -1
1609 '
1610
1611 test_expect_success 'format-patch format.useAutoBaseoption' '
1612         test_when_finished "git config --unset format.useAutoBase" &&
1613         git checkout local &&
1614         git config format.useAutoBase true &&
1615         git format-patch --stdout -1 >patch &&
1616         grep "^base-commit:" patch >actual &&
1617         echo "base-commit: $(git rev-parse upstream)" >expected &&
1618         test_cmp expected actual
1619 '
1620
1621 test_expect_success 'format-patch --base overrides format.useAutoBase' '
1622         test_when_finished "git config --unset format.useAutoBase" &&
1623         git config format.useAutoBase true &&
1624         git format-patch --stdout --base=HEAD~1 -1 >patch &&
1625         grep "^base-commit:" patch >actual &&
1626         echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
1627         test_cmp expected actual
1628 '
1629
1630 test_expect_success 'format-patch --base with --attach' '
1631         git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
1632         sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
1633                 patch >actual &&
1634         test_write_lines 1 2 >expect &&
1635         test_cmp expect actual
1636 '
1637
1638 test_expect_success 'format-patch --pretty=mboxrd' '
1639         sp=" " &&
1640         cat >msg <<-INPUT_END &&
1641         mboxrd should escape the body
1642
1643         From could trip up a loose mbox parser
1644         >From extra escape for reversibility
1645         >>From extra escape for reversibility 2
1646         from lower case not escaped
1647         Fromm bad speling not escaped
1648          From with leading space not escaped
1649
1650         F
1651         From
1652         From$sp
1653         From    $sp
1654         From    $sp
1655         INPUT_END
1656
1657         cat >expect <<-INPUT_END &&
1658         >From could trip up a loose mbox parser
1659         >>From extra escape for reversibility
1660         >>>From extra escape for reversibility 2
1661         from lower case not escaped
1662         Fromm bad speling not escaped
1663          From with leading space not escaped
1664
1665         F
1666         From
1667         From
1668         From
1669         From
1670         INPUT_END
1671
1672         C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
1673         git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
1674         git grep -h --no-index -A11 \
1675                 "^>From could trip up a loose mbox parser" patch >actual &&
1676         test_cmp expect actual
1677 '
1678
1679 test_done