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 git commit -m Initial &&
16 git checkout -b side &&
18 for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
19 test_chmod +x elif &&
20 git commit -m "Side changes #1" &&
22 for i in D E F; do echo "$i"; done >>file &&
23 git update-index file &&
24 git commit -m "Side changes #2" &&
25 git tag C2 &&
27 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
28 git update-index file &&
29 git commit -m "Side changes #3 with \\n backslash-n in it." &&
31 git checkout master &&
32 git diff-tree -p C2 | git apply --index &&
33 git commit -m "Master accepts moral equivalent of #2"
35 '
37 test_expect_success "format-patch --ignore-if-in-upstream" '
39 git format-patch --stdout master..side >patch0 &&
40 cnt=`grep "^From " patch0 | wc -l` &&
41 test $cnt = 3
43 '
45 test_expect_success "format-patch --ignore-if-in-upstream" '
47 git format-patch --stdout \
48 --ignore-if-in-upstream master..side >patch1 &&
49 cnt=`grep "^From " patch1 | wc -l` &&
50 test $cnt = 2
52 '
54 test_expect_success "format-patch result applies" '
56 git checkout -b rebuild-0 master &&
57 git am -3 patch0 &&
58 cnt=`git rev-list master.. | wc -l` &&
59 test $cnt = 2
60 '
62 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
64 git checkout -b rebuild-1 master &&
65 git am -3 patch1 &&
66 cnt=`git rev-list master.. | wc -l` &&
67 test $cnt = 2
68 '
70 test_expect_success 'commit did not screw up the log message' '
72 git cat-file commit side | grep "^Side .* with .* backslash-n"
74 '
76 test_expect_success 'format-patch did not screw up the log message' '
78 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
79 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
81 '
83 test_expect_success 'replay did not screw up the log message' '
85 git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
87 '
89 test_expect_success 'extra headers' '
91 git config format.headers "To: R. E. Cipient <rcipient@example.com>
92 " &&
93 git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>
94 " &&
95 git format-patch --stdout master..side > patch2 &&
96 sed -e "/^$/q" patch2 > hdrs2 &&
97 grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs2 &&
98 grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs2
100 '
102 test_expect_success 'extra headers without newlines' '
104 git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
105 git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>" &&
106 git format-patch --stdout master..side >patch3 &&
107 sed -e "/^$/q" patch3 > hdrs3 &&
108 grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs3 &&
109 grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs3
111 '
113 test_expect_success 'extra headers with multiple To:s' '
115 git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
116 git config --add format.headers "To: S. E. Cipient <scipient@example.com>" &&
117 git format-patch --stdout master..side > patch4 &&
118 sed -e "/^$/q" patch4 > hdrs4 &&
119 grep "^To: R. E. Cipient <rcipient@example.com>,$" hdrs4 &&
120 grep "^ *S. E. Cipient <scipient@example.com>$" hdrs4
121 '
123 test_expect_success 'additional command line cc' '
125 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
126 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch5 &&
127 grep "^Cc: R. E. Cipient <rcipient@example.com>,$" patch5 &&
128 grep "^ *S. E. Cipient <scipient@example.com>$" patch5
129 '
131 test_expect_success 'command line headers' '
133 git config --unset-all format.headers &&
134 git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch6 &&
135 grep "^Cc: R. E. Cipient <rcipient@example.com>$" patch6
136 '
138 test_expect_success 'configuration headers and command line headers' '
140 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
141 git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch7 &&
142 grep "^Cc: R. E. Cipient <rcipient@example.com>,$" patch7 &&
143 grep "^ *S. E. Cipient <scipient@example.com>$" patch7
144 '
146 test_expect_success 'multiple files' '
148 rm -rf patches/ &&
149 git checkout side &&
150 git format-patch -o patches/ master &&
151 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
152 '
154 check_threading () {
155 expect="$1" &&
156 shift &&
157 (git format-patch --stdout "$@"; echo $? > status.out) |
158 # Prints everything between the Message-ID and In-Reply-To,
159 # and replaces all Message-ID-lookalikes by a sequence number
160 perl -ne '
161 if (/^(message-id|references|in-reply-to)/i) {
162 $printing = 1;
163 } elsif (/^\S/) {
164 $printing = 0;
165 }
166 if ($printing) {
167 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
168 for $k (keys %h) {s/$k/$h{$k}/};
169 print;
170 }
171 print "---\n" if /^From /i;
172 ' > actual &&
173 test 0 = "$(cat status.out)" &&
174 test_cmp "$expect" actual
175 }
177 cat >> expect.no-threading <<EOF
178 ---
179 ---
180 ---
181 EOF
183 test_expect_success 'no threading' '
184 git checkout side &&
185 check_threading expect.no-threading master
186 '
188 cat > expect.thread <<EOF
189 ---
190 Message-Id: <0>
191 ---
192 Message-Id: <1>
193 In-Reply-To: <0>
194 References: <0>
195 ---
196 Message-Id: <2>
197 In-Reply-To: <0>
198 References: <0>
199 EOF
201 test_expect_success 'thread' '
202 check_threading expect.thread --thread master
203 '
205 cat > expect.in-reply-to <<EOF
206 ---
207 Message-Id: <0>
208 In-Reply-To: <1>
209 References: <1>
210 ---
211 Message-Id: <2>
212 In-Reply-To: <1>
213 References: <1>
214 ---
215 Message-Id: <3>
216 In-Reply-To: <1>
217 References: <1>
218 EOF
220 test_expect_success 'thread in-reply-to' '
221 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
222 --thread master
223 '
225 cat > expect.cover-letter <<EOF
226 ---
227 Message-Id: <0>
228 ---
229 Message-Id: <1>
230 In-Reply-To: <0>
231 References: <0>
232 ---
233 Message-Id: <2>
234 In-Reply-To: <0>
235 References: <0>
236 ---
237 Message-Id: <3>
238 In-Reply-To: <0>
239 References: <0>
240 EOF
242 test_expect_success 'thread cover-letter' '
243 check_threading expect.cover-letter --cover-letter --thread master
244 '
246 cat > expect.cl-irt <<EOF
247 ---
248 Message-Id: <0>
249 In-Reply-To: <1>
250 References: <1>
251 ---
252 Message-Id: <2>
253 In-Reply-To: <0>
254 References: <1>
255 <0>
256 ---
257 Message-Id: <3>
258 In-Reply-To: <0>
259 References: <1>
260 <0>
261 ---
262 Message-Id: <4>
263 In-Reply-To: <0>
264 References: <1>
265 <0>
266 EOF
268 test_expect_success 'thread cover-letter in-reply-to' '
269 check_threading expect.cl-irt --cover-letter \
270 --in-reply-to="<test.message>" --thread master
271 '
273 test_expect_success 'thread explicit shallow' '
274 check_threading expect.cl-irt --cover-letter \
275 --in-reply-to="<test.message>" --thread=shallow master
276 '
278 cat > expect.deep <<EOF
279 ---
280 Message-Id: <0>
281 ---
282 Message-Id: <1>
283 In-Reply-To: <0>
284 References: <0>
285 ---
286 Message-Id: <2>
287 In-Reply-To: <1>
288 References: <0>
289 <1>
290 EOF
292 test_expect_success 'thread deep' '
293 check_threading expect.deep --thread=deep master
294 '
296 cat > expect.deep-irt <<EOF
297 ---
298 Message-Id: <0>
299 In-Reply-To: <1>
300 References: <1>
301 ---
302 Message-Id: <2>
303 In-Reply-To: <0>
304 References: <1>
305 <0>
306 ---
307 Message-Id: <3>
308 In-Reply-To: <2>
309 References: <1>
310 <0>
311 <2>
312 EOF
314 test_expect_success 'thread deep in-reply-to' '
315 check_threading expect.deep-irt --thread=deep \
316 --in-reply-to="<test.message>" master
317 '
319 cat > expect.deep-cl <<EOF
320 ---
321 Message-Id: <0>
322 ---
323 Message-Id: <1>
324 In-Reply-To: <0>
325 References: <0>
326 ---
327 Message-Id: <2>
328 In-Reply-To: <1>
329 References: <0>
330 <1>
331 ---
332 Message-Id: <3>
333 In-Reply-To: <2>
334 References: <0>
335 <1>
336 <2>
337 EOF
339 test_expect_success 'thread deep cover-letter' '
340 check_threading expect.deep-cl --cover-letter --thread=deep master
341 '
343 cat > expect.deep-cl-irt <<EOF
344 ---
345 Message-Id: <0>
346 In-Reply-To: <1>
347 References: <1>
348 ---
349 Message-Id: <2>
350 In-Reply-To: <0>
351 References: <1>
352 <0>
353 ---
354 Message-Id: <3>
355 In-Reply-To: <2>
356 References: <1>
357 <0>
358 <2>
359 ---
360 Message-Id: <4>
361 In-Reply-To: <3>
362 References: <1>
363 <0>
364 <2>
365 <3>
366 EOF
368 test_expect_success 'thread deep cover-letter in-reply-to' '
369 check_threading expect.deep-cl-irt --cover-letter \
370 --in-reply-to="<test.message>" --thread=deep master
371 '
373 test_expect_success 'thread via config' '
374 git config format.thread true &&
375 check_threading expect.thread master
376 '
378 test_expect_success 'thread deep via config' '
379 git config format.thread deep &&
380 check_threading expect.deep master
381 '
383 test_expect_success 'thread config + override' '
384 git config format.thread deep &&
385 check_threading expect.thread --thread master
386 '
388 test_expect_success 'thread config + --no-thread' '
389 git config format.thread deep &&
390 check_threading expect.no-threading --no-thread master
391 '
393 test_expect_success 'excessive subject' '
395 rm -rf patches/ &&
396 git checkout side &&
397 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
398 git update-index file &&
399 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." &&
400 git format-patch -o patches/ master..side &&
401 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
402 '
404 test_expect_success 'cover-letter inherits diff options' '
406 git mv file foo &&
407 git commit -m foo &&
408 git format-patch --cover-letter -1 &&
409 ! grep "file => foo .* 0 *$" 0000-cover-letter.patch &&
410 git format-patch --cover-letter -1 -M &&
411 grep "file => foo .* 0 *$" 0000-cover-letter.patch
413 '
415 cat > expect << EOF
416 This is an excessively long subject line for a message due to the
417 habit some projects have of not having a short, one-line subject at
418 the start of the commit message, but rather sticking a whole
419 paragraph right at the start as the only thing in the commit
420 message. It had better not become the filename for the patch.
421 foo
423 EOF
425 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
427 git format-patch --cover-letter -2 &&
428 sed -e "1,/A U Thor/d" -e "/^$/q" < 0000-cover-letter.patch > output &&
429 test_cmp expect output
431 '
433 cat > expect << EOF
434 ---
435 file | 16 ++++++++++++++++
436 1 files changed, 16 insertions(+), 0 deletions(-)
438 diff --git a/file b/file
439 index 40f36c6..2dc5c23 100644
440 --- a/file
441 +++ b/file
442 @@ -13,4 +13,20 @@ C
443 10
444 D
445 E
446 F
447 +5
448 EOF
450 test_expect_success 'format-patch respects -U' '
452 git format-patch -U4 -2 &&
453 sed -e "1,/^$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
454 test_cmp expect output
456 '
458 test_expect_success 'format-patch from a subdirectory (1)' '
459 filename=$(
460 rm -rf sub &&
461 mkdir -p sub/dir &&
462 cd sub/dir &&
463 git format-patch -1
464 ) &&
465 case "$filename" in
466 0*)
467 ;; # ok
468 *)
469 echo "Oops? $filename"
470 false
471 ;;
472 esac &&
473 test -f "$filename"
474 '
476 test_expect_success 'format-patch from a subdirectory (2)' '
477 filename=$(
478 rm -rf sub &&
479 mkdir -p sub/dir &&
480 cd sub/dir &&
481 git format-patch -1 -o ..
482 ) &&
483 case "$filename" in
484 ../0*)
485 ;; # ok
486 *)
487 echo "Oops? $filename"
488 false
489 ;;
490 esac &&
491 basename=$(expr "$filename" : ".*/\(.*\)") &&
492 test -f "sub/$basename"
493 '
495 test_expect_success 'format-patch from a subdirectory (3)' '
496 rm -f 0* &&
497 filename=$(
498 rm -rf sub &&
499 mkdir -p sub/dir &&
500 cd sub/dir &&
501 git format-patch -1 -o "$TRASH_DIRECTORY"
502 ) &&
503 basename=$(expr "$filename" : ".*/\(.*\)") &&
504 test -f "$basename"
505 '
507 test_expect_success 'format-patch --in-reply-to' '
508 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
509 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
510 grep "^References: <baz@foo.bar>" patch8
511 '
513 test_expect_success 'format-patch --signoff' '
514 git format-patch -1 --signoff --stdout |
515 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
516 '
518 test_done