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
757test_expect_success 'format-patch --signature' '
758 git format-patch --stdout --signature="my sig" -1 >output &&
759 grep "my sig" output
760'
761
762test_expect_success 'format-patch with format.signature config' '
763 git config format.signature "config sig" &&
764 git format-patch --stdout -1 >output &&
765 grep "config sig" output
766'
767
768test_expect_success 'format-patch --signature overrides format.signature' '
769 git config format.signature "config sig" &&
770 git format-patch --stdout --signature="overrides" -1 >output &&
771 ! grep "config sig" output &&
772 grep "overrides" output
773'
774
775test_expect_success 'format-patch --no-signature ignores format.signature' '
776 git config format.signature "config sig" &&
777 git format-patch --stdout --signature="my sig" --no-signature \
778 -1 >output &&
779 check_patch output &&
780 ! grep "config sig" output &&
781 ! grep "my sig" output &&
782 ! grep "^-- \$" output
783'
784
785test_expect_success 'format-patch --signature --cover-letter' '
786 git config --unset-all format.signature &&
787 git format-patch --stdout --signature="my sig" --cover-letter \
788 -1 >output &&
789 grep "my sig" output &&
790 test 2 = $(grep "my sig" output | wc -l)
791'
792
793test_expect_success 'format.signature="" suppresses signatures' '
794 git config format.signature "" &&
795 git format-patch --stdout -1 >output &&
796 check_patch output &&
797 ! grep "^-- \$" output
798'
799
800test_expect_success 'format-patch --no-signature suppresses signatures' '
801 git config --unset-all format.signature &&
802 git format-patch --stdout --no-signature -1 >output &&
803 check_patch output &&
804 ! grep "^-- \$" output
805'
806
807test_expect_success 'format-patch --signature="" suppresses signatures' '
808 git format-patch --stdout --signature="" -1 >output &&
809 check_patch output &&
810 ! grep "^-- \$" output
811'
812
813test_expect_success 'prepare mail-signature input' '
814 cat >mail-signature <<-\EOF
815
816 Test User <test.email@kernel.org>
817 http://git.kernel.org/cgit/git/git.git
818
819 git.kernel.org/?p=git/git.git;a=summary
820
821 EOF
822'
823
824test_expect_success '--signature-file=file works' '
825 git format-patch --stdout --signature-file=mail-signature -1 >output &&
826 check_patch output &&
827 sed -e "1,/^-- \$/d" <output >actual &&
828 {
829 cat mail-signature && echo
830 } >expect &&
831 test_cmp expect actual
832'
833
834test_expect_success 'format.signaturefile works' '
835 test_config format.signaturefile mail-signature &&
836 git format-patch --stdout -1 >output &&
837 check_patch output &&
838 sed -e "1,/^-- \$/d" <output >actual &&
839 {
840 cat mail-signature && echo
841 } >expect &&
842 test_cmp expect actual
843'
844
845test_expect_success '--no-signature suppresses format.signaturefile ' '
846 test_config format.signaturefile mail-signature &&
847 git format-patch --stdout --no-signature -1 >output &&
848 check_patch output &&
849 ! grep "^-- \$" output
850'
851
852test_expect_success '--signature-file overrides format.signaturefile' '
853 cat >other-mail-signature <<-\EOF &&
854 Use this other signature instead of mail-signature.
855 EOF
856 test_config format.signaturefile mail-signature &&
857 git format-patch --stdout \
858 --signature-file=other-mail-signature -1 >output &&
859 check_patch output &&
860 sed -e "1,/^-- \$/d" <output >actual &&
861 {
862 cat other-mail-signature && echo
863 } >expect &&
864 test_cmp expect actual
865'
866
867test_expect_success '--signature overrides format.signaturefile' '
868 test_config format.signaturefile mail-signature &&
869 git format-patch --stdout --signature="my sig" -1 >output &&
870 check_patch output &&
871 grep "my sig" output
872'
873
874test_expect_success TTY 'format-patch --stdout paginates' '
875 rm -f pager_used &&
876 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
877 test_path_is_file pager_used
878'
879
880 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
881 rm -f pager_used &&
882 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
883 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
884 test_path_is_missing pager_used &&
885 test_path_is_missing .git/pager_used
886'
887
888test_expect_success 'format-patch handles multi-line subjects' '
889 rm -rf patches/ &&
890 echo content >>file &&
891 for i in one two three; do echo $i; done >msg &&
892 git add file &&
893 git commit -F msg &&
894 git format-patch -o patches -1 &&
895 grep ^Subject: patches/0001-one.patch >actual &&
896 echo "Subject: [PATCH] one two three" >expect &&
897 test_cmp expect actual
898'
899
900test_expect_success 'format-patch handles multi-line encoded subjects' '
901 rm -rf patches/ &&
902 echo content >>file &&
903 for i in en två tre; do echo $i; done >msg &&
904 git add file &&
905 git commit -F msg &&
906 git format-patch -o patches -1 &&
907 grep ^Subject: patches/0001-en.patch >actual &&
908 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
909 test_cmp expect actual
910'
911
912M8="foo bar "
913M64=$M8$M8$M8$M8$M8$M8$M8$M8
914M512=$M64$M64$M64$M64$M64$M64$M64$M64
915cat >expect <<'EOF'
916Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
917 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
918 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
919 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
920 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
921 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
922 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
923EOF
924test_expect_success 'format-patch wraps extremely long subject (ascii)' '
925 echo content >>file &&
926 git add file &&
927 git commit -m "$M512" &&
928 git format-patch --stdout -1 >patch &&
929 sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
930 test_cmp expect subject
931'
932
933M8="föö bar "
934M64=$M8$M8$M8$M8$M8$M8$M8$M8
935M512=$M64$M64$M64$M64$M64$M64$M64$M64
936cat >expect <<'EOF'
937Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
938 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
939 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
940 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
941 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
942 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
943 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
944 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
945 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
946 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
947 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
948 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
949 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
950 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
951 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
952 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
953 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
954 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
955 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
956 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
957 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
958 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
959 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
960 =?UTF-8?q?bar?=
961EOF
962test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
963 rm -rf patches/ &&
964 echo content >>file &&
965 git add file &&
966 git commit -m "$M512" &&
967 git format-patch --stdout -1 >patch &&
968 sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
969 test_cmp expect subject
970'
971
972check_author() {
973 echo content >>file &&
974 git add file &&
975 GIT_AUTHOR_NAME=$1 git commit -m author-check &&
976 git format-patch --stdout -1 >patch &&
977 sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
978 test_cmp expect actual
979}
980
981cat >expect <<'EOF'
982From: "Foo B. Bar" <author@example.com>
983EOF
984test_expect_success 'format-patch quotes dot in from-headers' '
985 check_author "Foo B. Bar"
986'
987
988cat >expect <<'EOF'
989From: "Foo \"The Baz\" Bar" <author@example.com>
990EOF
991test_expect_success 'format-patch quotes double-quote in from-headers' '
992 check_author "Foo \"The Baz\" Bar"
993'
994
995cat >expect <<'EOF'
996From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
997EOF
998test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
999 check_author "Föo Bar"
1000'
1001
1002cat >expect <<'EOF'
1003From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1004EOF
1005test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1006 check_author "Föo B. Bar"
1007'
1008
1009cat >expect <<EOF
1010From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1011 <author@example.com>
1012EOF
1013test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1014 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1015'
1016
1017cat >expect <<'EOF'
1018From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1019 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1020 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1021EOF
1022test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1023 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"
1024'
1025
1026cat >expect <<'EOF'
1027From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1028 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1029 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1030EOF
1031test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1032 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"
1033'
1034
1035cat >expect <<'EOF'
1036From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1037 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1038 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1039 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1040 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1041EOF
1042test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1043 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"
1044'
1045
1046cat >expect <<'EOF'
1047Subject: header with . in it
1048EOF
1049test_expect_success 'subject lines do not have 822 atom-quoting' '
1050 echo content >>file &&
1051 git add file &&
1052 git commit -m "header with . in it" &&
1053 git format-patch -k -1 --stdout >patch &&
1054 grep ^Subject: patch >actual &&
1055 test_cmp expect actual
1056'
1057
1058cat >expect <<'EOF'
1059Subject: [PREFIX 1/1] header with . in it
1060EOF
1061test_expect_success 'subject prefixes have space prepended' '
1062 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1063 grep ^Subject: patch >actual &&
1064 test_cmp expect actual
1065'
1066
1067cat >expect <<'EOF'
1068Subject: [1/1] header with . in it
1069EOF
1070test_expect_success 'empty subject prefix does not have extra space' '
1071 git format-patch -n -1 --stdout --subject-prefix= >patch &&
1072 grep ^Subject: patch >actual &&
1073 test_cmp expect actual
1074'
1075
1076test_expect_success '--from=ident notices bogus ident' '
1077 test_must_fail git format-patch -1 --stdout --from=foo >patch
1078'
1079
1080test_expect_success '--from=ident replaces author' '
1081 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1082 cat >expect <<-\EOF &&
1083 From: Me <me@example.com>
1084
1085 From: A U Thor <author@example.com>
1086
1087 EOF
1088 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1089 test_cmp expect patch.head
1090'
1091
1092test_expect_success '--from uses committer ident' '
1093 git format-patch -1 --stdout --from >patch &&
1094 cat >expect <<-\EOF &&
1095 From: C O Mitter <committer@example.com>
1096
1097 From: A U Thor <author@example.com>
1098
1099 EOF
1100 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1101 test_cmp expect patch.head
1102'
1103
1104test_expect_success '--from omits redundant in-body header' '
1105 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1106 cat >expect <<-\EOF &&
1107 From: A U Thor <author@example.com>
1108
1109 EOF
1110 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1111 test_cmp expect patch.head
1112'
1113
1114test_expect_success 'in-body headers trigger content encoding' '
1115 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1116 test_when_finished "git reset --hard HEAD^" &&
1117 git format-patch -1 --stdout --from >patch &&
1118 cat >expect <<-\EOF &&
1119 From: C O Mitter <committer@example.com>
1120 Content-Type: text/plain; charset=UTF-8
1121
1122 From: éxötìc <author@example.com>
1123
1124 EOF
1125 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1126 test_cmp expect patch.head
1127'
1128
1129append_signoff()
1130{
1131 C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1132 git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1133 sed -n -e "1,/^---$/p" append_signoff.patch |
1134 egrep -n "^Subject|Sign|^$"
1135}
1136
1137test_expect_success 'signoff: commit with no body' '
1138 append_signoff </dev/null >actual &&
1139 cat <<\EOF | sed "s/EOL$//" >expected &&
11404:Subject: [PATCH] EOL
11418:
11429:Signed-off-by: C O Mitter <committer@example.com>
1143EOF
1144 test_cmp expected actual
1145'
1146
1147test_expect_success 'signoff: commit with only subject' '
1148 echo subject | append_signoff >actual &&
1149 cat >expected <<\EOF &&
11504:Subject: [PATCH] subject
11518:
11529:Signed-off-by: C O Mitter <committer@example.com>
1153EOF
1154 test_cmp expected actual
1155'
1156
1157test_expect_success 'signoff: commit with only subject that does not end with NL' '
1158 printf subject | append_signoff >actual &&
1159 cat >expected <<\EOF &&
11604:Subject: [PATCH] subject
11618:
11629:Signed-off-by: C O Mitter <committer@example.com>
1163EOF
1164 test_cmp expected actual
1165'
1166
1167test_expect_success 'signoff: no existing signoffs' '
1168 append_signoff <<\EOF >actual &&
1169subject
1170
1171body
1172EOF
1173 cat >expected <<\EOF &&
11744:Subject: [PATCH] subject
11758:
117610:
117711:Signed-off-by: C O Mitter <committer@example.com>
1178EOF
1179 test_cmp expected actual
1180'
1181
1182test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1183 printf "subject\n\nbody" | append_signoff >actual &&
1184 cat >expected <<\EOF &&
11854:Subject: [PATCH] subject
11868:
118710:
118811:Signed-off-by: C O Mitter <committer@example.com>
1189EOF
1190 test_cmp expected actual
1191'
1192
1193test_expect_success 'signoff: some random signoff' '
1194 append_signoff <<\EOF >actual &&
1195subject
1196
1197body
1198
1199Signed-off-by: my@house
1200EOF
1201 cat >expected <<\EOF &&
12024:Subject: [PATCH] subject
12038:
120410:
120511:Signed-off-by: my@house
120612:Signed-off-by: C O Mitter <committer@example.com>
1207EOF
1208 test_cmp expected actual
1209'
1210
1211test_expect_success 'signoff: misc conforming footer elements' '
1212 append_signoff <<\EOF >actual &&
1213subject
1214
1215body
1216
1217Signed-off-by: my@house
1218(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1219Tested-by: Some One <someone@example.com>
1220Bug: 1234
1221EOF
1222 cat >expected <<\EOF &&
12234:Subject: [PATCH] subject
12248:
122510:
122611:Signed-off-by: my@house
122715:Signed-off-by: C O Mitter <committer@example.com>
1228EOF
1229 test_cmp expected actual
1230'
1231
1232test_expect_success 'signoff: some random signoff-alike' '
1233 append_signoff <<\EOF >actual &&
1234subject
1235
1236body
1237Fooled-by-me: my@house
1238EOF
1239 cat >expected <<\EOF &&
12404:Subject: [PATCH] subject
12418:
124211:
124312:Signed-off-by: C O Mitter <committer@example.com>
1244EOF
1245 test_cmp expected actual
1246'
1247
1248test_expect_success 'signoff: not really a signoff' '
1249 append_signoff <<\EOF >actual &&
1250subject
1251
1252I want to mention about Signed-off-by: here.
1253EOF
1254 cat >expected <<\EOF &&
12554:Subject: [PATCH] subject
12568:
12579:I want to mention about Signed-off-by: here.
125810:
125911:Signed-off-by: C O Mitter <committer@example.com>
1260EOF
1261 test_cmp expected actual
1262'
1263
1264test_expect_success 'signoff: not really a signoff (2)' '
1265 append_signoff <<\EOF >actual &&
1266subject
1267
1268My unfortunate
1269Signed-off-by: example happens to be wrapped here.
1270EOF
1271 cat >expected <<\EOF &&
12724:Subject: [PATCH] subject
12738:
127410:Signed-off-by: example happens to be wrapped here.
127511:
127612:Signed-off-by: C O Mitter <committer@example.com>
1277EOF
1278 test_cmp expected actual
1279'
1280
1281test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1282 append_signoff <<\EOF >actual &&
1283subject
1284
1285Signed-off-by: my@house
1286Signed-off-by: your@house
1287
1288A lot of houses.
1289EOF
1290 cat >expected <<\EOF &&
12914:Subject: [PATCH] subject
12928:
12939:Signed-off-by: my@house
129410:Signed-off-by: your@house
129511:
129613:
129714:Signed-off-by: C O Mitter <committer@example.com>
1298EOF
1299 test_cmp expected actual
1300'
1301
1302test_expect_success 'signoff: the same signoff at the end' '
1303 append_signoff <<\EOF >actual &&
1304subject
1305
1306body
1307
1308Signed-off-by: C O Mitter <committer@example.com>
1309EOF
1310 cat >expected <<\EOF &&
13114:Subject: [PATCH] subject
13128:
131310:
131411:Signed-off-by: C O Mitter <committer@example.com>
1315EOF
1316 test_cmp expected actual
1317'
1318
1319test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1320 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1321 append_signoff >actual &&
1322 cat >expected <<\EOF &&
13234:Subject: [PATCH] subject
13248:
13259:Signed-off-by: C O Mitter <committer@example.com>
1326EOF
1327 test_cmp expected actual
1328'
1329
1330test_expect_success 'signoff: the same signoff NOT at the end' '
1331 append_signoff <<\EOF >actual &&
1332subject
1333
1334body
1335
1336Signed-off-by: C O Mitter <committer@example.com>
1337Signed-off-by: my@house
1338EOF
1339 cat >expected <<\EOF &&
13404:Subject: [PATCH] subject
13418:
134210:
134311:Signed-off-by: C O Mitter <committer@example.com>
134412:Signed-off-by: my@house
1345EOF
1346 test_cmp expected actual
1347'
1348
1349test_expect_success 'signoff: detect garbage in non-conforming footer' '
1350 append_signoff <<\EOF >actual &&
1351subject
1352
1353body
1354
1355Tested-by: my@house
1356Some Trash
1357Signed-off-by: C O Mitter <committer@example.com>
1358EOF
1359 cat >expected <<\EOF &&
13604:Subject: [PATCH] subject
13618:
136210:
136313:Signed-off-by: C O Mitter <committer@example.com>
136414:
136515:Signed-off-by: C O Mitter <committer@example.com>
1366EOF
1367 test_cmp expected actual
1368'
1369
1370test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1371 append_signoff <<\EOF >actual &&
1372subject
1373
1374body
1375
1376Reviewed-id: Noone
1377Tested-by: my@house
1378Change-id: Ideadbeef
1379Signed-off-by: C O Mitter <committer@example.com>
1380Bug: 1234
1381EOF
1382 cat >expected <<\EOF &&
13834:Subject: [PATCH] subject
13848:
138510:
138614:Signed-off-by: C O Mitter <committer@example.com>
1387EOF
1388 test_cmp expected actual
1389'
1390
1391test_expect_success 'format patch ignores color.ui' '
1392 test_unconfig color.ui &&
1393 git format-patch --stdout -1 >expect &&
1394 test_config color.ui always &&
1395 git format-patch --stdout -1 >actual &&
1396 test_cmp expect actual
1397'
1398
1399test_expect_success 'cover letter using branch description (1)' '
1400 git checkout rebuild-1 &&
1401 test_config branch.rebuild-1.description hello &&
1402 git format-patch --stdout --cover-letter master >actual &&
1403 grep hello actual >/dev/null
1404'
1405
1406test_expect_success 'cover letter using branch description (2)' '
1407 git checkout rebuild-1 &&
1408 test_config branch.rebuild-1.description hello &&
1409 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1410 grep hello actual >/dev/null
1411'
1412
1413test_expect_success 'cover letter using branch description (3)' '
1414 git checkout rebuild-1 &&
1415 test_config branch.rebuild-1.description hello &&
1416 git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1417 grep hello actual >/dev/null
1418'
1419
1420test_expect_success 'cover letter using branch description (4)' '
1421 git checkout rebuild-1 &&
1422 test_config branch.rebuild-1.description hello &&
1423 git format-patch --stdout --cover-letter master.. >actual &&
1424 grep hello actual >/dev/null
1425'
1426
1427test_expect_success 'cover letter using branch description (5)' '
1428 git checkout rebuild-1 &&
1429 test_config branch.rebuild-1.description hello &&
1430 git format-patch --stdout --cover-letter -2 HEAD >actual &&
1431 grep hello actual >/dev/null
1432'
1433
1434test_expect_success 'cover letter using branch description (6)' '
1435 git checkout rebuild-1 &&
1436 test_config branch.rebuild-1.description hello &&
1437 git format-patch --stdout --cover-letter -2 >actual &&
1438 grep hello actual >/dev/null
1439'
1440
1441test_expect_success 'cover letter with nothing' '
1442 git format-patch --stdout --cover-letter >actual &&
1443 test_line_count = 0 actual
1444'
1445
1446test_expect_success 'cover letter auto' '
1447 mkdir -p tmp &&
1448 test_when_finished "rm -rf tmp;
1449 git config --unset format.coverletter" &&
1450
1451 git config format.coverletter auto &&
1452 git format-patch -o tmp -1 >list &&
1453 test_line_count = 1 list &&
1454 git format-patch -o tmp -2 >list &&
1455 test_line_count = 3 list
1456'
1457
1458test_expect_success 'cover letter auto user override' '
1459 mkdir -p tmp &&
1460 test_when_finished "rm -rf tmp;
1461 git config --unset format.coverletter" &&
1462
1463 git config format.coverletter auto &&
1464 git format-patch -o tmp --cover-letter -1 >list &&
1465 test_line_count = 2 list &&
1466 git format-patch -o tmp --cover-letter -2 >list &&
1467 test_line_count = 3 list &&
1468 git format-patch -o tmp --no-cover-letter -1 >list &&
1469 test_line_count = 1 list &&
1470 git format-patch -o tmp --no-cover-letter -2 >list &&
1471 test_line_count = 2 list
1472'
1473
1474test_expect_success 'format-patch --zero-commit' '
1475 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1476 grep "^From " patch2 | sort | uniq >actual &&
1477 echo "From $_z40 Mon Sep 17 00:00:00 2001" >expect &&
1478 test_cmp expect actual
1479'
1480
1481test_expect_success 'From line has expected format' '
1482 git format-patch --stdout v2..v1 >patch2 &&
1483 grep "^From " patch2 >from &&
1484 grep "^From $_x40 Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1485 test_cmp from filtered
1486'
1487
1488test_expect_success 'format-patch format.outputDirectory option' '
1489 test_config format.outputDirectory patches &&
1490 rm -fr patches &&
1491 git format-patch master..side &&
1492 test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
1493'
1494
1495test_expect_success 'format-patch -o overrides format.outputDirectory' '
1496 test_config format.outputDirectory patches &&
1497 rm -fr patches patchset &&
1498 git format-patch master..side -o patchset &&
1499 test_path_is_missing patches &&
1500 test_path_is_dir patchset
1501'
1502
1503test_expect_success 'format-patch --base' '
1504 git checkout side &&
1505 git format-patch --stdout --base=HEAD~3 -1 >patch &&
1506 grep "^base-commit:" patch >actual &&
1507 grep "^prerequisite-patch-id:" patch >>actual &&
1508 echo "base-commit: $(git rev-parse HEAD~3)" >expected &&
1509 echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1510 echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1511 test_cmp expected actual
1512'
1513
1514test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1515 test_must_fail git format-patch --base=HEAD -2 &&
1516 test_must_fail git format-patch --base=HEAD~1 -2 &&
1517 git format-patch --stdout --base=HEAD~2 -2 >patch &&
1518 grep "^base-commit:" patch >actual &&
1519 echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
1520 test_cmp expected actual
1521'
1522
1523test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1524 # For history as below:
1525 #
1526 # ---Q---P---Z---Y---*---X
1527 # \ /
1528 # ------------W
1529 #
1530 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1531 git checkout -b topic1 master &&
1532 git rev-parse HEAD >commit-id-base &&
1533 test_commit P &&
1534 git rev-parse HEAD >commit-id-P &&
1535 test_commit Z &&
1536 git rev-parse HEAD >commit-id-Z &&
1537 test_commit Y &&
1538 git checkout -b topic2 master &&
1539 test_commit W &&
1540 git merge topic1 &&
1541 test_commit X &&
1542 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1543 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1544 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1545 grep "^base-commit:" patch >actual &&
1546 echo "base-commit: $(cat commit-id-base)" >expected &&
1547 test_cmp expected actual
1548'
1549
1550test_expect_success 'format-patch --base=auto' '
1551 git checkout -b upstream master &&
1552 git checkout -b local upstream &&
1553 git branch --set-upstream-to=upstream &&
1554 test_commit N1 &&
1555 test_commit N2 &&
1556 git format-patch --stdout --base=auto -2 >patch &&
1557 grep "^base-commit:" patch >actual &&
1558 echo "base-commit: $(git rev-parse upstream)" >expected &&
1559 test_cmp expected actual
1560'
1561
1562test_expect_success 'format-patch errors out when history involves criss-cross' '
1563 # setup criss-cross history
1564 #
1565 # B---M1---D
1566 # / \ /
1567 # A X
1568 # \ / \
1569 # C---M2---E
1570 #
1571 git checkout master &&
1572 test_commit A &&
1573 git checkout -b xb master &&
1574 test_commit B &&
1575 git checkout -b xc master &&
1576 test_commit C &&
1577 git checkout -b xbc xb -- &&
1578 git merge xc &&
1579 git checkout -b xcb xc -- &&
1580 git branch --set-upstream-to=xbc &&
1581 git merge xb &&
1582 git checkout xbc &&
1583 test_commit D &&
1584 git checkout xcb &&
1585 test_commit E &&
1586 test_must_fail git format-patch --base=auto -1
1587'
1588
1589test_expect_success 'format-patch format.useAutoBaseoption' '
1590 test_when_finished "git config --unset format.useAutoBase" &&
1591 git checkout local &&
1592 git config format.useAutoBase true &&
1593 git format-patch --stdout -1 >patch &&
1594 grep "^base-commit:" patch >actual &&
1595 echo "base-commit: $(git rev-parse upstream)" >expected &&
1596 test_cmp expected actual
1597'
1598
1599test_expect_success 'format-patch --base overrides format.useAutoBase' '
1600 test_when_finished "git config --unset format.useAutoBase" &&
1601 git config format.useAutoBase true &&
1602 git format-patch --stdout --base=HEAD~1 -1 >patch &&
1603 grep "^base-commit:" patch >actual &&
1604 echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
1605 test_cmp expected actual
1606'
1607
1608test_expect_success 'format-patch --pretty=mboxrd' '
1609 sp=" " &&
1610 cat >msg <<-INPUT_END &&
1611 mboxrd should escape the body
1612
1613 From could trip up a loose mbox parser
1614 >From extra escape for reversibility
1615 >>From extra escape for reversibility 2
1616 from lower case not escaped
1617 Fromm bad speling not escaped
1618 From with leading space not escaped
1619
1620 F
1621 From
1622 From$sp
1623 From $sp
1624 From $sp
1625 INPUT_END
1626
1627 cat >expect <<-INPUT_END &&
1628 >From could trip up a loose mbox parser
1629 >>From extra escape for reversibility
1630 >>>From extra escape for reversibility 2
1631 from lower case not escaped
1632 Fromm bad speling not escaped
1633 From with leading space not escaped
1634
1635 F
1636 From
1637 From
1638 From
1639 From
1640 INPUT_END
1641
1642 C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
1643 git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
1644 git grep -h --no-index -A11 \
1645 "^>From could trip up a loose mbox parser" patch >actual &&
1646 test_cmp expect actual
1647'
1648
1649test_done