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