1 #!/bin/sh
2 #
3 # Copyright (c) 2006 Junio C Hamano
4 #
6 test_description='various format-patch tests'
8 . ./test-lib.sh
10 test_expect_success setup '
12 for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
13 cat file >elif &&
14 git add file elif &&
15 test_tick &&
16 git commit -m Initial &&
17 git checkout -b side &&
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" &&
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 &&
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." &&
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"
40 '
42 test_expect_success "format-patch --ignore-if-in-upstream" '
44 git format-patch --stdout master..side >patch0 &&
45 cnt=`grep "^From " patch0 | wc -l` &&
46 test $cnt = 3
48 '
50 test_expect_success "format-patch --ignore-if-in-upstream" '
52 git format-patch --stdout \
53 --ignore-if-in-upstream master..side >patch1 &&
54 cnt=`grep "^From " patch1 | wc -l` &&
55 test $cnt = 2
57 '
59 test_expect_success "format-patch result applies" '
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 '
67 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
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 '
75 test_expect_success 'commit did not screw up the log message' '
77 git cat-file commit side | grep "^Side .* with .* backslash-n"
79 '
81 test_expect_success 'format-patch did not screw up the log message' '
83 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
84 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
86 '
88 test_expect_success 'replay did not screw up the log message' '
90 git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
92 '
94 test_expect_success 'extra headers' '
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
105 '
107 test_expect_success 'extra headers without newlines' '
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
116 '
118 test_expect_success 'extra headers with multiple To:s' '
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 '
128 test_expect_success 'additional command line cc' '
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 '
136 test_expect_success 'command line headers' '
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 '
143 test_expect_success 'configuration headers and command line headers' '
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 '
151 test_expect_success 'command line To: header' '
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 '
158 test_expect_success 'configuration To: header' '
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 '
165 test_expect_success '--no-to overrides config.to' '
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 '
174 test_expect_success '--no-to and --to replaces config.to' '
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 '
185 test_expect_success '--no-cc overrides config.cc' '
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 '
194 test_expect_success '--no-add-headers overrides config.headers' '
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 '
203 test_expect_success 'multiple files' '
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 '
211 check_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 }
234 cat >> expect.no-threading <<EOF
235 ---
236 ---
237 ---
238 EOF
240 test_expect_success 'no threading' '
241 git checkout side &&
242 check_threading expect.no-threading master
243 '
245 cat > expect.thread <<EOF
246 ---
247 Message-Id: <0>
248 ---
249 Message-Id: <1>
250 In-Reply-To: <0>
251 References: <0>
252 ---
253 Message-Id: <2>
254 In-Reply-To: <0>
255 References: <0>
256 EOF
258 test_expect_success 'thread' '
259 check_threading expect.thread --thread master
260 '
262 cat > expect.in-reply-to <<EOF
263 ---
264 Message-Id: <0>
265 In-Reply-To: <1>
266 References: <1>
267 ---
268 Message-Id: <2>
269 In-Reply-To: <1>
270 References: <1>
271 ---
272 Message-Id: <3>
273 In-Reply-To: <1>
274 References: <1>
275 EOF
277 test_expect_success 'thread in-reply-to' '
278 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
279 --thread master
280 '
282 cat > expect.cover-letter <<EOF
283 ---
284 Message-Id: <0>
285 ---
286 Message-Id: <1>
287 In-Reply-To: <0>
288 References: <0>
289 ---
290 Message-Id: <2>
291 In-Reply-To: <0>
292 References: <0>
293 ---
294 Message-Id: <3>
295 In-Reply-To: <0>
296 References: <0>
297 EOF
299 test_expect_success 'thread cover-letter' '
300 check_threading expect.cover-letter --cover-letter --thread master
301 '
303 cat > expect.cl-irt <<EOF
304 ---
305 Message-Id: <0>
306 In-Reply-To: <1>
307 References: <1>
308 ---
309 Message-Id: <2>
310 In-Reply-To: <0>
311 References: <1>
312 <0>
313 ---
314 Message-Id: <3>
315 In-Reply-To: <0>
316 References: <1>
317 <0>
318 ---
319 Message-Id: <4>
320 In-Reply-To: <0>
321 References: <1>
322 <0>
323 EOF
325 test_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 '
330 test_expect_success 'thread explicit shallow' '
331 check_threading expect.cl-irt --cover-letter \
332 --in-reply-to="<test.message>" --thread=shallow master
333 '
335 cat > expect.deep <<EOF
336 ---
337 Message-Id: <0>
338 ---
339 Message-Id: <1>
340 In-Reply-To: <0>
341 References: <0>
342 ---
343 Message-Id: <2>
344 In-Reply-To: <1>
345 References: <0>
346 <1>
347 EOF
349 test_expect_success 'thread deep' '
350 check_threading expect.deep --thread=deep master
351 '
353 cat > expect.deep-irt <<EOF
354 ---
355 Message-Id: <0>
356 In-Reply-To: <1>
357 References: <1>
358 ---
359 Message-Id: <2>
360 In-Reply-To: <0>
361 References: <1>
362 <0>
363 ---
364 Message-Id: <3>
365 In-Reply-To: <2>
366 References: <1>
367 <0>
368 <2>
369 EOF
371 test_expect_success 'thread deep in-reply-to' '
372 check_threading expect.deep-irt --thread=deep \
373 --in-reply-to="<test.message>" master
374 '
376 cat > expect.deep-cl <<EOF
377 ---
378 Message-Id: <0>
379 ---
380 Message-Id: <1>
381 In-Reply-To: <0>
382 References: <0>
383 ---
384 Message-Id: <2>
385 In-Reply-To: <1>
386 References: <0>
387 <1>
388 ---
389 Message-Id: <3>
390 In-Reply-To: <2>
391 References: <0>
392 <1>
393 <2>
394 EOF
396 test_expect_success 'thread deep cover-letter' '
397 check_threading expect.deep-cl --cover-letter --thread=deep master
398 '
400 cat > expect.deep-cl-irt <<EOF
401 ---
402 Message-Id: <0>
403 In-Reply-To: <1>
404 References: <1>
405 ---
406 Message-Id: <2>
407 In-Reply-To: <0>
408 References: <1>
409 <0>
410 ---
411 Message-Id: <3>
412 In-Reply-To: <2>
413 References: <1>
414 <0>
415 <2>
416 ---
417 Message-Id: <4>
418 In-Reply-To: <3>
419 References: <1>
420 <0>
421 <2>
422 <3>
423 EOF
425 test_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 '
430 test_expect_success 'thread via config' '
431 git config format.thread true &&
432 check_threading expect.thread master
433 '
435 test_expect_success 'thread deep via config' '
436 git config format.thread deep &&
437 check_threading expect.deep master
438 '
440 test_expect_success 'thread config + override' '
441 git config format.thread deep &&
442 check_threading expect.thread --thread master
443 '
445 test_expect_success 'thread config + --no-thread' '
446 git config format.thread deep &&
447 check_threading expect.no-threading --no-thread master
448 '
450 test_expect_success 'excessive subject' '
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 '
461 test_expect_success 'cover-letter inherits diff options' '
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
470 '
472 cat > 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
480 EOF
482 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
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
488 '
490 cat > expect << EOF
491 ---
492 file | 16 ++++++++++++++++
493 1 files changed, 16 insertions(+), 0 deletions(-)
495 diff --git a/file b/file
496 index 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
505 EOF
507 test_expect_success 'format-patch respects -U' '
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
513 '
515 cat > expect << EOF
517 diff --git a/file b/file
518 index 40f36c6..2dc5c23 100644
519 --- a/file
520 +++ b/file
521 @@ -14,3 +14,19 @@ C
522 D
523 E
524 F
525 +5
526 EOF
528 test_expect_success 'format-patch -p suppresses stat' '
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
534 '
536 test_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 '
554 test_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 '
573 test_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 '
585 test_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 '
591 test_expect_success 'format-patch --signoff' '
592 git format-patch -1 --signoff --stdout |
593 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
594 '
596 echo "fatal: --name-only does not make sense" > expect.name-only
597 echo "fatal: --name-status does not make sense" > expect.name-status
598 echo "fatal: --check does not make sense" > expect.check
600 test_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'
608 test_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)'
612 test_expect_success 'format-patch -- <path>' '
613 git format-patch master..side -- file 2>error &&
614 ! grep "Use .--" error
615 '
617 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
618 git format-patch --ignore-if-in-upstream HEAD
619 '
621 test_done