1#!/bin/sh
2
3test_description='git am running'
4
5. ./test-lib.sh
6
7test_expect_success 'setup: messages' '
8 cat >msg <<-\EOF &&
9 second
10
11 Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy
12 eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
13 voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita
14 kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem
15 ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
16 tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
17 vero eos et accusam et justo duo dolores et ea rebum.
18
19 EOF
20 qz_to_tab_space <<-\EOF >>msg &&
21 QDuis autem vel eum iriure dolor in hendrerit in vulputate velit
22 Qesse molestie consequat, vel illum dolore eu feugiat nulla facilisis
23 Qat vero eros et accumsan et iusto odio dignissim qui blandit
24 Qpraesent luptatum zzril delenit augue duis dolore te feugait nulla
25 Qfacilisi.
26 EOF
27 cat >>msg <<-\EOF &&
28
29 Lorem ipsum dolor sit amet,
30 consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
31 laoreet dolore magna aliquam erat volutpat.
32
33 git
34 ---
35 +++
36
37 Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit
38 lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure
39 dolor in hendrerit in vulputate velit esse molestie consequat, vel illum
40 dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
41 dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te
42 feugait nulla facilisi.
43
44 Reported-by: A N Other <a.n.other@example.com>
45 EOF
46
47 cat >failmail <<-\EOF &&
48 From foo@example.com Fri May 23 10:43:49 2008
49 From: foo@example.com
50 To: bar@example.com
51 Subject: Re: [RFC/PATCH] git-foo.sh
52 Date: Fri, 23 May 2008 05:23:42 +0200
53
54 Sometimes we have to find out that there'\''s nothing left.
55
56 EOF
57
58 cat >pine <<-\EOF &&
59 From MAILER-DAEMON Fri May 23 10:43:49 2008
60 Date: 23 May 2008 05:23:42 +0200
61 From: Mail System Internal Data <MAILER-DAEMON@example.com>
62 Subject: DON'\''T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA
63 Message-ID: <foo-0001@example.com>
64
65 This text is part of the internal format of your mail folder, and is not
66 a real message. It is created automatically by the mail system software.
67 If deleted, important folder data will be lost, and it will be re-created
68 with the data reset to initial values.
69
70 EOF
71
72 cat >msg-without-scissors-line <<-\EOF &&
73 Test that git-am --scissors cuts at the scissors line
74
75 This line should be included in the commit message.
76 EOF
77
78 printf "Subject: " >subject-prefix &&
79
80 cat - subject-prefix msg-without-scissors-line >msg-with-scissors-line <<-\EOF &&
81 This line should not be included in the commit message with --scissors enabled.
82
83 - - >8 - - remove everything above this line - - >8 - -
84
85 EOF
86
87 signoff="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
88'
89
90test_expect_success setup '
91 echo hello >file &&
92 git add file &&
93 test_tick &&
94 git commit -m first &&
95 git tag first &&
96
97 echo world >>file &&
98 git add file &&
99 test_tick &&
100 git commit -F msg &&
101 git tag second &&
102
103 git format-patch --stdout first >patch1 &&
104 {
105 echo "Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>" &&
106 echo "X-Fake-Field: Line One" &&
107 echo "X-Fake-Field: Line Two" &&
108 echo "X-Fake-Field: Line Three" &&
109 git format-patch --stdout first | sed -e "1d"
110 } > patch1.eml &&
111 {
112 echo "X-Fake-Field: Line One" &&
113 echo "X-Fake-Field: Line Two" &&
114 echo "X-Fake-Field: Line Three" &&
115 git format-patch --stdout first | sed -e "1d"
116 } | append_cr >patch1-crlf.eml &&
117 {
118 printf "%255s\\n" ""
119 echo "X-Fake-Field: Line One" &&
120 echo "X-Fake-Field: Line Two" &&
121 echo "X-Fake-Field: Line Three" &&
122 git format-patch --stdout first | sed -e "1d"
123 } > patch1-ws.eml &&
124 {
125 sed -ne "1p" msg &&
126 echo &&
127 echo "From: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" &&
128 echo "Date: $GIT_AUTHOR_DATE" &&
129 echo &&
130 sed -e "1,2d" msg &&
131 echo "---" &&
132 git diff-tree --no-commit-id --stat -p second
133 } >patch1-stgit.eml &&
134 mkdir stgit-series &&
135 cp patch1-stgit.eml stgit-series/patch &&
136 {
137 echo "# This series applies on GIT commit $(git rev-parse first)" &&
138 echo "patch"
139 } >stgit-series/series &&
140 {
141 echo "# HG changeset patch" &&
142 echo "# User $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" &&
143 echo "# Date $test_tick 25200" &&
144 echo "# $(git show --pretty="%aD" -s second)" &&
145 echo "# Node ID $ZERO_OID" &&
146 echo "# Parent $ZERO_OID" &&
147 cat msg &&
148 echo &&
149 git diff-tree --no-commit-id -p second
150 } >patch1-hg.eml &&
151
152
153 echo file >file &&
154 git add file &&
155 git commit -F msg-without-scissors-line &&
156 git tag expected-for-scissors &&
157 git reset --hard HEAD^ &&
158
159 echo file >file &&
160 git add file &&
161 git commit -F msg-with-scissors-line &&
162 git tag expected-for-no-scissors &&
163 git format-patch --stdout expected-for-no-scissors^ >patch-with-scissors-line.eml &&
164 git reset --hard HEAD^ &&
165
166 sed -n -e "3,\$p" msg >file &&
167 git add file &&
168 test_tick &&
169 git commit -m third &&
170
171 git format-patch --stdout first >patch2 &&
172
173 git checkout -b lorem &&
174 sed -n -e "11,\$p" msg >file &&
175 head -n 9 msg >>file &&
176 test_tick &&
177 git commit -a -m "moved stuff" &&
178
179 echo goodbye >another &&
180 git add another &&
181 test_tick &&
182 git commit -m "added another file" &&
183
184 git format-patch --stdout master >lorem-move.patch &&
185 git format-patch --no-prefix --stdout master >lorem-zero.patch &&
186
187 git checkout -b rename &&
188 git mv file renamed &&
189 git commit -m "renamed a file" &&
190
191 git format-patch -M --stdout lorem >rename.patch &&
192
193 git reset --soft lorem^ &&
194 git commit -m "renamed a file and added another" &&
195
196 git format-patch -M --stdout lorem^ >rename-add.patch &&
197
198 # reset time
199 sane_unset test_tick &&
200 test_tick
201'
202
203test_expect_success 'am applies patch correctly' '
204 rm -fr .git/rebase-apply &&
205 git reset --hard &&
206 git checkout first &&
207 test_tick &&
208 git am <patch1 &&
209 test_path_is_missing .git/rebase-apply &&
210 git diff --exit-code second &&
211 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
212 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
213'
214
215test_expect_success 'am fails if index is dirty' '
216 test_when_finished "rm -f dirtyfile" &&
217 rm -fr .git/rebase-apply &&
218 git reset --hard &&
219 git checkout first &&
220 echo dirtyfile >dirtyfile &&
221 git add dirtyfile &&
222 test_must_fail git am patch1 &&
223 test_path_is_dir .git/rebase-apply &&
224 test_cmp_rev first HEAD
225'
226
227test_expect_success 'am applies patch e-mail not in a mbox' '
228 rm -fr .git/rebase-apply &&
229 git reset --hard &&
230 git checkout first &&
231 git am patch1.eml &&
232 test_path_is_missing .git/rebase-apply &&
233 git diff --exit-code second &&
234 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
235 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
236'
237
238test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
239 rm -fr .git/rebase-apply &&
240 git reset --hard &&
241 git checkout first &&
242 git am patch1-crlf.eml &&
243 test_path_is_missing .git/rebase-apply &&
244 git diff --exit-code second &&
245 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
246 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
247'
248
249test_expect_success 'am applies patch e-mail with preceding whitespace' '
250 rm -fr .git/rebase-apply &&
251 git reset --hard &&
252 git checkout first &&
253 git am patch1-ws.eml &&
254 test_path_is_missing .git/rebase-apply &&
255 git diff --exit-code second &&
256 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
257 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
258'
259
260test_expect_success 'am applies stgit patch' '
261 rm -fr .git/rebase-apply &&
262 git checkout -f first &&
263 git am patch1-stgit.eml &&
264 test_path_is_missing .git/rebase-apply &&
265 git diff --exit-code second &&
266 test_cmp_rev second HEAD &&
267 test_cmp_rev second^ HEAD^
268'
269
270test_expect_success 'am --patch-format=stgit applies stgit patch' '
271 rm -fr .git/rebase-apply &&
272 git checkout -f first &&
273 git am --patch-format=stgit <patch1-stgit.eml &&
274 test_path_is_missing .git/rebase-apply &&
275 git diff --exit-code second &&
276 test_cmp_rev second HEAD &&
277 test_cmp_rev second^ HEAD^
278'
279
280test_expect_success 'am applies stgit series' '
281 rm -fr .git/rebase-apply &&
282 git checkout -f first &&
283 git am stgit-series/series &&
284 test_path_is_missing .git/rebase-apply &&
285 git diff --exit-code second &&
286 test_cmp_rev second HEAD &&
287 test_cmp_rev second^ HEAD^
288'
289
290test_expect_success 'am applies hg patch' '
291 rm -fr .git/rebase-apply &&
292 git checkout -f first &&
293 git am patch1-hg.eml &&
294 test_path_is_missing .git/rebase-apply &&
295 git diff --exit-code second &&
296 test_cmp_rev second HEAD &&
297 test_cmp_rev second^ HEAD^
298'
299
300test_expect_success 'am --patch-format=hg applies hg patch' '
301 rm -fr .git/rebase-apply &&
302 git checkout -f first &&
303 git am --patch-format=hg <patch1-hg.eml &&
304 test_path_is_missing .git/rebase-apply &&
305 git diff --exit-code second &&
306 test_cmp_rev second HEAD &&
307 test_cmp_rev second^ HEAD^
308'
309
310test_expect_success 'am with applypatch-msg hook' '
311 test_when_finished "rm -f .git/hooks/applypatch-msg" &&
312 rm -fr .git/rebase-apply &&
313 git reset --hard &&
314 git checkout first &&
315 mkdir -p .git/hooks &&
316 write_script .git/hooks/applypatch-msg <<-\EOF &&
317 cat "$1" >actual-msg &&
318 echo hook-message >"$1"
319 EOF
320 git am patch1 &&
321 test_path_is_missing .git/rebase-apply &&
322 git diff --exit-code second &&
323 echo hook-message >expected &&
324 git log -1 --format=format:%B >actual &&
325 test_cmp expected actual &&
326 git log -1 --format=format:%B second >expected &&
327 test_cmp expected actual-msg
328'
329
330test_expect_success 'am with failing applypatch-msg hook' '
331 test_when_finished "rm -f .git/hooks/applypatch-msg" &&
332 rm -fr .git/rebase-apply &&
333 git reset --hard &&
334 git checkout first &&
335 mkdir -p .git/hooks &&
336 write_script .git/hooks/applypatch-msg <<-\EOF &&
337 exit 1
338 EOF
339 test_must_fail git am patch1 &&
340 test_path_is_dir .git/rebase-apply &&
341 git diff --exit-code first &&
342 test_cmp_rev first HEAD
343'
344
345test_expect_success 'am with pre-applypatch hook' '
346 test_when_finished "rm -f .git/hooks/pre-applypatch" &&
347 rm -fr .git/rebase-apply &&
348 git reset --hard &&
349 git checkout first &&
350 mkdir -p .git/hooks &&
351 write_script .git/hooks/pre-applypatch <<-\EOF &&
352 git diff first >diff.actual
353 exit 0
354 EOF
355 git am patch1 &&
356 test_path_is_missing .git/rebase-apply &&
357 git diff --exit-code second &&
358 test_cmp_rev second HEAD &&
359 git diff first..second >diff.expected &&
360 test_cmp diff.expected diff.actual
361'
362
363test_expect_success 'am with failing pre-applypatch hook' '
364 test_when_finished "rm -f .git/hooks/pre-applypatch" &&
365 rm -fr .git/rebase-apply &&
366 git reset --hard &&
367 git checkout first &&
368 mkdir -p .git/hooks &&
369 write_script .git/hooks/pre-applypatch <<-\EOF &&
370 exit 1
371 EOF
372 test_must_fail git am patch1 &&
373 test_path_is_dir .git/rebase-apply &&
374 git diff --exit-code second &&
375 test_cmp_rev first HEAD
376'
377
378test_expect_success 'am with post-applypatch hook' '
379 test_when_finished "rm -f .git/hooks/post-applypatch" &&
380 rm -fr .git/rebase-apply &&
381 git reset --hard &&
382 git checkout first &&
383 mkdir -p .git/hooks &&
384 write_script .git/hooks/post-applypatch <<-\EOF &&
385 git rev-parse HEAD >head.actual
386 git diff second >diff.actual
387 exit 0
388 EOF
389 git am patch1 &&
390 test_path_is_missing .git/rebase-apply &&
391 test_cmp_rev second HEAD &&
392 git rev-parse second >head.expected &&
393 test_cmp head.expected head.actual &&
394 git diff second >diff.expected &&
395 test_cmp diff.expected diff.actual
396'
397
398test_expect_success 'am with failing post-applypatch hook' '
399 test_when_finished "rm -f .git/hooks/post-applypatch" &&
400 rm -fr .git/rebase-apply &&
401 git reset --hard &&
402 git checkout first &&
403 mkdir -p .git/hooks &&
404 write_script .git/hooks/post-applypatch <<-\EOF &&
405 git rev-parse HEAD >head.actual
406 exit 1
407 EOF
408 git am patch1 &&
409 test_path_is_missing .git/rebase-apply &&
410 git diff --exit-code second &&
411 test_cmp_rev second HEAD &&
412 git rev-parse second >head.expected &&
413 test_cmp head.expected head.actual
414'
415
416test_expect_success 'am --scissors cuts the message at the scissors line' '
417 rm -fr .git/rebase-apply &&
418 git reset --hard &&
419 git checkout second &&
420 git am --scissors patch-with-scissors-line.eml &&
421 test_path_is_missing .git/rebase-apply &&
422 git diff --exit-code expected-for-scissors &&
423 test_cmp_rev expected-for-scissors HEAD
424'
425
426test_expect_success 'am --no-scissors overrides mailinfo.scissors' '
427 rm -fr .git/rebase-apply &&
428 git reset --hard &&
429 git checkout second &&
430 test_config mailinfo.scissors true &&
431 git am --no-scissors patch-with-scissors-line.eml &&
432 test_path_is_missing .git/rebase-apply &&
433 git diff --exit-code expected-for-no-scissors &&
434 test_cmp_rev expected-for-no-scissors HEAD
435'
436
437test_expect_success 'setup: new author and committer' '
438 GIT_AUTHOR_NAME="Another Thor" &&
439 GIT_AUTHOR_EMAIL="a.thor@example.com" &&
440 GIT_COMMITTER_NAME="Co M Miter" &&
441 GIT_COMMITTER_EMAIL="c.miter@example.com" &&
442 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
443'
444
445compare () {
446 a=$(git cat-file commit "$2" | grep "^$1 ") &&
447 b=$(git cat-file commit "$3" | grep "^$1 ") &&
448 test "$a" = "$b"
449}
450
451test_expect_success 'am changes committer and keeps author' '
452 test_tick &&
453 rm -fr .git/rebase-apply &&
454 git reset --hard &&
455 git checkout first &&
456 git am patch2 &&
457 test_path_is_missing .git/rebase-apply &&
458 test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
459 git diff --exit-code master..HEAD &&
460 git diff --exit-code master^..HEAD^ &&
461 compare author master HEAD &&
462 compare author master^ HEAD^ &&
463 test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
464 "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
465'
466
467test_expect_success 'am --signoff adds Signed-off-by: line' '
468 rm -fr .git/rebase-apply &&
469 git reset --hard &&
470 git checkout -b master2 first &&
471 git am --signoff <patch2 &&
472 {
473 printf "third\n\nSigned-off-by: %s <%s>\n\n" \
474 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" &&
475 cat msg &&
476 printf "Signed-off-by: %s <%s>\n\n" \
477 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL"
478 } >expected-log &&
479 git log --pretty=%B -2 HEAD >actual &&
480 test_cmp expected-log actual
481'
482
483test_expect_success 'am stays in branch' '
484 echo refs/heads/master2 >expected &&
485 git symbolic-ref HEAD >actual &&
486 test_cmp expected actual
487'
488
489test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
490 git format-patch --stdout first >patch3 &&
491 git reset --hard first &&
492 git am --signoff <patch3 &&
493 git log --pretty=%B -2 HEAD >actual &&
494 test_cmp expected-log actual
495'
496
497test_expect_success 'am --signoff adds Signed-off-by: if another author is preset' '
498 NAME="A N Other" &&
499 EMAIL="a.n.other@example.com" &&
500 {
501 printf "third\n\nSigned-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
502 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
503 "$NAME" "$EMAIL" &&
504 cat msg &&
505 printf "Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
506 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
507 "$NAME" "$EMAIL"
508 } >expected-log &&
509 git reset --hard first &&
510 GIT_COMMITTER_NAME="$NAME" GIT_COMMITTER_EMAIL="$EMAIL" \
511 git am --signoff <patch3 &&
512 git log --pretty=%B -2 HEAD >actual &&
513 test_cmp expected-log actual
514'
515
516test_expect_success 'am --signoff duplicates Signed-off-by: if it is not the last one' '
517 NAME="A N Other" &&
518 EMAIL="a.n.other@example.com" &&
519 {
520 printf "third\n\nSigned-off-by: %s <%s>\n\
521Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
522 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
523 "$NAME" "$EMAIL" \
524 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" &&
525 cat msg &&
526 printf "Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\
527Signed-off-by: %s <%s>\n\n" \
528 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
529 "$NAME" "$EMAIL" \
530 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL"
531 } >expected-log &&
532 git format-patch --stdout first >patch3 &&
533 git reset --hard first &&
534 git am --signoff <patch3 &&
535 git log --pretty=%B -2 HEAD >actual &&
536 test_cmp expected-log actual
537'
538
539test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
540 git format-patch --stdout HEAD^ >tmp &&
541 sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," tmp >patch4 &&
542 git reset --hard HEAD^ &&
543 git am <patch4 &&
544 git rev-parse HEAD >expected &&
545 git rev-parse master2 >actual &&
546 test_cmp expected actual
547'
548
549test_expect_success 'am --keep really keeps the subject' '
550 rm -fr .git/rebase-apply &&
551 git reset --hard &&
552 git checkout HEAD^ &&
553 git am --keep patch4 &&
554 test_path_is_missing .git/rebase-apply &&
555 git cat-file commit HEAD >actual &&
556 grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual
557'
558
559test_expect_success 'am --keep-non-patch really keeps the non-patch part' '
560 rm -fr .git/rebase-apply &&
561 git reset --hard &&
562 git checkout HEAD^ &&
563 git am --keep-non-patch patch4 &&
564 test_path_is_missing .git/rebase-apply &&
565 git cat-file commit HEAD >actual &&
566 grep "^\[foo\] third" actual
567'
568
569test_expect_success 'setup am -3' '
570 rm -fr .git/rebase-apply &&
571 git reset --hard &&
572 git checkout -b base3way master2 &&
573 sed -n -e "3,\$p" msg >file &&
574 head -n 9 msg >>file &&
575 git add file &&
576 test_tick &&
577 git commit -m "copied stuff"
578'
579
580test_expect_success 'am -3 falls back to 3-way merge' '
581 rm -fr .git/rebase-apply &&
582 git reset --hard &&
583 git checkout -b lorem2 base3way &&
584 git am -3 lorem-move.patch &&
585 test_path_is_missing .git/rebase-apply &&
586 git diff --exit-code lorem
587'
588
589test_expect_success 'am -3 -p0 can read --no-prefix patch' '
590 rm -fr .git/rebase-apply &&
591 git reset --hard &&
592 git checkout -b lorem3 base3way &&
593 git am -3 -p0 lorem-zero.patch &&
594 test_path_is_missing .git/rebase-apply &&
595 git diff --exit-code lorem
596'
597
598test_expect_success 'am with config am.threeWay falls back to 3-way merge' '
599 rm -fr .git/rebase-apply &&
600 git reset --hard &&
601 git checkout -b lorem4 base3way &&
602 test_config am.threeWay 1 &&
603 git am lorem-move.patch &&
604 test_path_is_missing .git/rebase-apply &&
605 git diff --exit-code lorem
606'
607
608test_expect_success 'am with config am.threeWay overridden by --no-3way' '
609 rm -fr .git/rebase-apply &&
610 git reset --hard &&
611 git checkout -b lorem5 base3way &&
612 test_config am.threeWay 1 &&
613 test_must_fail git am --no-3way lorem-move.patch &&
614 test_path_is_dir .git/rebase-apply
615'
616
617test_expect_success 'am can rename a file' '
618 grep "^rename from" rename.patch &&
619 rm -fr .git/rebase-apply &&
620 git reset --hard &&
621 git checkout lorem^0 &&
622 git am rename.patch &&
623 test_path_is_missing .git/rebase-apply &&
624 git update-index --refresh &&
625 git diff --exit-code rename
626'
627
628test_expect_success 'am -3 can rename a file' '
629 grep "^rename from" rename.patch &&
630 rm -fr .git/rebase-apply &&
631 git reset --hard &&
632 git checkout lorem^0 &&
633 git am -3 rename.patch &&
634 test_path_is_missing .git/rebase-apply &&
635 git update-index --refresh &&
636 git diff --exit-code rename
637'
638
639test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
640 grep "^rename from" rename-add.patch &&
641 rm -fr .git/rebase-apply &&
642 git reset --hard &&
643 git checkout lorem^0 &&
644 git am -3 rename-add.patch &&
645 test_path_is_missing .git/rebase-apply &&
646 git update-index --refresh &&
647 git diff --exit-code rename
648'
649
650test_expect_success 'am -3 -q is quiet' '
651 rm -fr .git/rebase-apply &&
652 git checkout -f lorem2 &&
653 git reset base3way --hard &&
654 git am -3 -q lorem-move.patch >output.out 2>&1 &&
655 test_must_be_empty output.out
656'
657
658test_expect_success 'am pauses on conflict' '
659 rm -fr .git/rebase-apply &&
660 git reset --hard &&
661 git checkout lorem2^^ &&
662 test_must_fail git am lorem-move.patch &&
663 test -d .git/rebase-apply
664'
665
666test_expect_success 'am --show-current-patch' '
667 git am --show-current-patch >actual.patch &&
668 test_cmp .git/rebase-apply/0001 actual.patch
669'
670
671test_expect_success 'am --skip works' '
672 echo goodbye >expected &&
673 git am --skip &&
674 test_path_is_missing .git/rebase-apply &&
675 git diff --exit-code lorem2^^ -- file &&
676 test_cmp expected another
677'
678
679test_expect_success 'am --abort removes a stray directory' '
680 mkdir .git/rebase-apply &&
681 git am --abort &&
682 test_path_is_missing .git/rebase-apply
683'
684
685test_expect_success 'am refuses patches when paused' '
686 rm -fr .git/rebase-apply &&
687 git reset --hard &&
688 git checkout lorem2^^ &&
689
690 test_must_fail git am lorem-move.patch &&
691 test_path_is_dir .git/rebase-apply &&
692 test_cmp_rev lorem2^^ HEAD &&
693
694 test_must_fail git am <lorem-move.patch &&
695 test_path_is_dir .git/rebase-apply &&
696 test_cmp_rev lorem2^^ HEAD
697'
698
699test_expect_success 'am --resolved works' '
700 echo goodbye >expected &&
701 rm -fr .git/rebase-apply &&
702 git reset --hard &&
703 git checkout lorem2^^ &&
704 test_must_fail git am lorem-move.patch &&
705 test -d .git/rebase-apply &&
706 echo resolved >>file &&
707 git add file &&
708 git am --resolved &&
709 test_path_is_missing .git/rebase-apply &&
710 test_cmp expected another
711'
712
713test_expect_success 'am --resolved fails if index has no changes' '
714 rm -fr .git/rebase-apply &&
715 git reset --hard &&
716 git checkout lorem2^^ &&
717 test_must_fail git am lorem-move.patch &&
718 test_path_is_dir .git/rebase-apply &&
719 test_cmp_rev lorem2^^ HEAD &&
720 test_must_fail git am --resolved &&
721 test_path_is_dir .git/rebase-apply &&
722 test_cmp_rev lorem2^^ HEAD
723'
724
725test_expect_success 'am --resolved fails if index has unmerged entries' '
726 rm -fr .git/rebase-apply &&
727 git reset --hard &&
728 git checkout second &&
729 test_must_fail git am -3 lorem-move.patch &&
730 test_path_is_dir .git/rebase-apply &&
731 test_cmp_rev second HEAD &&
732 test_must_fail git am --resolved >err &&
733 test_path_is_dir .git/rebase-apply &&
734 test_cmp_rev second HEAD &&
735 test_i18ngrep "still have unmerged paths" err
736'
737
738test_expect_success 'am takes patches from a Pine mailbox' '
739 rm -fr .git/rebase-apply &&
740 git reset --hard &&
741 git checkout first &&
742 cat pine patch1 | git am &&
743 test_path_is_missing .git/rebase-apply &&
744 git diff --exit-code master^..HEAD
745'
746
747test_expect_success 'am fails on mail without patch' '
748 rm -fr .git/rebase-apply &&
749 git reset --hard &&
750 test_must_fail git am <failmail &&
751 git am --abort &&
752 test_path_is_missing .git/rebase-apply
753'
754
755test_expect_success 'am fails on empty patch' '
756 rm -fr .git/rebase-apply &&
757 git reset --hard &&
758 echo "---" >>failmail &&
759 test_must_fail git am <failmail &&
760 git am --skip &&
761 test_path_is_missing .git/rebase-apply
762'
763
764test_expect_success 'am works from stdin in subdirectory' '
765 rm -fr subdir &&
766 rm -fr .git/rebase-apply &&
767 git reset --hard &&
768 git checkout first &&
769 (
770 mkdir -p subdir &&
771 cd subdir &&
772 git am <../patch1
773 ) &&
774 git diff --exit-code second
775'
776
777test_expect_success 'am works from file (relative path given) in subdirectory' '
778 rm -fr subdir &&
779 rm -fr .git/rebase-apply &&
780 git reset --hard &&
781 git checkout first &&
782 (
783 mkdir -p subdir &&
784 cd subdir &&
785 git am ../patch1
786 ) &&
787 git diff --exit-code second
788'
789
790test_expect_success 'am works from file (absolute path given) in subdirectory' '
791 rm -fr subdir &&
792 rm -fr .git/rebase-apply &&
793 git reset --hard &&
794 git checkout first &&
795 P=$(pwd) &&
796 (
797 mkdir -p subdir &&
798 cd subdir &&
799 git am "$P/patch1"
800 ) &&
801 git diff --exit-code second
802'
803
804test_expect_success 'am --committer-date-is-author-date' '
805 rm -fr .git/rebase-apply &&
806 git reset --hard &&
807 git checkout first &&
808 test_tick &&
809 git am --committer-date-is-author-date patch1 &&
810 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
811 sed -ne "/^author /s/.*> //p" head1 >at &&
812 sed -ne "/^committer /s/.*> //p" head1 >ct &&
813 test_cmp at ct
814'
815
816test_expect_success 'am without --committer-date-is-author-date' '
817 rm -fr .git/rebase-apply &&
818 git reset --hard &&
819 git checkout first &&
820 test_tick &&
821 git am patch1 &&
822 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
823 sed -ne "/^author /s/.*> //p" head1 >at &&
824 sed -ne "/^committer /s/.*> //p" head1 >ct &&
825 ! test_cmp at ct
826'
827
828# This checks for +0000 because TZ is set to UTC and that should
829# show up when the current time is used. The date in message is set
830# by test_tick that uses -0700 timezone; if this feature does not
831# work, we will see that instead of +0000.
832test_expect_success 'am --ignore-date' '
833 rm -fr .git/rebase-apply &&
834 git reset --hard &&
835 git checkout first &&
836 test_tick &&
837 git am --ignore-date patch1 &&
838 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
839 sed -ne "/^author /s/.*> //p" head1 >at &&
840 grep "+0000" at
841'
842
843test_expect_success 'am into an unborn branch' '
844 git rev-parse first^{tree} >expected &&
845 rm -fr .git/rebase-apply &&
846 git reset --hard &&
847 rm -fr subdir &&
848 mkdir subdir &&
849 git format-patch --numbered-files -o subdir -1 first &&
850 (
851 cd subdir &&
852 git init &&
853 git am 1
854 ) &&
855 (
856 cd subdir &&
857 git rev-parse HEAD^{tree} >../actual
858 ) &&
859 test_cmp expected actual
860'
861
862test_expect_success 'am newline in subject' '
863 rm -fr .git/rebase-apply &&
864 git reset --hard &&
865 git checkout first &&
866 test_tick &&
867 sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
868 git am <patchnl >output.out 2>&1 &&
869 test_i18ngrep "^Applying: second \\\n foo$" output.out
870'
871
872test_expect_success 'am -q is quiet' '
873 rm -fr .git/rebase-apply &&
874 git reset --hard &&
875 git checkout first &&
876 test_tick &&
877 git am -q <patch1 >output.out 2>&1 &&
878 test_must_be_empty output.out
879'
880
881test_expect_success 'am empty-file does not infloop' '
882 rm -fr .git/rebase-apply &&
883 git reset --hard &&
884 touch empty-file &&
885 test_tick &&
886 test_must_fail git am empty-file 2>actual &&
887 echo Patch format detection failed. >expected &&
888 test_i18ncmp expected actual
889'
890
891test_expect_success 'am --message-id really adds the message id' '
892 rm -fr .git/rebase-apply &&
893 git reset --hard &&
894 git checkout HEAD^ &&
895 git am --message-id patch1.eml &&
896 test_path_is_missing .git/rebase-apply &&
897 git cat-file commit HEAD | tail -n1 >actual &&
898 grep Message-Id patch1.eml >expected &&
899 test_cmp expected actual
900'
901
902test_expect_success 'am.messageid really adds the message id' '
903 rm -fr .git/rebase-apply &&
904 git reset --hard &&
905 git checkout HEAD^ &&
906 test_config am.messageid true &&
907 git am patch1.eml &&
908 test_path_is_missing .git/rebase-apply &&
909 git cat-file commit HEAD | tail -n1 >actual &&
910 grep Message-Id patch1.eml >expected &&
911 test_cmp expected actual
912'
913
914test_expect_success 'am --message-id -s signs off after the message id' '
915 rm -fr .git/rebase-apply &&
916 git reset --hard &&
917 git checkout HEAD^ &&
918 git am -s --message-id patch1.eml &&
919 test_path_is_missing .git/rebase-apply &&
920 git cat-file commit HEAD | tail -n2 | head -n1 >actual &&
921 grep Message-Id patch1.eml >expected &&
922 test_cmp expected actual
923'
924
925test_expect_success 'am -3 works with rerere' '
926 rm -fr .git/rebase-apply &&
927 git reset --hard &&
928
929 # make patches one->two and two->three...
930 test_commit one file &&
931 test_commit two file &&
932 test_commit three file &&
933 git format-patch -2 --stdout >seq.patch &&
934
935 # and create a situation that conflicts...
936 git reset --hard one &&
937 test_commit other file &&
938
939 # enable rerere...
940 test_config rerere.enabled true &&
941 test_when_finished "rm -rf .git/rr-cache" &&
942
943 # ...and apply. Our resolution is to skip the first
944 # patch, and the rerere the second one.
945 test_must_fail git am -3 seq.patch &&
946 test_must_fail git am --skip &&
947 echo resolved >file &&
948 git add file &&
949 git am --resolved &&
950
951 # now apply again, and confirm that rerere engaged (we still
952 # expect failure from am because rerere does not auto-commit
953 # for us).
954 git reset --hard other &&
955 test_must_fail git am -3 seq.patch &&
956 test_must_fail git am --skip &&
957 echo resolved >expect &&
958 test_cmp expect file
959'
960
961test_expect_success 'am -s unexpected trailer block' '
962 rm -fr .git/rebase-apply &&
963 git reset --hard &&
964 echo signed >file &&
965 git add file &&
966 cat >msg <<-EOF &&
967 subject here
968
969 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
970 [jc: tweaked log message]
971 Signed-off-by: J C H <j@c.h>
972 EOF
973 git commit -F msg &&
974 git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
975 git format-patch --stdout -1 >patch &&
976
977 git reset --hard HEAD^ &&
978 git am -s patch &&
979 (
980 cat original &&
981 echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
982 ) >expect &&
983 git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
984 test_cmp expect actual &&
985
986 cat >msg <<-\EOF &&
987 subject here
988
989 We make sure that there is a blank line between the log
990 message proper and Signed-off-by: line added.
991 EOF
992 git reset HEAD^ &&
993 git commit -F msg file &&
994 git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
995 git format-patch --stdout -1 >patch &&
996
997 git reset --hard HEAD^ &&
998 git am -s patch &&
999
1000 (
1001 cat original &&
1002 echo &&
1003 echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
1004 ) >expect &&
1005 git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
1006 test_cmp expect actual
1007'
1008
1009test_expect_success 'am --patch-format=mboxrd handles mboxrd' '
1010 rm -fr .git/rebase-apply &&
1011 git checkout -f first &&
1012 echo mboxrd >>file &&
1013 git add file &&
1014 cat >msg <<-\INPUT_END &&
1015 mboxrd should escape the body
1016
1017 From could trip up a loose mbox parser
1018 >From extra escape for reversibility
1019 INPUT_END
1020 git commit -F msg &&
1021 git format-patch --pretty=mboxrd --stdout -1 >mboxrd1 &&
1022 grep "^>From could trip up a loose mbox parser" mboxrd1 &&
1023 git checkout -f first &&
1024 git am --patch-format=mboxrd mboxrd1 &&
1025 git cat-file commit HEAD | tail -n4 >out &&
1026 test_cmp msg out
1027'
1028
1029test_expect_success 'am works with multi-line in-body headers' '
1030 FORTY="String that has a length of more than forty characters" &&
1031 LONG="$FORTY $FORTY" &&
1032 rm -fr .git/rebase-apply &&
1033 git checkout -f first &&
1034 echo one >> file &&
1035 git commit -am "$LONG
1036
1037 Body test" --author="$LONG <long@example.com>" &&
1038 git format-patch --stdout -1 >patch &&
1039 # bump from, date, and subject down to in-body header
1040 perl -lpe "
1041 if (/^From:/) {
1042 print \"From: x <x\@example.com>\";
1043 print \"Date: Sat, 1 Jan 2000 00:00:00 +0000\";
1044 print \"Subject: x\n\";
1045 }
1046 " patch >msg &&
1047 git checkout HEAD^ &&
1048 git am msg &&
1049 # Ensure that the author and full message are present
1050 git cat-file commit HEAD | grep "^author.*long@example.com" &&
1051 git cat-file commit HEAD | grep "^$LONG$"
1052'
1053
1054test_expect_success 'am --quit keeps HEAD where it is' '
1055 mkdir .git/rebase-apply &&
1056 >.git/rebase-apply/last &&
1057 >.git/rebase-apply/next &&
1058 git rev-parse HEAD^ >.git/ORIG_HEAD &&
1059 git rev-parse HEAD >expected &&
1060 git am --quit &&
1061 test_path_is_missing .git/rebase-apply &&
1062 git rev-parse HEAD >actual &&
1063 test_cmp expected actual
1064'
1065
1066test_done