3 # Copyright (c) 2006 Junio C Hamano
6 test_description='various format-patch tests'
9 . "$TEST_DIRECTORY"/lib-terminal.sh
11 test_expect_success setup '
13 for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
17 git commit -m Initial &&
18 git checkout -b side &&
20 for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
23 git commit -m "Side changes #1" &&
25 for i in D E F; do echo "$i"; done >>file &&
26 git update-index file &&
28 git commit -m "Side changes #2" &&
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 &&
34 git commit -m "Side changes #3 with \\n backslash-n in it." &&
36 git checkout master &&
37 git diff-tree -p C2 | git apply --index &&
39 git commit -m "Master accepts moral equivalent of #2"
43 test_expect_success "format-patch --ignore-if-in-upstream" '
45 git format-patch --stdout master..side >patch0 &&
46 cnt=`grep "^From " patch0 | wc -l` &&
51 test_expect_success "format-patch --ignore-if-in-upstream" '
53 git format-patch --stdout \
54 --ignore-if-in-upstream master..side >patch1 &&
55 cnt=`grep "^From " patch1 | wc -l` &&
60 test_expect_success "format-patch doesn't consider merge commits" '
62 git checkout -b slave master &&
63 echo "Another line" >>file &&
65 git commit -am "Slave change #1" &&
66 echo "Yet another line" >>file &&
68 git commit -am "Slave change #2" &&
69 git checkout -b merger master &&
71 git merge --no-ff slave &&
72 cnt=`git format-patch -3 --stdout | grep "^From " | wc -l` &&
76 test_expect_success "format-patch result applies" '
78 git checkout -b rebuild-0 master &&
80 cnt=`git rev-list master.. | wc -l` &&
84 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
86 git checkout -b rebuild-1 master &&
88 cnt=`git rev-list master.. | wc -l` &&
92 test_expect_success 'commit did not screw up the log message' '
94 git cat-file commit side | grep "^Side .* with .* backslash-n"
98 test_expect_success 'format-patch did not screw up the log message' '
100 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
101 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
105 test_expect_success 'replay did not screw up the log message' '
107 git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
111 test_expect_success 'extra headers' '
113 git config format.headers "To: R. E. Cipient <rcipient@example.com>
115 git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>
117 git format-patch --stdout master..side > patch2 &&
118 sed -e "/^\$/q" patch2 > hdrs2 &&
119 grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs2 &&
120 grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs2
124 test_expect_success 'extra headers without newlines' '
126 git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
127 git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>" &&
128 git format-patch --stdout master..side >patch3 &&
129 sed -e "/^\$/q" patch3 > hdrs3 &&
130 grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs3 &&
131 grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs3
135 test_expect_success 'extra headers with multiple To:s' '
137 git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
138 git config --add format.headers "To: S. E. Cipient <scipient@example.com>" &&
139 git format-patch --stdout master..side > patch4 &&
140 sed -e "/^\$/q" patch4 > hdrs4 &&
141 grep "^To: R. E. Cipient <rcipient@example.com>,\$" hdrs4 &&
142 grep "^ *S. E. Cipient <scipient@example.com>\$" hdrs4
145 test_expect_success 'additional command line cc' '
147 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
148 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
149 grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch5 &&
150 grep "^ *S. E. Cipient <scipient@example.com>\$" patch5
153 test_expect_success 'command line headers' '
155 git config --unset-all format.headers &&
156 git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
157 grep "^Cc: R. E. Cipient <rcipient@example.com>\$" patch6
160 test_expect_success 'configuration headers and command line headers' '
162 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
163 git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
164 grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch7 &&
165 grep "^ *S. E. Cipient <scipient@example.com>\$" patch7
168 test_expect_success 'command line To: header' '
170 git config --unset-all format.headers &&
171 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
172 grep "^To: R. E. Cipient <rcipient@example.com>\$" patch8
175 test_expect_success 'configuration To: header' '
177 git config format.to "R. E. Cipient <rcipient@example.com>" &&
178 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
179 grep "^To: R. E. Cipient <rcipient@example.com>\$" patch9
182 test_expect_success '--no-to overrides config.to' '
184 git config --replace-all format.to \
185 "R. E. Cipient <rcipient@example.com>" &&
186 git format-patch --no-to --stdout master..side |
187 sed -e "/^\$/q" >patch10 &&
188 ! grep "^To: R. E. Cipient <rcipient@example.com>\$" patch10
191 test_expect_success '--no-to and --to replaces config.to' '
193 git config --replace-all format.to \
194 "Someone <someone@out.there>" &&
195 git format-patch --no-to --to="Someone Else <else@out.there>" \
196 --stdout master..side |
197 sed -e "/^\$/q" >patch11 &&
198 ! grep "^To: Someone <someone@out.there>\$" patch11 &&
199 grep "^To: Someone Else <else@out.there>\$" patch11
202 test_expect_success '--no-cc overrides config.cc' '
204 git config --replace-all format.cc \
205 "C. E. Cipient <rcipient@example.com>" &&
206 git format-patch --no-cc --stdout master..side |
207 sed -e "/^\$/q" >patch12 &&
208 ! grep "^Cc: C. E. Cipient <rcipient@example.com>\$" patch12
211 test_expect_success '--no-add-headers overrides config.headers' '
213 git config --replace-all format.headers \
214 "Header1: B. E. Cipient <rcipient@example.com>" &&
215 git format-patch --no-add-headers --stdout master..side |
216 sed -e "/^\$/q" >patch13 &&
217 ! grep "^Header1: B. E. Cipient <rcipient@example.com>\$" patch13
220 test_expect_success 'multiple files' '
224 git format-patch -o patches/ master &&
225 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
231 (git format-patch --stdout "$@"; echo $? > status.out) |
232 # Prints everything between the Message-ID and In-Reply-To,
233 # and replaces all Message-ID-lookalikes by a sequence number
235 if (/^(message-id|references|in-reply-to)/i) {
241 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
242 for $k (keys %h) {s/$k/$h{$k}/};
245 print "---\n" if /^From /i;
247 test 0 = "$(cat status.out)" &&
248 test_cmp "$expect" actual
251 cat >> expect.no-threading <<EOF
257 test_expect_success 'no threading' '
259 check_threading expect.no-threading master
262 cat > expect.thread <<EOF
275 test_expect_success 'thread' '
276 check_threading expect.thread --thread master
279 cat > expect.in-reply-to <<EOF
294 test_expect_success 'thread in-reply-to' '
295 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
299 cat > expect.cover-letter <<EOF
316 test_expect_success 'thread cover-letter' '
317 check_threading expect.cover-letter --cover-letter --thread master
320 cat > expect.cl-irt <<EOF
342 test_expect_success 'thread cover-letter in-reply-to' '
343 check_threading expect.cl-irt --cover-letter \
344 --in-reply-to="<test.message>" --thread master
347 test_expect_success 'thread explicit shallow' '
348 check_threading expect.cl-irt --cover-letter \
349 --in-reply-to="<test.message>" --thread=shallow master
352 cat > expect.deep <<EOF
366 test_expect_success 'thread deep' '
367 check_threading expect.deep --thread=deep master
370 cat > expect.deep-irt <<EOF
388 test_expect_success 'thread deep in-reply-to' '
389 check_threading expect.deep-irt --thread=deep \
390 --in-reply-to="<test.message>" master
393 cat > expect.deep-cl <<EOF
413 test_expect_success 'thread deep cover-letter' '
414 check_threading expect.deep-cl --cover-letter --thread=deep master
417 cat > expect.deep-cl-irt <<EOF
442 test_expect_success 'thread deep cover-letter in-reply-to' '
443 check_threading expect.deep-cl-irt --cover-letter \
444 --in-reply-to="<test.message>" --thread=deep master
447 test_expect_success 'thread via config' '
448 git config format.thread true &&
449 check_threading expect.thread master
452 test_expect_success 'thread deep via config' '
453 git config format.thread deep &&
454 check_threading expect.deep master
457 test_expect_success 'thread config + override' '
458 git config format.thread deep &&
459 check_threading expect.thread --thread master
462 test_expect_success 'thread config + --no-thread' '
463 git config format.thread deep &&
464 check_threading expect.no-threading --no-thread master
467 test_expect_success 'excessive subject' '
471 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
472 git update-index file &&
473 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." &&
474 git format-patch -o patches/ master..side &&
475 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
478 test_expect_success 'cover-letter inherits diff options' '
482 git format-patch --cover-letter -1 &&
483 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
484 git format-patch --cover-letter -1 -M &&
485 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
490 This is an excessively long subject line for a message due to the
491 habit some projects have of not having a short, one-line subject at
492 the start of the commit message, but rather sticking a whole
493 paragraph right at the start as the only thing in the commit
494 message. It had better not become the filename for the patch.
499 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
501 git format-patch --cover-letter -2 &&
502 sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
503 test_cmp expect output
509 file | 16 ++++++++++++++++
510 1 files changed, 16 insertions(+), 0 deletions(-)
512 diff --git a/file b/file
513 index 40f36c6..2dc5c23 100644
524 test_expect_success 'format-patch respects -U' '
526 git format-patch -U4 -2 &&
527 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
528 test_cmp expect output
534 diff --git a/file b/file
535 index 40f36c6..2dc5c23 100644
545 test_expect_success 'format-patch -p suppresses stat' '
547 git format-patch -p -2 &&
548 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
549 test_cmp expect output
553 test_expect_success 'format-patch from a subdirectory (1)' '
564 echo "Oops? $filename"
571 test_expect_success 'format-patch from a subdirectory (2)' '
576 git format-patch -1 -o ..
582 echo "Oops? $filename"
586 basename=$(expr "$filename" : ".*/\(.*\)") &&
587 test -f "sub/$basename"
590 test_expect_success 'format-patch from a subdirectory (3)' '
596 git format-patch -1 -o "$TRASH_DIRECTORY"
598 basename=$(expr "$filename" : ".*/\(.*\)") &&
602 test_expect_success 'format-patch --in-reply-to' '
603 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
604 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
605 grep "^References: <baz@foo.bar>" patch8
608 test_expect_success 'format-patch --signoff' '
609 git format-patch -1 --signoff --stdout |
610 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
613 echo "fatal: --name-only does not make sense" > expect.name-only
614 echo "fatal: --name-status does not make sense" > expect.name-status
615 echo "fatal: --check does not make sense" > expect.check
617 test_expect_success 'options no longer allowed for format-patch' '
618 test_must_fail git format-patch --name-only 2> output &&
619 test_cmp expect.name-only output &&
620 test_must_fail git format-patch --name-status 2> output &&
621 test_cmp expect.name-status output &&
622 test_must_fail git format-patch --check 2> output &&
623 test_cmp expect.check output'
625 test_expect_success 'format-patch --numstat should produce a patch' '
626 git format-patch --numstat --stdout master..side > output &&
627 test 6 = $(grep "^diff --git a/" output | wc -l)'
629 test_expect_success 'format-patch -- <path>' '
630 git format-patch master..side -- file 2>error &&
631 ! grep "Use .--" error
634 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
635 git format-patch --ignore-if-in-upstream HEAD
638 test_expect_success 'format-patch --signature' '
639 git format-patch --stdout --signature="my sig" -1 >output &&
643 test_expect_success 'format-patch with format.signature config' '
644 git config format.signature "config sig" &&
645 git format-patch --stdout -1 >output &&
646 grep "config sig" output
649 test_expect_success 'format-patch --signature overrides format.signature' '
650 git config format.signature "config sig" &&
651 git format-patch --stdout --signature="overrides" -1 >output &&
652 ! grep "config sig" output &&
653 grep "overrides" output
656 test_expect_success 'format-patch --no-signature ignores format.signature' '
657 git config format.signature "config sig" &&
658 git format-patch --stdout --signature="my sig" --no-signature \
660 ! grep "config sig" output &&
661 ! grep "my sig" output &&
662 ! grep "^-- \$" output
665 test_expect_success 'format-patch --signature --cover-letter' '
666 git config --unset-all format.signature &&
667 git format-patch --stdout --signature="my sig" --cover-letter \
669 grep "my sig" output &&
670 test 2 = $(grep "my sig" output | wc -l)
673 test_expect_success 'format.signature="" supresses signatures' '
674 git config format.signature "" &&
675 git format-patch --stdout -1 >output &&
676 ! grep "^-- \$" output
679 test_expect_success 'format-patch --no-signature supresses signatures' '
680 git config --unset-all format.signature &&
681 git format-patch --stdout --no-signature -1 >output &&
682 ! grep "^-- \$" output
685 test_expect_success 'format-patch --signature="" supresses signatures' '
686 git format-patch --signature="" -1 >output &&
687 ! grep "^-- \$" output
690 test_expect_success TTY 'format-patch --stdout paginates' '
693 GIT_PAGER="wc >pager_used" &&
695 test_terminal git format-patch --stdout --all
697 test_path_is_file pager_used
700 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
703 GIT_PAGER="wc >pager_used" &&
705 test_terminal git --no-pager format-patch --stdout --all &&
706 test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
708 test_path_is_missing pager_used &&
709 test_path_is_missing .git/pager_used