6321ac88aa65a9c9a9d5b114b01165e687363047
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
10test_expect_success setup '
11
12 for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
13 cat file >elif &&
14 git add file elif &&
15 test_tick &&
16 git commit -m Initial &&
17 git checkout -b side &&
18
19 for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
20 test_chmod +x elif &&
21 test_tick &&
22 git commit -m "Side changes #1" &&
23
24 for i in D E F; do echo "$i"; done >>file &&
25 git update-index file &&
26 test_tick &&
27 git commit -m "Side changes #2" &&
28 git tag C2 &&
29
30 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
31 git update-index file &&
32 test_tick &&
33 git commit -m "Side changes #3 with \\n backslash-n in it." &&
34
35 git checkout master &&
36 git diff-tree -p C2 | git apply --index &&
37 test_tick &&
38 git commit -m "Master accepts moral equivalent of #2"
39
40'
41
42test_expect_success "format-patch --ignore-if-in-upstream" '
43
44 git format-patch --stdout master..side >patch0 &&
45 cnt=`grep "^From " patch0 | wc -l` &&
46 test $cnt = 3
47
48'
49
50test_expect_success "format-patch --ignore-if-in-upstream" '
51
52 git format-patch --stdout \
53 --ignore-if-in-upstream master..side >patch1 &&
54 cnt=`grep "^From " patch1 | wc -l` &&
55 test $cnt = 2
56
57'
58
59test_expect_success "format-patch result applies" '
60
61 git checkout -b rebuild-0 master &&
62 git am -3 patch0 &&
63 cnt=`git rev-list master.. | wc -l` &&
64 test $cnt = 2
65'
66
67test_expect_success "format-patch --ignore-if-in-upstream result applies" '
68
69 git checkout -b rebuild-1 master &&
70 git am -3 patch1 &&
71 cnt=`git rev-list master.. | wc -l` &&
72 test $cnt = 2
73'
74
75test_expect_success 'commit did not screw up the log message' '
76
77 git cat-file commit side | grep "^Side .* with .* backslash-n"
78
79'
80
81test_expect_success 'format-patch did not screw up the log message' '
82
83 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
84 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
85
86'
87
88test_expect_success 'replay did not screw up the log message' '
89
90 git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
91
92'
93
94test_expect_success 'extra headers' '
95
96 git config format.headers "To: R. E. Cipient <rcipient@example.com>
97" &&
98 git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>
99" &&
100 git format-patch --stdout master..side > patch2 &&
101 sed -e "/^\$/q" patch2 > hdrs2 &&
102 grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs2 &&
103 grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs2
104
105'
106
107test_expect_success 'extra headers without newlines' '
108
109 git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
110 git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>" &&
111 git format-patch --stdout master..side >patch3 &&
112 sed -e "/^\$/q" patch3 > hdrs3 &&
113 grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs3 &&
114 grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs3
115
116'
117
118test_expect_success 'extra headers with multiple To:s' '
119
120 git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
121 git config --add format.headers "To: S. E. Cipient <scipient@example.com>" &&
122 git format-patch --stdout master..side > patch4 &&
123 sed -e "/^\$/q" patch4 > hdrs4 &&
124 grep "^To: R. E. Cipient <rcipient@example.com>,\$" hdrs4 &&
125 grep "^ *S. E. Cipient <scipient@example.com>\$" hdrs4
126'
127
128test_expect_success 'additional command line cc' '
129
130 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
131 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
132 grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch5 &&
133 grep "^ *S. E. Cipient <scipient@example.com>\$" patch5
134'
135
136test_expect_success 'command line headers' '
137
138 git config --unset-all format.headers &&
139 git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
140 grep "^Cc: R. E. Cipient <rcipient@example.com>\$" patch6
141'
142
143test_expect_success 'configuration headers and command line headers' '
144
145 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
146 git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
147 grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch7 &&
148 grep "^ *S. E. Cipient <scipient@example.com>\$" patch7
149'
150
151test_expect_success 'command line To: header' '
152
153 git config --unset-all format.headers &&
154 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
155 grep "^To: R. E. Cipient <rcipient@example.com>\$" patch8
156'
157
158test_expect_success 'configuration To: header' '
159
160 git config format.to "R. E. Cipient <rcipient@example.com>" &&
161 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
162 grep "^To: R. E. Cipient <rcipient@example.com>\$" patch9
163'
164
165test_expect_success '--no-to overrides config.to' '
166
167 git config --replace-all format.to \
168 "R. E. Cipient <rcipient@example.com>" &&
169 git format-patch --no-to --stdout master..side |
170 sed -e "/^\$/q" >patch10 &&
171 ! grep "^To: R. E. Cipient <rcipient@example.com>\$" patch10
172'
173
174test_expect_success '--no-to and --to replaces config.to' '
175
176 git config --replace-all format.to \
177 "Someone <someone@out.there>" &&
178 git format-patch --no-to --to="Someone Else <else@out.there>" \
179 --stdout master..side |
180 sed -e "/^\$/q" >patch11 &&
181 ! grep "^To: Someone <someone@out.there>\$" patch11 &&
182 grep "^To: Someone Else <else@out.there>\$" patch11
183'
184
185test_expect_success '--no-cc overrides config.cc' '
186
187 git config --replace-all format.cc \
188 "C. E. Cipient <rcipient@example.com>" &&
189 git format-patch --no-cc --stdout master..side |
190 sed -e "/^\$/q" >patch12 &&
191 ! grep "^Cc: C. E. Cipient <rcipient@example.com>\$" patch12
192'
193
194test_expect_success '--no-add-headers overrides config.headers' '
195
196 git config --replace-all format.headers \
197 "Header1: B. E. Cipient <rcipient@example.com>" &&
198 git format-patch --no-add-headers --stdout master..side |
199 sed -e "/^\$/q" >patch13 &&
200 ! grep "^Header1: B. E. Cipient <rcipient@example.com>\$" patch13
201'
202
203test_expect_success 'multiple files' '
204
205 rm -rf patches/ &&
206 git checkout side &&
207 git format-patch -o patches/ master &&
208 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
209'
210
211check_threading () {
212 expect="$1" &&
213 shift &&
214 (git format-patch --stdout "$@"; echo $? > status.out) |
215 # Prints everything between the Message-ID and In-Reply-To,
216 # and replaces all Message-ID-lookalikes by a sequence number
217 perl -ne '
218 if (/^(message-id|references|in-reply-to)/i) {
219 $printing = 1;
220 } elsif (/^\S/) {
221 $printing = 0;
222 }
223 if ($printing) {
224 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
225 for $k (keys %h) {s/$k/$h{$k}/};
226 print;
227 }
228 print "---\n" if /^From /i;
229 ' > actual &&
230 test 0 = "$(cat status.out)" &&
231 test_cmp "$expect" actual
232}
233
234cat >> expect.no-threading <<EOF
235---
236---
237---
238EOF
239
240test_expect_success 'no threading' '
241 git checkout side &&
242 check_threading expect.no-threading master
243'
244
245cat > expect.thread <<EOF
246---
247Message-Id: <0>
248---
249Message-Id: <1>
250In-Reply-To: <0>
251References: <0>
252---
253Message-Id: <2>
254In-Reply-To: <0>
255References: <0>
256EOF
257
258test_expect_success 'thread' '
259 check_threading expect.thread --thread master
260'
261
262cat > expect.in-reply-to <<EOF
263---
264Message-Id: <0>
265In-Reply-To: <1>
266References: <1>
267---
268Message-Id: <2>
269In-Reply-To: <1>
270References: <1>
271---
272Message-Id: <3>
273In-Reply-To: <1>
274References: <1>
275EOF
276
277test_expect_success 'thread in-reply-to' '
278 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
279 --thread master
280'
281
282cat > expect.cover-letter <<EOF
283---
284Message-Id: <0>
285---
286Message-Id: <1>
287In-Reply-To: <0>
288References: <0>
289---
290Message-Id: <2>
291In-Reply-To: <0>
292References: <0>
293---
294Message-Id: <3>
295In-Reply-To: <0>
296References: <0>
297EOF
298
299test_expect_success 'thread cover-letter' '
300 check_threading expect.cover-letter --cover-letter --thread master
301'
302
303cat > expect.cl-irt <<EOF
304---
305Message-Id: <0>
306In-Reply-To: <1>
307References: <1>
308---
309Message-Id: <2>
310In-Reply-To: <0>
311References: <1>
312 <0>
313---
314Message-Id: <3>
315In-Reply-To: <0>
316References: <1>
317 <0>
318---
319Message-Id: <4>
320In-Reply-To: <0>
321References: <1>
322 <0>
323EOF
324
325test_expect_success 'thread cover-letter in-reply-to' '
326 check_threading expect.cl-irt --cover-letter \
327 --in-reply-to="<test.message>" --thread master
328'
329
330test_expect_success 'thread explicit shallow' '
331 check_threading expect.cl-irt --cover-letter \
332 --in-reply-to="<test.message>" --thread=shallow master
333'
334
335cat > expect.deep <<EOF
336---
337Message-Id: <0>
338---
339Message-Id: <1>
340In-Reply-To: <0>
341References: <0>
342---
343Message-Id: <2>
344In-Reply-To: <1>
345References: <0>
346 <1>
347EOF
348
349test_expect_success 'thread deep' '
350 check_threading expect.deep --thread=deep master
351'
352
353cat > expect.deep-irt <<EOF
354---
355Message-Id: <0>
356In-Reply-To: <1>
357References: <1>
358---
359Message-Id: <2>
360In-Reply-To: <0>
361References: <1>
362 <0>
363---
364Message-Id: <3>
365In-Reply-To: <2>
366References: <1>
367 <0>
368 <2>
369EOF
370
371test_expect_success 'thread deep in-reply-to' '
372 check_threading expect.deep-irt --thread=deep \
373 --in-reply-to="<test.message>" master
374'
375
376cat > expect.deep-cl <<EOF
377---
378Message-Id: <0>
379---
380Message-Id: <1>
381In-Reply-To: <0>
382References: <0>
383---
384Message-Id: <2>
385In-Reply-To: <1>
386References: <0>
387 <1>
388---
389Message-Id: <3>
390In-Reply-To: <2>
391References: <0>
392 <1>
393 <2>
394EOF
395
396test_expect_success 'thread deep cover-letter' '
397 check_threading expect.deep-cl --cover-letter --thread=deep master
398'
399
400cat > expect.deep-cl-irt <<EOF
401---
402Message-Id: <0>
403In-Reply-To: <1>
404References: <1>
405---
406Message-Id: <2>
407In-Reply-To: <0>
408References: <1>
409 <0>
410---
411Message-Id: <3>
412In-Reply-To: <2>
413References: <1>
414 <0>
415 <2>
416---
417Message-Id: <4>
418In-Reply-To: <3>
419References: <1>
420 <0>
421 <2>
422 <3>
423EOF
424
425test_expect_success 'thread deep cover-letter in-reply-to' '
426 check_threading expect.deep-cl-irt --cover-letter \
427 --in-reply-to="<test.message>" --thread=deep master
428'
429
430test_expect_success 'thread via config' '
431 git config format.thread true &&
432 check_threading expect.thread master
433'
434
435test_expect_success 'thread deep via config' '
436 git config format.thread deep &&
437 check_threading expect.deep master
438'
439
440test_expect_success 'thread config + override' '
441 git config format.thread deep &&
442 check_threading expect.thread --thread master
443'
444
445test_expect_success 'thread config + --no-thread' '
446 git config format.thread deep &&
447 check_threading expect.no-threading --no-thread master
448'
449
450test_expect_success 'excessive subject' '
451
452 rm -rf patches/ &&
453 git checkout side &&
454 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
455 git update-index file &&
456 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." &&
457 git format-patch -o patches/ master..side &&
458 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
459'
460
461test_expect_success 'cover-letter inherits diff options' '
462
463 git mv file foo &&
464 git commit -m foo &&
465 git format-patch --cover-letter -1 &&
466 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
467 git format-patch --cover-letter -1 -M &&
468 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
469
470'
471
472cat > expect << EOF
473 This is an excessively long subject line for a message due to the
474 habit some projects have of not having a short, one-line subject at
475 the start of the commit message, but rather sticking a whole
476 paragraph right at the start as the only thing in the commit
477 message. It had better not become the filename for the patch.
478 foo
479
480EOF
481
482test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
483
484 git format-patch --cover-letter -2 &&
485 sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
486 test_cmp expect output
487
488'
489
490cat > expect << EOF
491---
492 file | 16 ++++++++++++++++
493 1 files changed, 16 insertions(+), 0 deletions(-)
494
495diff --git a/file b/file
496index 40f36c6..2dc5c23 100644
497--- a/file
498+++ b/file
499@@ -13,4 +13,20 @@ C
500 10
501 D
502 E
503 F
504+5
505EOF
506
507test_expect_success 'format-patch respects -U' '
508
509 git format-patch -U4 -2 &&
510 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
511 test_cmp expect output
512
513'
514
515cat > expect << EOF
516
517diff --git a/file b/file
518index 40f36c6..2dc5c23 100644
519--- a/file
520+++ b/file
521@@ -14,3 +14,19 @@ C
522 D
523 E
524 F
525+5
526EOF
527
528test_expect_success 'format-patch -p suppresses stat' '
529
530 git format-patch -p -2 &&
531 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
532 test_cmp expect output
533
534'
535
536test_expect_success 'format-patch from a subdirectory (1)' '
537 filename=$(
538 rm -rf sub &&
539 mkdir -p sub/dir &&
540 cd sub/dir &&
541 git format-patch -1
542 ) &&
543 case "$filename" in
544 0*)
545 ;; # ok
546 *)
547 echo "Oops? $filename"
548 false
549 ;;
550 esac &&
551 test -f "$filename"
552'
553
554test_expect_success 'format-patch from a subdirectory (2)' '
555 filename=$(
556 rm -rf sub &&
557 mkdir -p sub/dir &&
558 cd sub/dir &&
559 git format-patch -1 -o ..
560 ) &&
561 case "$filename" in
562 ../0*)
563 ;; # ok
564 *)
565 echo "Oops? $filename"
566 false
567 ;;
568 esac &&
569 basename=$(expr "$filename" : ".*/\(.*\)") &&
570 test -f "sub/$basename"
571'
572
573test_expect_success 'format-patch from a subdirectory (3)' '
574 rm -f 0* &&
575 filename=$(
576 rm -rf sub &&
577 mkdir -p sub/dir &&
578 cd sub/dir &&
579 git format-patch -1 -o "$TRASH_DIRECTORY"
580 ) &&
581 basename=$(expr "$filename" : ".*/\(.*\)") &&
582 test -f "$basename"
583'
584
585test_expect_success 'format-patch --in-reply-to' '
586 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
587 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
588 grep "^References: <baz@foo.bar>" patch8
589'
590
591test_expect_success 'format-patch --signoff' '
592 git format-patch -1 --signoff --stdout |
593 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
594'
595
596echo "fatal: --name-only does not make sense" > expect.name-only
597echo "fatal: --name-status does not make sense" > expect.name-status
598echo "fatal: --check does not make sense" > expect.check
599
600test_expect_success 'options no longer allowed for format-patch' '
601 test_must_fail git format-patch --name-only 2> output &&
602 test_cmp expect.name-only output &&
603 test_must_fail git format-patch --name-status 2> output &&
604 test_cmp expect.name-status output &&
605 test_must_fail git format-patch --check 2> output &&
606 test_cmp expect.check output'
607
608test_expect_success 'format-patch --numstat should produce a patch' '
609 git format-patch --numstat --stdout master..side > output &&
610 test 6 = $(grep "^diff --git a/" output | wc -l)'
611
612test_expect_success 'format-patch -- <path>' '
613 git format-patch master..side -- file 2>error &&
614 ! grep "Use .--" error
615'
616
617test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
618 git format-patch --ignore-if-in-upstream HEAD
619'
620
621test_done