1#!/bin/sh
2#
3# Copyright (c) 2006 Junio C Hamano
4#
5
6test_description='various format-patch tests'
7
8. ./test-lib.sh
9. "$TEST_DIRECTORY"/lib-terminal.sh
10
11test_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
43test_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
51test_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
60test_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
68test_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
84test_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
92test_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
100test_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
106test_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
113test_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
119test_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
132test_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
143test_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
153test_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
161test_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
169test_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
176test_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
184test_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
191test_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
197test_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
203test_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
210test_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
217test_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
226check_patch () {
227 grep -e "^From:" "$1" &&
228 grep -e "^Date:" "$1" &&
229 grep -e "^Subject:" "$1"
230}
231
232test_expect_success '--no-to overrides config.to' '
233
234 git config --replace-all format.to \
235 "R E Cipient <rcipient@example.com>" &&
236 git format-patch --no-to --stdout master..side |
237 sed -e "/^\$/q" >patch10 &&
238 check_patch patch10 &&
239 ! grep "^To: R E Cipient <rcipient@example.com>\$" patch10
240'
241
242test_expect_success '--no-to and --to replaces config.to' '
243
244 git config --replace-all format.to \
245 "Someone <someone@out.there>" &&
246 git format-patch --no-to --to="Someone Else <else@out.there>" \
247 --stdout master..side |
248 sed -e "/^\$/q" >patch11 &&
249 check_patch patch11 &&
250 ! grep "^To: Someone <someone@out.there>\$" patch11 &&
251 grep "^To: Someone Else <else@out.there>\$" patch11
252'
253
254test_expect_success '--no-cc overrides config.cc' '
255
256 git config --replace-all format.cc \
257 "C E Cipient <rcipient@example.com>" &&
258 git format-patch --no-cc --stdout master..side |
259 sed -e "/^\$/q" >patch12 &&
260 check_patch patch12 &&
261 ! grep "^Cc: C E Cipient <rcipient@example.com>\$" patch12
262'
263
264test_expect_success '--no-add-header overrides config.headers' '
265
266 git config --replace-all format.headers \
267 "Header1: B E Cipient <rcipient@example.com>" &&
268 git format-patch --no-add-header --stdout master..side |
269 sed -e "/^\$/q" >patch13 &&
270 check_patch patch13 &&
271 ! grep "^Header1: B E Cipient <rcipient@example.com>\$" patch13
272'
273
274test_expect_success 'multiple files' '
275
276 rm -rf patches/ &&
277 git checkout side &&
278 git format-patch -o patches/ master &&
279 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
280'
281
282test_expect_success 'reroll count' '
283 rm -fr patches &&
284 git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
285 ! grep -v "^patches/v4-000[0-3]-" list &&
286 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
287 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
288'
289
290test_expect_success 'reroll count (-v)' '
291 rm -fr patches &&
292 git format-patch -o patches --cover-letter -v4 master..side >list &&
293 ! grep -v "^patches/v4-000[0-3]-" list &&
294 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
295 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
296'
297
298check_threading () {
299 expect="$1" &&
300 shift &&
301 (git format-patch --stdout "$@"; echo $? > status.out) |
302 # Prints everything between the Message-ID and In-Reply-To,
303 # and replaces all Message-ID-lookalikes by a sequence number
304 perl -ne '
305 if (/^(message-id|references|in-reply-to)/i) {
306 $printing = 1;
307 } elsif (/^\S/) {
308 $printing = 0;
309 }
310 if ($printing) {
311 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
312 for $k (keys %h) {s/$k/$h{$k}/};
313 print;
314 }
315 print "---\n" if /^From /i;
316 ' > actual &&
317 test 0 = "$(cat status.out)" &&
318 test_cmp "$expect" actual
319}
320
321cat >> expect.no-threading <<EOF
322---
323---
324---
325EOF
326
327test_expect_success 'no threading' '
328 git checkout side &&
329 check_threading expect.no-threading master
330'
331
332cat > expect.thread <<EOF
333---
334Message-Id: <0>
335---
336Message-Id: <1>
337In-Reply-To: <0>
338References: <0>
339---
340Message-Id: <2>
341In-Reply-To: <0>
342References: <0>
343EOF
344
345test_expect_success 'thread' '
346 check_threading expect.thread --thread master
347'
348
349cat > expect.in-reply-to <<EOF
350---
351Message-Id: <0>
352In-Reply-To: <1>
353References: <1>
354---
355Message-Id: <2>
356In-Reply-To: <1>
357References: <1>
358---
359Message-Id: <3>
360In-Reply-To: <1>
361References: <1>
362EOF
363
364test_expect_success 'thread in-reply-to' '
365 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
366 --thread master
367'
368
369cat > expect.cover-letter <<EOF
370---
371Message-Id: <0>
372---
373Message-Id: <1>
374In-Reply-To: <0>
375References: <0>
376---
377Message-Id: <2>
378In-Reply-To: <0>
379References: <0>
380---
381Message-Id: <3>
382In-Reply-To: <0>
383References: <0>
384EOF
385
386test_expect_success 'thread cover-letter' '
387 check_threading expect.cover-letter --cover-letter --thread master
388'
389
390cat > expect.cl-irt <<EOF
391---
392Message-Id: <0>
393In-Reply-To: <1>
394References: <1>
395---
396Message-Id: <2>
397In-Reply-To: <0>
398References: <1>
399 <0>
400---
401Message-Id: <3>
402In-Reply-To: <0>
403References: <1>
404 <0>
405---
406Message-Id: <4>
407In-Reply-To: <0>
408References: <1>
409 <0>
410EOF
411
412test_expect_success 'thread cover-letter in-reply-to' '
413 check_threading expect.cl-irt --cover-letter \
414 --in-reply-to="<test.message>" --thread master
415'
416
417test_expect_success 'thread explicit shallow' '
418 check_threading expect.cl-irt --cover-letter \
419 --in-reply-to="<test.message>" --thread=shallow master
420'
421
422cat > expect.deep <<EOF
423---
424Message-Id: <0>
425---
426Message-Id: <1>
427In-Reply-To: <0>
428References: <0>
429---
430Message-Id: <2>
431In-Reply-To: <1>
432References: <0>
433 <1>
434EOF
435
436test_expect_success 'thread deep' '
437 check_threading expect.deep --thread=deep master
438'
439
440cat > expect.deep-irt <<EOF
441---
442Message-Id: <0>
443In-Reply-To: <1>
444References: <1>
445---
446Message-Id: <2>
447In-Reply-To: <0>
448References: <1>
449 <0>
450---
451Message-Id: <3>
452In-Reply-To: <2>
453References: <1>
454 <0>
455 <2>
456EOF
457
458test_expect_success 'thread deep in-reply-to' '
459 check_threading expect.deep-irt --thread=deep \
460 --in-reply-to="<test.message>" master
461'
462
463cat > expect.deep-cl <<EOF
464---
465Message-Id: <0>
466---
467Message-Id: <1>
468In-Reply-To: <0>
469References: <0>
470---
471Message-Id: <2>
472In-Reply-To: <1>
473References: <0>
474 <1>
475---
476Message-Id: <3>
477In-Reply-To: <2>
478References: <0>
479 <1>
480 <2>
481EOF
482
483test_expect_success 'thread deep cover-letter' '
484 check_threading expect.deep-cl --cover-letter --thread=deep master
485'
486
487cat > expect.deep-cl-irt <<EOF
488---
489Message-Id: <0>
490In-Reply-To: <1>
491References: <1>
492---
493Message-Id: <2>
494In-Reply-To: <0>
495References: <1>
496 <0>
497---
498Message-Id: <3>
499In-Reply-To: <2>
500References: <1>
501 <0>
502 <2>
503---
504Message-Id: <4>
505In-Reply-To: <3>
506References: <1>
507 <0>
508 <2>
509 <3>
510EOF
511
512test_expect_success 'thread deep cover-letter in-reply-to' '
513 check_threading expect.deep-cl-irt --cover-letter \
514 --in-reply-to="<test.message>" --thread=deep master
515'
516
517test_expect_success 'thread via config' '
518 test_config format.thread true &&
519 check_threading expect.thread master
520'
521
522test_expect_success 'thread deep via config' '
523 test_config format.thread deep &&
524 check_threading expect.deep master
525'
526
527test_expect_success 'thread config + override' '
528 test_config format.thread deep &&
529 check_threading expect.thread --thread master
530'
531
532test_expect_success 'thread config + --no-thread' '
533 test_config format.thread deep &&
534 check_threading expect.no-threading --no-thread master
535'
536
537test_expect_success 'excessive subject' '
538
539 rm -rf patches/ &&
540 git checkout side &&
541 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
542 git update-index file &&
543 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." &&
544 git format-patch -o patches/ master..side &&
545 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
546'
547
548test_expect_success 'cover-letter inherits diff options' '
549
550 git mv file foo &&
551 git commit -m foo &&
552 git format-patch --no-renames --cover-letter -1 &&
553 check_patch 0000-cover-letter.patch &&
554 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
555 git format-patch --cover-letter -1 -M &&
556 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
557
558'
559
560cat > expect << EOF
561 This is an excessively long subject line for a message due to the
562 habit some projects have of not having a short, one-line subject at
563 the start of the commit message, but rather sticking a whole
564 paragraph right at the start as the only thing in the commit
565 message. It had better not become the filename for the patch.
566 foo
567
568EOF
569
570test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
571
572 git format-patch --cover-letter -2 &&
573 sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
574 test_cmp expect output
575
576'
577
578cat > expect << EOF
579index 40f36c6..2dc5c23 100644
580--- a/file
581+++ b/file
582@@ -13,4 +13,20 @@ C
583 10
584 D
585 E
586 F
587+5
588EOF
589
590test_expect_success 'format-patch respects -U' '
591
592 git format-patch -U4 -2 &&
593 sed -e "1,/^diff/d" -e "/^+5/q" \
594 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
595 >output &&
596 test_cmp expect output
597
598'
599
600cat > expect << EOF
601
602diff --git a/file b/file
603index 40f36c6..2dc5c23 100644
604--- a/file
605+++ b/file
606@@ -14,3 +14,19 @@ C
607 D
608 E
609 F
610+5
611EOF
612
613test_expect_success 'format-patch -p suppresses stat' '
614
615 git format-patch -p -2 &&
616 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
617 test_cmp expect output
618
619'
620
621test_expect_success 'format-patch from a subdirectory (1)' '
622 filename=$(
623 rm -rf sub &&
624 mkdir -p sub/dir &&
625 cd sub/dir &&
626 git format-patch -1
627 ) &&
628 case "$filename" in
629 0*)
630 ;; # ok
631 *)
632 echo "Oops? $filename"
633 false
634 ;;
635 esac &&
636 test -f "$filename"
637'
638
639test_expect_success 'format-patch from a subdirectory (2)' '
640 filename=$(
641 rm -rf sub &&
642 mkdir -p sub/dir &&
643 cd sub/dir &&
644 git format-patch -1 -o ..
645 ) &&
646 case "$filename" in
647 ../0*)
648 ;; # ok
649 *)
650 echo "Oops? $filename"
651 false
652 ;;
653 esac &&
654 basename=$(expr "$filename" : ".*/\(.*\)") &&
655 test -f "sub/$basename"
656'
657
658test_expect_success 'format-patch from a subdirectory (3)' '
659 rm -f 0* &&
660 filename=$(
661 rm -rf sub &&
662 mkdir -p sub/dir &&
663 cd sub/dir &&
664 git format-patch -1 -o "$TRASH_DIRECTORY"
665 ) &&
666 basename=$(expr "$filename" : ".*/\(.*\)") &&
667 test -f "$basename"
668'
669
670test_expect_success 'format-patch --in-reply-to' '
671 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
672 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
673 grep "^References: <baz@foo.bar>" patch8
674'
675
676test_expect_success 'format-patch --signoff' '
677 git format-patch -1 --signoff --stdout >out &&
678 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
679'
680
681test_expect_success 'format-patch --notes --signoff' '
682 git notes --ref test add -m "test message" HEAD &&
683 git format-patch -1 --signoff --stdout --notes=test >out &&
684 # Three dashes must come after S-o-b
685 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
686 sed "1,/^Signed-off-by: /d" out | grep "test message" &&
687 # Notes message must come after three dashes
688 ! sed "/^---$/q" out | grep "test message" &&
689 sed "1,/^---$/d" out | grep "test message"
690'
691
692echo "fatal: --name-only does not make sense" > expect.name-only
693echo "fatal: --name-status does not make sense" > expect.name-status
694echo "fatal: --check does not make sense" > expect.check
695
696test_expect_success 'options no longer allowed for format-patch' '
697 test_must_fail git format-patch --name-only 2> output &&
698 test_i18ncmp expect.name-only output &&
699 test_must_fail git format-patch --name-status 2> output &&
700 test_i18ncmp expect.name-status output &&
701 test_must_fail git format-patch --check 2> output &&
702 test_i18ncmp expect.check output'
703
704test_expect_success 'format-patch --numstat should produce a patch' '
705 git format-patch --numstat --stdout master..side > output &&
706 test 5 = $(grep "^diff --git a/" output | wc -l)'
707
708test_expect_success 'format-patch -- <path>' '
709 git format-patch master..side -- file 2>error &&
710 ! grep "Use .--" error
711'
712
713test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
714 git format-patch --ignore-if-in-upstream HEAD
715'
716
717test_expect_success 'format-patch --signature' '
718 git format-patch --stdout --signature="my sig" -1 >output &&
719 grep "my sig" output
720'
721
722test_expect_success 'format-patch with format.signature config' '
723 git config format.signature "config sig" &&
724 git format-patch --stdout -1 >output &&
725 grep "config sig" output
726'
727
728test_expect_success 'format-patch --signature overrides format.signature' '
729 git config format.signature "config sig" &&
730 git format-patch --stdout --signature="overrides" -1 >output &&
731 ! grep "config sig" output &&
732 grep "overrides" output
733'
734
735test_expect_success 'format-patch --no-signature ignores format.signature' '
736 git config format.signature "config sig" &&
737 git format-patch --stdout --signature="my sig" --no-signature \
738 -1 >output &&
739 check_patch output &&
740 ! grep "config sig" output &&
741 ! grep "my sig" output &&
742 ! grep "^-- \$" output
743'
744
745test_expect_success 'format-patch --signature --cover-letter' '
746 git config --unset-all format.signature &&
747 git format-patch --stdout --signature="my sig" --cover-letter \
748 -1 >output &&
749 grep "my sig" output &&
750 test 2 = $(grep "my sig" output | wc -l)
751'
752
753test_expect_success 'format.signature="" suppresses signatures' '
754 git config format.signature "" &&
755 git format-patch --stdout -1 >output &&
756 check_patch output &&
757 ! grep "^-- \$" output
758'
759
760test_expect_success 'format-patch --no-signature suppresses signatures' '
761 git config --unset-all format.signature &&
762 git format-patch --stdout --no-signature -1 >output &&
763 check_patch output &&
764 ! grep "^-- \$" output
765'
766
767test_expect_success 'format-patch --signature="" suppresses signatures' '
768 git format-patch --stdout --signature="" -1 >output &&
769 check_patch output &&
770 ! grep "^-- \$" output
771'
772
773test_expect_success 'prepare mail-signature input' '
774 cat >mail-signature <<-\EOF
775
776 Test User <test.email@kernel.org>
777 http://git.kernel.org/cgit/git/git.git
778
779 git.kernel.org/?p=git/git.git;a=summary
780
781 EOF
782'
783
784test_expect_success '--signature-file=file works' '
785 git format-patch --stdout --signature-file=mail-signature -1 >output &&
786 check_patch output &&
787 sed -e "1,/^-- \$/d" <output >actual &&
788 {
789 cat mail-signature && echo
790 } >expect &&
791 test_cmp expect actual
792'
793
794test_expect_success 'format.signaturefile works' '
795 test_config format.signaturefile mail-signature &&
796 git format-patch --stdout -1 >output &&
797 check_patch output &&
798 sed -e "1,/^-- \$/d" <output >actual &&
799 {
800 cat mail-signature && echo
801 } >expect &&
802 test_cmp expect actual
803'
804
805test_expect_success '--no-signature suppresses format.signaturefile ' '
806 test_config format.signaturefile mail-signature &&
807 git format-patch --stdout --no-signature -1 >output &&
808 check_patch output &&
809 ! grep "^-- \$" output
810'
811
812test_expect_success '--signature-file overrides format.signaturefile' '
813 cat >other-mail-signature <<-\EOF &&
814 Use this other signature instead of mail-signature.
815 EOF
816 test_config format.signaturefile mail-signature &&
817 git format-patch --stdout \
818 --signature-file=other-mail-signature -1 >output &&
819 check_patch output &&
820 sed -e "1,/^-- \$/d" <output >actual &&
821 {
822 cat other-mail-signature && echo
823 } >expect &&
824 test_cmp expect actual
825'
826
827test_expect_success '--signature overrides format.signaturefile' '
828 test_config format.signaturefile mail-signature &&
829 git format-patch --stdout --signature="my sig" -1 >output &&
830 check_patch output &&
831 grep "my sig" output
832'
833
834test_expect_success TTY 'format-patch --stdout paginates' '
835 rm -f pager_used &&
836 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
837 test_path_is_file pager_used
838'
839
840 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
841 rm -f pager_used &&
842 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
843 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
844 test_path_is_missing pager_used &&
845 test_path_is_missing .git/pager_used
846'
847
848test_expect_success 'format-patch handles multi-line subjects' '
849 rm -rf patches/ &&
850 echo content >>file &&
851 for i in one two three; do echo $i; done >msg &&
852 git add file &&
853 git commit -F msg &&
854 git format-patch -o patches -1 &&
855 grep ^Subject: patches/0001-one.patch >actual &&
856 echo "Subject: [PATCH] one two three" >expect &&
857 test_cmp expect actual
858'
859
860test_expect_success 'format-patch handles multi-line encoded subjects' '
861 rm -rf patches/ &&
862 echo content >>file &&
863 for i in en två tre; do echo $i; done >msg &&
864 git add file &&
865 git commit -F msg &&
866 git format-patch -o patches -1 &&
867 grep ^Subject: patches/0001-en.patch >actual &&
868 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
869 test_cmp expect actual
870'
871
872M8="foo bar "
873M64=$M8$M8$M8$M8$M8$M8$M8$M8
874M512=$M64$M64$M64$M64$M64$M64$M64$M64
875cat >expect <<'EOF'
876Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
877 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
878 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
879 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
880 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
881 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
882 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
883EOF
884test_expect_success 'format-patch wraps extremely long subject (ascii)' '
885 echo content >>file &&
886 git add file &&
887 git commit -m "$M512" &&
888 git format-patch --stdout -1 >patch &&
889 sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
890 test_cmp expect subject
891'
892
893M8="föö bar "
894M64=$M8$M8$M8$M8$M8$M8$M8$M8
895M512=$M64$M64$M64$M64$M64$M64$M64$M64
896cat >expect <<'EOF'
897Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
898 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
899 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
900 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
901 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
902 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
903 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
904 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
905 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
906 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
907 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
908 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
909 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
910 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
911 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
912 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
913 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
914 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
915 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
916 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
917 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
918 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
919 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
920 =?UTF-8?q?bar?=
921EOF
922test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
923 rm -rf patches/ &&
924 echo content >>file &&
925 git add file &&
926 git commit -m "$M512" &&
927 git format-patch --stdout -1 >patch &&
928 sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
929 test_cmp expect subject
930'
931
932check_author() {
933 echo content >>file &&
934 git add file &&
935 GIT_AUTHOR_NAME=$1 git commit -m author-check &&
936 git format-patch --stdout -1 >patch &&
937 sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
938 test_cmp expect actual
939}
940
941cat >expect <<'EOF'
942From: "Foo B. Bar" <author@example.com>
943EOF
944test_expect_success 'format-patch quotes dot in from-headers' '
945 check_author "Foo B. Bar"
946'
947
948cat >expect <<'EOF'
949From: "Foo \"The Baz\" Bar" <author@example.com>
950EOF
951test_expect_success 'format-patch quotes double-quote in from-headers' '
952 check_author "Foo \"The Baz\" Bar"
953'
954
955cat >expect <<'EOF'
956From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
957EOF
958test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
959 check_author "Föo Bar"
960'
961
962cat >expect <<'EOF'
963From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
964EOF
965test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
966 check_author "Föo B. Bar"
967'
968
969cat >expect <<EOF
970From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
971 <author@example.com>
972EOF
973test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
974 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
975'
976
977cat >expect <<'EOF'
978From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
979 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
980 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
981EOF
982test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
983 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"
984'
985
986cat >expect <<'EOF'
987From: "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 Foo
989 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
990EOF
991test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
992 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"
993'
994
995cat >expect <<'EOF'
996From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
997 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
998 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
999 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1000 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1001EOF
1002test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1003 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"
1004'
1005
1006cat >expect <<'EOF'
1007Subject: header with . in it
1008EOF
1009test_expect_success 'subject lines do not have 822 atom-quoting' '
1010 echo content >>file &&
1011 git add file &&
1012 git commit -m "header with . in it" &&
1013 git format-patch -k -1 --stdout >patch &&
1014 grep ^Subject: patch >actual &&
1015 test_cmp expect actual
1016'
1017
1018cat >expect <<'EOF'
1019Subject: [PREFIX 1/1] header with . in it
1020EOF
1021test_expect_success 'subject prefixes have space prepended' '
1022 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1023 grep ^Subject: patch >actual &&
1024 test_cmp expect actual
1025'
1026
1027cat >expect <<'EOF'
1028Subject: [1/1] header with . in it
1029EOF
1030test_expect_success 'empty subject prefix does not have extra space' '
1031 git format-patch -n -1 --stdout --subject-prefix= >patch &&
1032 grep ^Subject: patch >actual &&
1033 test_cmp expect actual
1034'
1035
1036test_expect_success '--from=ident notices bogus ident' '
1037 test_must_fail git format-patch -1 --stdout --from=foo >patch
1038'
1039
1040test_expect_success '--from=ident replaces author' '
1041 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1042 cat >expect <<-\EOF &&
1043 From: Me <me@example.com>
1044
1045 From: A U Thor <author@example.com>
1046
1047 EOF
1048 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1049 test_cmp expect patch.head
1050'
1051
1052test_expect_success '--from uses committer ident' '
1053 git format-patch -1 --stdout --from >patch &&
1054 cat >expect <<-\EOF &&
1055 From: C O Mitter <committer@example.com>
1056
1057 From: A U Thor <author@example.com>
1058
1059 EOF
1060 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1061 test_cmp expect patch.head
1062'
1063
1064test_expect_success '--from omits redundant in-body header' '
1065 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1066 cat >expect <<-\EOF &&
1067 From: A U Thor <author@example.com>
1068
1069 EOF
1070 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1071 test_cmp expect patch.head
1072'
1073
1074test_expect_success 'in-body headers trigger content encoding' '
1075 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1076 test_when_finished "git reset --hard HEAD^" &&
1077 git format-patch -1 --stdout --from >patch &&
1078 cat >expect <<-\EOF &&
1079 From: C O Mitter <committer@example.com>
1080 Content-Type: text/plain; charset=UTF-8
1081
1082 From: éxötìc <author@example.com>
1083
1084 EOF
1085 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1086 test_cmp expect patch.head
1087'
1088
1089append_signoff()
1090{
1091 C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1092 git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1093 sed -n -e "1,/^---$/p" append_signoff.patch |
1094 egrep -n "^Subject|Sign|^$"
1095}
1096
1097test_expect_success 'signoff: commit with no body' '
1098 append_signoff </dev/null >actual &&
1099 cat <<\EOF | sed "s/EOL$//" >expected &&
11004:Subject: [PATCH] EOL
11018:
11029:Signed-off-by: C O Mitter <committer@example.com>
1103EOF
1104 test_cmp expected actual
1105'
1106
1107test_expect_success 'signoff: commit with only subject' '
1108 echo subject | append_signoff >actual &&
1109 cat >expected <<\EOF &&
11104:Subject: [PATCH] subject
11118:
11129:Signed-off-by: C O Mitter <committer@example.com>
1113EOF
1114 test_cmp expected actual
1115'
1116
1117test_expect_success 'signoff: commit with only subject that does not end with NL' '
1118 printf subject | append_signoff >actual &&
1119 cat >expected <<\EOF &&
11204:Subject: [PATCH] subject
11218:
11229:Signed-off-by: C O Mitter <committer@example.com>
1123EOF
1124 test_cmp expected actual
1125'
1126
1127test_expect_success 'signoff: no existing signoffs' '
1128 append_signoff <<\EOF >actual &&
1129subject
1130
1131body
1132EOF
1133 cat >expected <<\EOF &&
11344:Subject: [PATCH] subject
11358:
113610:
113711:Signed-off-by: C O Mitter <committer@example.com>
1138EOF
1139 test_cmp expected actual
1140'
1141
1142test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1143 printf "subject\n\nbody" | append_signoff >actual &&
1144 cat >expected <<\EOF &&
11454:Subject: [PATCH] subject
11468:
114710:
114811:Signed-off-by: C O Mitter <committer@example.com>
1149EOF
1150 test_cmp expected actual
1151'
1152
1153test_expect_success 'signoff: some random signoff' '
1154 append_signoff <<\EOF >actual &&
1155subject
1156
1157body
1158
1159Signed-off-by: my@house
1160EOF
1161 cat >expected <<\EOF &&
11624:Subject: [PATCH] subject
11638:
116410:
116511:Signed-off-by: my@house
116612:Signed-off-by: C O Mitter <committer@example.com>
1167EOF
1168 test_cmp expected actual
1169'
1170
1171test_expect_success 'signoff: misc conforming footer elements' '
1172 append_signoff <<\EOF >actual &&
1173subject
1174
1175body
1176
1177Signed-off-by: my@house
1178(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1179Tested-by: Some One <someone@example.com>
1180Bug: 1234
1181EOF
1182 cat >expected <<\EOF &&
11834:Subject: [PATCH] subject
11848:
118510:
118611:Signed-off-by: my@house
118715:Signed-off-by: C O Mitter <committer@example.com>
1188EOF
1189 test_cmp expected actual
1190'
1191
1192test_expect_success 'signoff: some random signoff-alike' '
1193 append_signoff <<\EOF >actual &&
1194subject
1195
1196body
1197Fooled-by-me: my@house
1198EOF
1199 cat >expected <<\EOF &&
12004:Subject: [PATCH] subject
12018:
120211:
120312:Signed-off-by: C O Mitter <committer@example.com>
1204EOF
1205 test_cmp expected actual
1206'
1207
1208test_expect_success 'signoff: not really a signoff' '
1209 append_signoff <<\EOF >actual &&
1210subject
1211
1212I want to mention about Signed-off-by: here.
1213EOF
1214 cat >expected <<\EOF &&
12154:Subject: [PATCH] subject
12168:
12179:I want to mention about Signed-off-by: here.
121810:
121911:Signed-off-by: C O Mitter <committer@example.com>
1220EOF
1221 test_cmp expected actual
1222'
1223
1224test_expect_success 'signoff: not really a signoff (2)' '
1225 append_signoff <<\EOF >actual &&
1226subject
1227
1228My unfortunate
1229Signed-off-by: example happens to be wrapped here.
1230EOF
1231 cat >expected <<\EOF &&
12324:Subject: [PATCH] subject
12338:
123410:Signed-off-by: example happens to be wrapped here.
123511:
123612:Signed-off-by: C O Mitter <committer@example.com>
1237EOF
1238 test_cmp expected actual
1239'
1240
1241test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1242 append_signoff <<\EOF >actual &&
1243subject
1244
1245Signed-off-by: my@house
1246Signed-off-by: your@house
1247
1248A lot of houses.
1249EOF
1250 cat >expected <<\EOF &&
12514:Subject: [PATCH] subject
12528:
12539:Signed-off-by: my@house
125410:Signed-off-by: your@house
125511:
125613:
125714:Signed-off-by: C O Mitter <committer@example.com>
1258EOF
1259 test_cmp expected actual
1260'
1261
1262test_expect_success 'signoff: the same signoff at the end' '
1263 append_signoff <<\EOF >actual &&
1264subject
1265
1266body
1267
1268Signed-off-by: C O Mitter <committer@example.com>
1269EOF
1270 cat >expected <<\EOF &&
12714:Subject: [PATCH] subject
12728:
127310:
127411:Signed-off-by: C O Mitter <committer@example.com>
1275EOF
1276 test_cmp expected actual
1277'
1278
1279test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1280 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1281 append_signoff >actual &&
1282 cat >expected <<\EOF &&
12834:Subject: [PATCH] subject
12848:
12859:Signed-off-by: C O Mitter <committer@example.com>
1286EOF
1287 test_cmp expected actual
1288'
1289
1290test_expect_success 'signoff: the same signoff NOT at the end' '
1291 append_signoff <<\EOF >actual &&
1292subject
1293
1294body
1295
1296Signed-off-by: C O Mitter <committer@example.com>
1297Signed-off-by: my@house
1298EOF
1299 cat >expected <<\EOF &&
13004:Subject: [PATCH] subject
13018:
130210:
130311:Signed-off-by: C O Mitter <committer@example.com>
130412:Signed-off-by: my@house
1305EOF
1306 test_cmp expected actual
1307'
1308
1309test_expect_success 'signoff: detect garbage in non-conforming footer' '
1310 append_signoff <<\EOF >actual &&
1311subject
1312
1313body
1314
1315Tested-by: my@house
1316Some Trash
1317Signed-off-by: C O Mitter <committer@example.com>
1318EOF
1319 cat >expected <<\EOF &&
13204:Subject: [PATCH] subject
13218:
132210:
132313:Signed-off-by: C O Mitter <committer@example.com>
132414:
132515:Signed-off-by: C O Mitter <committer@example.com>
1326EOF
1327 test_cmp expected actual
1328'
1329
1330test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1331 append_signoff <<\EOF >actual &&
1332subject
1333
1334body
1335
1336Reviewed-id: Noone
1337Tested-by: my@house
1338Change-id: Ideadbeef
1339Signed-off-by: C O Mitter <committer@example.com>
1340Bug: 1234
1341EOF
1342 cat >expected <<\EOF &&
13434:Subject: [PATCH] subject
13448:
134510:
134614:Signed-off-by: C O Mitter <committer@example.com>
1347EOF
1348 test_cmp expected actual
1349'
1350
1351test_expect_success 'format patch ignores color.ui' '
1352 test_unconfig color.ui &&
1353 git format-patch --stdout -1 >expect &&
1354 test_config color.ui always &&
1355 git format-patch --stdout -1 >actual &&
1356 test_cmp expect actual
1357'
1358
1359test_expect_success 'cover letter using branch description (1)' '
1360 git checkout rebuild-1 &&
1361 test_config branch.rebuild-1.description hello &&
1362 git format-patch --stdout --cover-letter master >actual &&
1363 grep hello actual >/dev/null
1364'
1365
1366test_expect_success 'cover letter using branch description (2)' '
1367 git checkout rebuild-1 &&
1368 test_config branch.rebuild-1.description hello &&
1369 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1370 grep hello actual >/dev/null
1371'
1372
1373test_expect_success 'cover letter using branch description (3)' '
1374 git checkout rebuild-1 &&
1375 test_config branch.rebuild-1.description hello &&
1376 git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1377 grep hello actual >/dev/null
1378'
1379
1380test_expect_success 'cover letter using branch description (4)' '
1381 git checkout rebuild-1 &&
1382 test_config branch.rebuild-1.description hello &&
1383 git format-patch --stdout --cover-letter master.. >actual &&
1384 grep hello actual >/dev/null
1385'
1386
1387test_expect_success 'cover letter using branch description (5)' '
1388 git checkout rebuild-1 &&
1389 test_config branch.rebuild-1.description hello &&
1390 git format-patch --stdout --cover-letter -2 HEAD >actual &&
1391 grep hello actual >/dev/null
1392'
1393
1394test_expect_success 'cover letter using branch description (6)' '
1395 git checkout rebuild-1 &&
1396 test_config branch.rebuild-1.description hello &&
1397 git format-patch --stdout --cover-letter -2 >actual &&
1398 grep hello actual >/dev/null
1399'
1400
1401test_expect_success 'cover letter with nothing' '
1402 git format-patch --stdout --cover-letter >actual &&
1403 test_line_count = 0 actual
1404'
1405
1406test_expect_success 'cover letter auto' '
1407 mkdir -p tmp &&
1408 test_when_finished "rm -rf tmp;
1409 git config --unset format.coverletter" &&
1410
1411 git config format.coverletter auto &&
1412 git format-patch -o tmp -1 >list &&
1413 test_line_count = 1 list &&
1414 git format-patch -o tmp -2 >list &&
1415 test_line_count = 3 list
1416'
1417
1418test_expect_success 'cover letter auto user override' '
1419 mkdir -p tmp &&
1420 test_when_finished "rm -rf tmp;
1421 git config --unset format.coverletter" &&
1422
1423 git config format.coverletter auto &&
1424 git format-patch -o tmp --cover-letter -1 >list &&
1425 test_line_count = 2 list &&
1426 git format-patch -o tmp --cover-letter -2 >list &&
1427 test_line_count = 3 list &&
1428 git format-patch -o tmp --no-cover-letter -1 >list &&
1429 test_line_count = 1 list &&
1430 git format-patch -o tmp --no-cover-letter -2 >list &&
1431 test_line_count = 2 list
1432'
1433
1434test_expect_success 'format-patch --zero-commit' '
1435 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1436 grep "^From " patch2 | sort | uniq >actual &&
1437 echo "From $_z40 Mon Sep 17 00:00:00 2001" >expect &&
1438 test_cmp expect actual
1439'
1440
1441test_expect_success 'From line has expected format' '
1442 git format-patch --stdout v2..v1 >patch2 &&
1443 grep "^From " patch2 >from &&
1444 grep "^From $_x40 Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1445 test_cmp from filtered
1446'
1447
1448test_expect_success 'format-patch format.outputDirectory option' '
1449 test_config format.outputDirectory patches &&
1450 rm -fr patches &&
1451 git format-patch master..side &&
1452 test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
1453'
1454
1455test_expect_success 'format-patch -o overrides format.outputDirectory' '
1456 test_config format.outputDirectory patches &&
1457 rm -fr patches patchset &&
1458 git format-patch master..side -o patchset &&
1459 test_path_is_missing patches &&
1460 test_path_is_dir patchset
1461'
1462
1463test_expect_success 'format-patch --base' '
1464 git checkout side &&
1465 git format-patch --stdout --base=HEAD~3 -1 >patch &&
1466 grep "^base-commit:" patch >actual &&
1467 grep "^prerequisite-patch-id:" patch >>actual &&
1468 echo "base-commit: $(git rev-parse HEAD~3)" >expected &&
1469 echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1470 echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1471 test_cmp expected actual
1472'
1473
1474test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1475 test_must_fail git format-patch --base=HEAD -2 &&
1476 test_must_fail git format-patch --base=HEAD~1 -2 &&
1477 git format-patch --stdout --base=HEAD~2 -2 >patch &&
1478 grep "^base-commit:" patch >actual &&
1479 echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
1480 test_cmp expected actual
1481'
1482
1483test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1484 # For history as below:
1485 #
1486 # ---Q---P---Z---Y---*---X
1487 # \ /
1488 # ------------W
1489 #
1490 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1491 git checkout -b topic1 master &&
1492 git rev-parse HEAD >commit-id-base &&
1493 test_commit P &&
1494 git rev-parse HEAD >commit-id-P &&
1495 test_commit Z &&
1496 git rev-parse HEAD >commit-id-Z &&
1497 test_commit Y &&
1498 git checkout -b topic2 master &&
1499 test_commit W &&
1500 git merge topic1 &&
1501 test_commit X &&
1502 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1503 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1504 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1505 grep "^base-commit:" patch >actual &&
1506 echo "base-commit: $(cat commit-id-base)" >expected &&
1507 test_cmp expected actual
1508'
1509
1510test_expect_success 'format-patch --base=auto' '
1511 git checkout -b upstream master &&
1512 git checkout -b local upstream &&
1513 git branch --set-upstream-to=upstream &&
1514 test_commit N1 &&
1515 test_commit N2 &&
1516 git format-patch --stdout --base=auto -2 >patch &&
1517 grep "^base-commit:" patch >actual &&
1518 echo "base-commit: $(git rev-parse upstream)" >expected &&
1519 test_cmp expected actual
1520'
1521
1522test_expect_success 'format-patch errors out when history involves criss-cross' '
1523 # setup criss-cross history
1524 #
1525 # B---M1---D
1526 # / \ /
1527 # A X
1528 # \ / \
1529 # C---M2---E
1530 #
1531 git checkout master &&
1532 test_commit A &&
1533 git checkout -b xb master &&
1534 test_commit B &&
1535 git checkout -b xc master &&
1536 test_commit C &&
1537 git checkout -b xbc xb -- &&
1538 git merge xc &&
1539 git checkout -b xcb xc -- &&
1540 git branch --set-upstream-to=xbc &&
1541 git merge xb &&
1542 git checkout xbc &&
1543 test_commit D &&
1544 git checkout xcb &&
1545 test_commit E &&
1546 test_must_fail git format-patch --base=auto -1
1547'
1548
1549test_expect_success 'format-patch format.useAutoBaseoption' '
1550 test_when_finished "git config --unset format.useAutoBase" &&
1551 git checkout local &&
1552 git config format.useAutoBase true &&
1553 git format-patch --stdout -1 >patch &&
1554 grep "^base-commit:" patch >actual &&
1555 echo "base-commit: $(git rev-parse upstream)" >expected &&
1556 test_cmp expected actual
1557'
1558
1559test_expect_success 'format-patch --base overrides format.useAutoBase' '
1560 test_when_finished "git config --unset format.useAutoBase" &&
1561 git config format.useAutoBase true &&
1562 git format-patch --stdout --base=HEAD~1 -1 >patch &&
1563 grep "^base-commit:" patch >actual &&
1564 echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
1565 test_cmp expected actual
1566'
1567
1568test_expect_success 'format-patch --pretty=mboxrd' '
1569 sp=" " &&
1570 cat >msg <<-INPUT_END &&
1571 mboxrd should escape the body
1572
1573 From could trip up a loose mbox parser
1574 >From extra escape for reversibility
1575 >>From extra escape for reversibility 2
1576 from lower case not escaped
1577 Fromm bad speling not escaped
1578 From with leading space not escaped
1579
1580 F
1581 From
1582 From$sp
1583 From $sp
1584 From $sp
1585 INPUT_END
1586
1587 cat >expect <<-INPUT_END &&
1588 >From could trip up a loose mbox parser
1589 >>From extra escape for reversibility
1590 >>>From extra escape for reversibility 2
1591 from lower case not escaped
1592 Fromm bad speling not escaped
1593 From with leading space not escaped
1594
1595 F
1596 From
1597 From
1598 From
1599 From
1600 INPUT_END
1601
1602 C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
1603 git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
1604 git grep -h --no-index -A11 \
1605 "^>From could trip up a loose mbox parser" patch >actual &&
1606 test_cmp expect actual
1607'
1608
1609test_done