Code

tests: factor out terminal handling from t7006
[git.git] / t / t4014-format-patch.sh
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
104 test_expect_success 'replay did not screw up the log message' '
106         git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
346 test_expect_success 'thread explicit shallow' '
347         check_threading expect.cl-irt --cover-letter \
348                 --in-reply-to="<test.message>" --thread=shallow master
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
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
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
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
446 test_expect_success 'thread via config' '
447         git config format.thread true &&
448         check_threading expect.thread master
451 test_expect_success 'thread deep via config' '
452         git config format.thread deep &&
453         check_threading expect.deep master
456 test_expect_success 'thread config + override' '
457         git config format.thread deep &&
458         check_threading expect.thread --thread master
461 test_expect_success 'thread config + --no-thread' '
462         git config format.thread deep &&
463         check_threading expect.no-threading --no-thread master
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
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
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
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
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
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"
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"
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"
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
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>"
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
633 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
634         git format-patch --ignore-if-in-upstream HEAD
637 test_expect_success 'format-patch --signature' '
638         git format-patch --stdout --signature="my sig" -1 >output &&
639         grep "my sig" output
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
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
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
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)
672 test_expect_success 'format.signature="" supresses signatures' '
673         git config format.signature "" &&
674         git format-patch --stdout -1 >output &&
675         ! grep "^-- \$" output
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
684 test_expect_success 'format-patch --signature="" supresses signatures' '
685         git format-patch --signature="" -1 >output &&
686         ! grep "^-- \$" output
689 test_done