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