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 doesn't consider merge commits" '
61 git checkout -b slave master &&
62 echo "Another line" >>file &&
63 test_tick &&
64 git commit -am "Slave change #1" &&
65 echo "Yet another line" >>file &&
66 test_tick &&
67 git commit -am "Slave change #2" &&
68 git checkout -b merger master &&
69 test_tick &&
70 git merge --no-ff slave &&
71 cnt=`git format-patch -3 --stdout | grep "^From " | wc -l` &&
72 test $cnt = 3
73 '
75 test_expect_success "format-patch result applies" '
77 git checkout -b rebuild-0 master &&
78 git am -3 patch0 &&
79 cnt=`git rev-list master.. | wc -l` &&
80 test $cnt = 2
81 '
83 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
85 git checkout -b rebuild-1 master &&
86 git am -3 patch1 &&
87 cnt=`git rev-list master.. | wc -l` &&
88 test $cnt = 2
89 '
91 test_expect_success 'commit did not screw up the log message' '
93 git cat-file commit side | grep "^Side .* with .* backslash-n"
95 '
97 test_expect_success 'format-patch did not screw up the log message' '
99 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
100 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
102 '
104 test_expect_success 'replay did not screw up the log message' '
106 git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
108 '
110 test_expect_success 'extra headers' '
112 git config format.headers "To: R. E. Cipient <rcipient@example.com>
113 " &&
114 git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>
115 " &&
116 git format-patch --stdout master..side > patch2 &&
117 sed -e "/^\$/q" patch2 > hdrs2 &&
118 grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs2 &&
119 grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs2
121 '
123 test_expect_success 'extra headers without newlines' '
125 git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
126 git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>" &&
127 git format-patch --stdout master..side >patch3 &&
128 sed -e "/^\$/q" patch3 > hdrs3 &&
129 grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs3 &&
130 grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs3
132 '
134 test_expect_success 'extra headers with multiple To:s' '
136 git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
137 git config --add format.headers "To: S. E. Cipient <scipient@example.com>" &&
138 git format-patch --stdout master..side > patch4 &&
139 sed -e "/^\$/q" patch4 > hdrs4 &&
140 grep "^To: R. E. Cipient <rcipient@example.com>,\$" hdrs4 &&
141 grep "^ *S. E. Cipient <scipient@example.com>\$" hdrs4
142 '
144 test_expect_success 'additional command line cc' '
146 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
147 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
148 grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch5 &&
149 grep "^ *S. E. Cipient <scipient@example.com>\$" patch5
150 '
152 test_expect_success 'command line headers' '
154 git config --unset-all format.headers &&
155 git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
156 grep "^Cc: R. E. Cipient <rcipient@example.com>\$" patch6
157 '
159 test_expect_success 'configuration headers and command line headers' '
161 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
162 git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
163 grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch7 &&
164 grep "^ *S. E. Cipient <scipient@example.com>\$" patch7
165 '
167 test_expect_success 'command line To: header' '
169 git config --unset-all format.headers &&
170 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
171 grep "^To: R. E. Cipient <rcipient@example.com>\$" patch8
172 '
174 test_expect_success 'configuration To: header' '
176 git config format.to "R. E. Cipient <rcipient@example.com>" &&
177 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
178 grep "^To: R. E. Cipient <rcipient@example.com>\$" patch9
179 '
181 test_expect_success '--no-to overrides config.to' '
183 git config --replace-all format.to \
184 "R. E. Cipient <rcipient@example.com>" &&
185 git format-patch --no-to --stdout master..side |
186 sed -e "/^\$/q" >patch10 &&
187 ! grep "^To: R. E. Cipient <rcipient@example.com>\$" patch10
188 '
190 test_expect_success '--no-to and --to replaces config.to' '
192 git config --replace-all format.to \
193 "Someone <someone@out.there>" &&
194 git format-patch --no-to --to="Someone Else <else@out.there>" \
195 --stdout master..side |
196 sed -e "/^\$/q" >patch11 &&
197 ! grep "^To: Someone <someone@out.there>\$" patch11 &&
198 grep "^To: Someone Else <else@out.there>\$" patch11
199 '
201 test_expect_success '--no-cc overrides config.cc' '
203 git config --replace-all format.cc \
204 "C. E. Cipient <rcipient@example.com>" &&
205 git format-patch --no-cc --stdout master..side |
206 sed -e "/^\$/q" >patch12 &&
207 ! grep "^Cc: C. E. Cipient <rcipient@example.com>\$" patch12
208 '
210 test_expect_success '--no-add-headers overrides config.headers' '
212 git config --replace-all format.headers \
213 "Header1: B. E. Cipient <rcipient@example.com>" &&
214 git format-patch --no-add-headers --stdout master..side |
215 sed -e "/^\$/q" >patch13 &&
216 ! grep "^Header1: B. E. Cipient <rcipient@example.com>\$" patch13
217 '
219 test_expect_success 'multiple files' '
221 rm -rf patches/ &&
222 git checkout side &&
223 git format-patch -o patches/ master &&
224 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
225 '
227 check_threading () {
228 expect="$1" &&
229 shift &&
230 (git format-patch --stdout "$@"; echo $? > status.out) |
231 # Prints everything between the Message-ID and In-Reply-To,
232 # and replaces all Message-ID-lookalikes by a sequence number
233 perl -ne '
234 if (/^(message-id|references|in-reply-to)/i) {
235 $printing = 1;
236 } elsif (/^\S/) {
237 $printing = 0;
238 }
239 if ($printing) {
240 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
241 for $k (keys %h) {s/$k/$h{$k}/};
242 print;
243 }
244 print "---\n" if /^From /i;
245 ' > actual &&
246 test 0 = "$(cat status.out)" &&
247 test_cmp "$expect" actual
248 }
250 cat >> expect.no-threading <<EOF
251 ---
252 ---
253 ---
254 EOF
256 test_expect_success 'no threading' '
257 git checkout side &&
258 check_threading expect.no-threading master
259 '
261 cat > expect.thread <<EOF
262 ---
263 Message-Id: <0>
264 ---
265 Message-Id: <1>
266 In-Reply-To: <0>
267 References: <0>
268 ---
269 Message-Id: <2>
270 In-Reply-To: <0>
271 References: <0>
272 EOF
274 test_expect_success 'thread' '
275 check_threading expect.thread --thread master
276 '
278 cat > expect.in-reply-to <<EOF
279 ---
280 Message-Id: <0>
281 In-Reply-To: <1>
282 References: <1>
283 ---
284 Message-Id: <2>
285 In-Reply-To: <1>
286 References: <1>
287 ---
288 Message-Id: <3>
289 In-Reply-To: <1>
290 References: <1>
291 EOF
293 test_expect_success 'thread in-reply-to' '
294 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
295 --thread master
296 '
298 cat > expect.cover-letter <<EOF
299 ---
300 Message-Id: <0>
301 ---
302 Message-Id: <1>
303 In-Reply-To: <0>
304 References: <0>
305 ---
306 Message-Id: <2>
307 In-Reply-To: <0>
308 References: <0>
309 ---
310 Message-Id: <3>
311 In-Reply-To: <0>
312 References: <0>
313 EOF
315 test_expect_success 'thread cover-letter' '
316 check_threading expect.cover-letter --cover-letter --thread master
317 '
319 cat > expect.cl-irt <<EOF
320 ---
321 Message-Id: <0>
322 In-Reply-To: <1>
323 References: <1>
324 ---
325 Message-Id: <2>
326 In-Reply-To: <0>
327 References: <1>
328 <0>
329 ---
330 Message-Id: <3>
331 In-Reply-To: <0>
332 References: <1>
333 <0>
334 ---
335 Message-Id: <4>
336 In-Reply-To: <0>
337 References: <1>
338 <0>
339 EOF
341 test_expect_success 'thread cover-letter in-reply-to' '
342 check_threading expect.cl-irt --cover-letter \
343 --in-reply-to="<test.message>" --thread master
344 '
346 test_expect_success 'thread explicit shallow' '
347 check_threading expect.cl-irt --cover-letter \
348 --in-reply-to="<test.message>" --thread=shallow master
349 '
351 cat > expect.deep <<EOF
352 ---
353 Message-Id: <0>
354 ---
355 Message-Id: <1>
356 In-Reply-To: <0>
357 References: <0>
358 ---
359 Message-Id: <2>
360 In-Reply-To: <1>
361 References: <0>
362 <1>
363 EOF
365 test_expect_success 'thread deep' '
366 check_threading expect.deep --thread=deep master
367 '
369 cat > expect.deep-irt <<EOF
370 ---
371 Message-Id: <0>
372 In-Reply-To: <1>
373 References: <1>
374 ---
375 Message-Id: <2>
376 In-Reply-To: <0>
377 References: <1>
378 <0>
379 ---
380 Message-Id: <3>
381 In-Reply-To: <2>
382 References: <1>
383 <0>
384 <2>
385 EOF
387 test_expect_success 'thread deep in-reply-to' '
388 check_threading expect.deep-irt --thread=deep \
389 --in-reply-to="<test.message>" master
390 '
392 cat > expect.deep-cl <<EOF
393 ---
394 Message-Id: <0>
395 ---
396 Message-Id: <1>
397 In-Reply-To: <0>
398 References: <0>
399 ---
400 Message-Id: <2>
401 In-Reply-To: <1>
402 References: <0>
403 <1>
404 ---
405 Message-Id: <3>
406 In-Reply-To: <2>
407 References: <0>
408 <1>
409 <2>
410 EOF
412 test_expect_success 'thread deep cover-letter' '
413 check_threading expect.deep-cl --cover-letter --thread=deep master
414 '
416 cat > expect.deep-cl-irt <<EOF
417 ---
418 Message-Id: <0>
419 In-Reply-To: <1>
420 References: <1>
421 ---
422 Message-Id: <2>
423 In-Reply-To: <0>
424 References: <1>
425 <0>
426 ---
427 Message-Id: <3>
428 In-Reply-To: <2>
429 References: <1>
430 <0>
431 <2>
432 ---
433 Message-Id: <4>
434 In-Reply-To: <3>
435 References: <1>
436 <0>
437 <2>
438 <3>
439 EOF
441 test_expect_success 'thread deep cover-letter in-reply-to' '
442 check_threading expect.deep-cl-irt --cover-letter \
443 --in-reply-to="<test.message>" --thread=deep master
444 '
446 test_expect_success 'thread via config' '
447 git config format.thread true &&
448 check_threading expect.thread master
449 '
451 test_expect_success 'thread deep via config' '
452 git config format.thread deep &&
453 check_threading expect.deep master
454 '
456 test_expect_success 'thread config + override' '
457 git config format.thread deep &&
458 check_threading expect.thread --thread master
459 '
461 test_expect_success 'thread config + --no-thread' '
462 git config format.thread deep &&
463 check_threading expect.no-threading --no-thread master
464 '
466 test_expect_success 'excessive subject' '
468 rm -rf patches/ &&
469 git checkout side &&
470 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
471 git update-index file &&
472 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." &&
473 git format-patch -o patches/ master..side &&
474 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
475 '
477 test_expect_success 'cover-letter inherits diff options' '
479 git mv file foo &&
480 git commit -m foo &&
481 git format-patch --cover-letter -1 &&
482 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
483 git format-patch --cover-letter -1 -M &&
484 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
486 '
488 cat > expect << EOF
489 This is an excessively long subject line for a message due to the
490 habit some projects have of not having a short, one-line subject at
491 the start of the commit message, but rather sticking a whole
492 paragraph right at the start as the only thing in the commit
493 message. It had better not become the filename for the patch.
494 foo
496 EOF
498 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
500 git format-patch --cover-letter -2 &&
501 sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
502 test_cmp expect output
504 '
506 cat > expect << EOF
507 ---
508 file | 16 ++++++++++++++++
509 1 files changed, 16 insertions(+), 0 deletions(-)
511 diff --git a/file b/file
512 index 40f36c6..2dc5c23 100644
513 --- a/file
514 +++ b/file
515 @@ -13,4 +13,20 @@ C
516 10
517 D
518 E
519 F
520 +5
521 EOF
523 test_expect_success 'format-patch respects -U' '
525 git format-patch -U4 -2 &&
526 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
527 test_cmp expect output
529 '
531 cat > expect << EOF
533 diff --git a/file b/file
534 index 40f36c6..2dc5c23 100644
535 --- a/file
536 +++ b/file
537 @@ -14,3 +14,19 @@ C
538 D
539 E
540 F
541 +5
542 EOF
544 test_expect_success 'format-patch -p suppresses stat' '
546 git format-patch -p -2 &&
547 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
548 test_cmp expect output
550 '
552 test_expect_success 'format-patch from a subdirectory (1)' '
553 filename=$(
554 rm -rf sub &&
555 mkdir -p sub/dir &&
556 cd sub/dir &&
557 git format-patch -1
558 ) &&
559 case "$filename" in
560 0*)
561 ;; # ok
562 *)
563 echo "Oops? $filename"
564 false
565 ;;
566 esac &&
567 test -f "$filename"
568 '
570 test_expect_success 'format-patch from a subdirectory (2)' '
571 filename=$(
572 rm -rf sub &&
573 mkdir -p sub/dir &&
574 cd sub/dir &&
575 git format-patch -1 -o ..
576 ) &&
577 case "$filename" in
578 ../0*)
579 ;; # ok
580 *)
581 echo "Oops? $filename"
582 false
583 ;;
584 esac &&
585 basename=$(expr "$filename" : ".*/\(.*\)") &&
586 test -f "sub/$basename"
587 '
589 test_expect_success 'format-patch from a subdirectory (3)' '
590 rm -f 0* &&
591 filename=$(
592 rm -rf sub &&
593 mkdir -p sub/dir &&
594 cd sub/dir &&
595 git format-patch -1 -o "$TRASH_DIRECTORY"
596 ) &&
597 basename=$(expr "$filename" : ".*/\(.*\)") &&
598 test -f "$basename"
599 '
601 test_expect_success 'format-patch --in-reply-to' '
602 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
603 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
604 grep "^References: <baz@foo.bar>" patch8
605 '
607 test_expect_success 'format-patch --signoff' '
608 git format-patch -1 --signoff --stdout |
609 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
610 '
612 echo "fatal: --name-only does not make sense" > expect.name-only
613 echo "fatal: --name-status does not make sense" > expect.name-status
614 echo "fatal: --check does not make sense" > expect.check
616 test_expect_success 'options no longer allowed for format-patch' '
617 test_must_fail git format-patch --name-only 2> output &&
618 test_cmp expect.name-only output &&
619 test_must_fail git format-patch --name-status 2> output &&
620 test_cmp expect.name-status output &&
621 test_must_fail git format-patch --check 2> output &&
622 test_cmp expect.check output'
624 test_expect_success 'format-patch --numstat should produce a patch' '
625 git format-patch --numstat --stdout master..side > output &&
626 test 6 = $(grep "^diff --git a/" output | wc -l)'
628 test_expect_success 'format-patch -- <path>' '
629 git format-patch master..side -- file 2>error &&
630 ! grep "Use .--" error
631 '
633 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
634 git format-patch --ignore-if-in-upstream HEAD
635 '
637 test_expect_success 'format-patch --signature' '
638 git format-patch --stdout --signature="my sig" -1 >output &&
639 grep "my sig" output
640 '
642 test_expect_success 'format-patch with format.signature config' '
643 git config format.signature "config sig" &&
644 git format-patch --stdout -1 >output &&
645 grep "config sig" output
646 '
648 test_expect_success 'format-patch --signature overrides format.signature' '
649 git config format.signature "config sig" &&
650 git format-patch --stdout --signature="overrides" -1 >output &&
651 ! grep "config sig" output &&
652 grep "overrides" output
653 '
655 test_expect_success 'format-patch --no-signature ignores format.signature' '
656 git config format.signature "config sig" &&
657 git format-patch --stdout --signature="my sig" --no-signature \
658 -1 >output &&
659 ! grep "config sig" output &&
660 ! grep "my sig" output &&
661 ! grep "^-- \$" output
662 '
664 test_expect_success 'format-patch --signature --cover-letter' '
665 git config --unset-all format.signature &&
666 git format-patch --stdout --signature="my sig" --cover-letter \
667 -1 >output &&
668 grep "my sig" output &&
669 test 2 = $(grep "my sig" output | wc -l)
670 '
672 test_expect_success 'format.signature="" supresses signatures' '
673 git config format.signature "" &&
674 git format-patch --stdout -1 >output &&
675 ! grep "^-- \$" output
676 '
678 test_expect_success 'format-patch --no-signature supresses signatures' '
679 git config --unset-all format.signature &&
680 git format-patch --stdout --no-signature -1 >output &&
681 ! grep "^-- \$" output
682 '
684 test_expect_success 'format-patch --signature="" supresses signatures' '
685 git format-patch --signature="" -1 >output &&
686 ! grep "^-- \$" output
687 '
689 test_done