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