Code

fast-import: don't allow 'ls' of path with empty components
[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
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 &&
14         cat file >elif &&
15         git add file elif &&
16         test_tick &&
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 &&
21         test_chmod +x elif &&
22         test_tick &&
23         git commit -m "Side changes #1" &&
25         for i in D E F; do echo "$i"; done >>file &&
26         git update-index file &&
27         test_tick &&
28         git commit -m "Side changes #2" &&
29         git tag C2 &&
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 &&
33         test_tick &&
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 &&
38         test_tick &&
39         git commit -m "Master accepts moral equivalent of #2"
41 '
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` &&
47         test $cnt = 3
49 '
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` &&
56         test $cnt = 2
58 '
60 test_expect_success "format-patch doesn't consider merge commits" '
62         git checkout -b slave master &&
63         echo "Another line" >>file &&
64         test_tick &&
65         git commit -am "Slave change #1" &&
66         echo "Yet another line" >>file &&
67         test_tick &&
68         git commit -am "Slave change #2" &&
69         git checkout -b merger master &&
70         test_tick &&
71         git merge --no-ff slave &&
72         cnt=`git format-patch -3 --stdout | grep "^From " | wc -l` &&
73         test $cnt = 3
74 '
76 test_expect_success "format-patch result applies" '
78         git checkout -b rebuild-0 master &&
79         git am -3 patch0 &&
80         cnt=`git rev-list master.. | wc -l` &&
81         test $cnt = 2
82 '
84 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
86         git checkout -b rebuild-1 master &&
87         git am -3 patch1 &&
88         cnt=`git rev-list master.. | wc -l` &&
89         test $cnt = 2
90 '
92 test_expect_success 'commit did not screw up the log message' '
94         git cat-file commit side | grep "^Side .* with .* backslash-n"
96 '
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>
114 " &&
115         git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>
116 " &&
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' '
222         rm -rf patches/ &&
223         git checkout side &&
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
228 check_threading () {
229         expect="$1" &&
230         shift &&
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
234         perl -ne '
235                 if (/^(message-id|references|in-reply-to)/i) {
236                         $printing = 1;
237                 } elsif (/^\S/) {
238                         $printing = 0;
239                 }
240                 if ($printing) {
241                         $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
242                         for $k (keys %h) {s/$k/$h{$k}/};
243                         print;
244                 }
245                 print "---\n" if /^From /i;
246         ' > actual &&
247         test 0 = "$(cat status.out)" &&
248         test_cmp "$expect" actual
251 cat >> expect.no-threading <<EOF
252 ---
253 ---
254 ---
255 EOF
257 test_expect_success 'no threading' '
258         git checkout side &&
259         check_threading expect.no-threading master
262 cat > expect.thread <<EOF
263 ---
264 Message-Id: <0>
265 ---
266 Message-Id: <1>
267 In-Reply-To: <0>
268 References: <0>
269 ---
270 Message-Id: <2>
271 In-Reply-To: <0>
272 References: <0>
273 EOF
275 test_expect_success 'thread' '
276         check_threading expect.thread --thread master
279 cat > expect.in-reply-to <<EOF
280 ---
281 Message-Id: <0>
282 In-Reply-To: <1>
283 References: <1>
284 ---
285 Message-Id: <2>
286 In-Reply-To: <1>
287 References: <1>
288 ---
289 Message-Id: <3>
290 In-Reply-To: <1>
291 References: <1>
292 EOF
294 test_expect_success 'thread in-reply-to' '
295         check_threading expect.in-reply-to --in-reply-to="<test.message>" \
296                 --thread master
299 cat > expect.cover-letter <<EOF
300 ---
301 Message-Id: <0>
302 ---
303 Message-Id: <1>
304 In-Reply-To: <0>
305 References: <0>
306 ---
307 Message-Id: <2>
308 In-Reply-To: <0>
309 References: <0>
310 ---
311 Message-Id: <3>
312 In-Reply-To: <0>
313 References: <0>
314 EOF
316 test_expect_success 'thread cover-letter' '
317         check_threading expect.cover-letter --cover-letter --thread master
320 cat > expect.cl-irt <<EOF
321 ---
322 Message-Id: <0>
323 In-Reply-To: <1>
324 References: <1>
325 ---
326 Message-Id: <2>
327 In-Reply-To: <0>
328 References: <1>
329         <0>
330 ---
331 Message-Id: <3>
332 In-Reply-To: <0>
333 References: <1>
334         <0>
335 ---
336 Message-Id: <4>
337 In-Reply-To: <0>
338 References: <1>
339         <0>
340 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
353 ---
354 Message-Id: <0>
355 ---
356 Message-Id: <1>
357 In-Reply-To: <0>
358 References: <0>
359 ---
360 Message-Id: <2>
361 In-Reply-To: <1>
362 References: <0>
363         <1>
364 EOF
366 test_expect_success 'thread deep' '
367         check_threading expect.deep --thread=deep master
370 cat > expect.deep-irt <<EOF
371 ---
372 Message-Id: <0>
373 In-Reply-To: <1>
374 References: <1>
375 ---
376 Message-Id: <2>
377 In-Reply-To: <0>
378 References: <1>
379         <0>
380 ---
381 Message-Id: <3>
382 In-Reply-To: <2>
383 References: <1>
384         <0>
385         <2>
386 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
394 ---
395 Message-Id: <0>
396 ---
397 Message-Id: <1>
398 In-Reply-To: <0>
399 References: <0>
400 ---
401 Message-Id: <2>
402 In-Reply-To: <1>
403 References: <0>
404         <1>
405 ---
406 Message-Id: <3>
407 In-Reply-To: <2>
408 References: <0>
409         <1>
410         <2>
411 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
418 ---
419 Message-Id: <0>
420 In-Reply-To: <1>
421 References: <1>
422 ---
423 Message-Id: <2>
424 In-Reply-To: <0>
425 References: <1>
426         <0>
427 ---
428 Message-Id: <3>
429 In-Reply-To: <2>
430 References: <1>
431         <0>
432         <2>
433 ---
434 Message-Id: <4>
435 In-Reply-To: <3>
436 References: <1>
437         <0>
438         <2>
439         <3>
440 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' '
469         rm -rf patches/ &&
470         git checkout side &&
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' '
480         git mv file foo &&
481         git commit -m foo &&
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
489 cat > expect << EOF
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.
495   foo
497 EOF
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
507 cat > expect << EOF
508 ---
509  file |   16 ++++++++++++++++
510  1 files changed, 16 insertions(+), 0 deletions(-)
512 diff --git a/file b/file
513 index 40f36c6..2dc5c23 100644
514 --- a/file
515 +++ b/file
516 @@ -13,4 +13,20 @@ C
517  10
518  D
519  E
520  F
521 +5
522 EOF
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
532 cat > expect << EOF
534 diff --git a/file b/file
535 index 40f36c6..2dc5c23 100644
536 --- a/file
537 +++ b/file
538 @@ -14,3 +14,19 @@ C
539  D
540  E
541  F
542 +5
543 EOF
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)' '
554         filename=$(
555                 rm -rf sub &&
556                 mkdir -p sub/dir &&
557                 cd sub/dir &&
558                 git format-patch -1
559         ) &&
560         case "$filename" in
561         0*)
562                 ;; # ok
563         *)
564                 echo "Oops? $filename"
565                 false
566                 ;;
567         esac &&
568         test -f "$filename"
571 test_expect_success 'format-patch from a subdirectory (2)' '
572         filename=$(
573                 rm -rf sub &&
574                 mkdir -p sub/dir &&
575                 cd sub/dir &&
576                 git format-patch -1 -o ..
577         ) &&
578         case "$filename" in
579         ../0*)
580                 ;; # ok
581         *)
582                 echo "Oops? $filename"
583                 false
584                 ;;
585         esac &&
586         basename=$(expr "$filename" : ".*/\(.*\)") &&
587         test -f "sub/$basename"
590 test_expect_success 'format-patch from a subdirectory (3)' '
591         rm -f 0* &&
592         filename=$(
593                 rm -rf sub &&
594                 mkdir -p sub/dir &&
595                 cd sub/dir &&
596                 git format-patch -1 -o "$TRASH_DIRECTORY"
597         ) &&
598         basename=$(expr "$filename" : ".*/\(.*\)") &&
599         test -f "$basename"
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 &&
640         grep "my sig" 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 \
659                 -1 >output &&
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 \
668                 -1 >output &&
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' '
691         rm -f pager_used &&
692         (
693                 GIT_PAGER="wc >pager_used" &&
694                 export GIT_PAGER &&
695                 test_terminal git format-patch --stdout --all
696         ) &&
697         test_path_is_file pager_used
700  test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
701         rm -f pager_used &&
702         (
703                 GIT_PAGER="wc >pager_used" &&
704                 export GIT_PAGER &&
705                 test_terminal git --no-pager format-patch --stdout --all &&
706                 test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
707         ) &&
708         test_path_is_missing pager_used &&
709         test_path_is_missing .git/pager_used
712 test_done