sparse: allow '{ 0 }' to be used without warnings
[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 --show-current-patch=raw' '
670         git am --show-current-patch=raw >actual.patch &&
671         test_cmp .git/rebase-apply/0001 actual.patch
672 '
673
674 test_expect_success 'am --show-current-patch=diff' '
675         git am --show-current-patch=diff >actual.patch &&
676         test_cmp .git/rebase-apply/patch actual.patch
677 '
678
679 test_expect_success 'am accepts repeated --show-current-patch' '
680         git am --show-current-patch --show-current-patch=raw >actual.patch &&
681         test_cmp .git/rebase-apply/0001 actual.patch
682 '
683
684 test_expect_success 'am detects incompatible --show-current-patch' '
685         test_must_fail git am --show-current-patch=raw --show-current-patch=diff &&
686         test_must_fail git am --show-current-patch --show-current-patch=diff
687 '
688
689 test_expect_success 'am --skip works' '
690         echo goodbye >expected &&
691         git am --skip &&
692         test_path_is_missing .git/rebase-apply &&
693         git diff --exit-code lorem2^^ -- file &&
694         test_cmp expected another
695 '
696
697 test_expect_success 'am --abort removes a stray directory' '
698         mkdir .git/rebase-apply &&
699         git am --abort &&
700         test_path_is_missing .git/rebase-apply
701 '
702
703 test_expect_success 'am refuses patches when paused' '
704         rm -fr .git/rebase-apply &&
705         git reset --hard &&
706         git checkout lorem2^^ &&
707
708         test_must_fail git am lorem-move.patch &&
709         test_path_is_dir .git/rebase-apply &&
710         test_cmp_rev lorem2^^ HEAD &&
711
712         test_must_fail git am <lorem-move.patch &&
713         test_path_is_dir .git/rebase-apply &&
714         test_cmp_rev lorem2^^ HEAD
715 '
716
717 test_expect_success 'am --resolved works' '
718         echo goodbye >expected &&
719         rm -fr .git/rebase-apply &&
720         git reset --hard &&
721         git checkout lorem2^^ &&
722         test_must_fail git am lorem-move.patch &&
723         test -d .git/rebase-apply &&
724         echo resolved >>file &&
725         git add file &&
726         git am --resolved &&
727         test_path_is_missing .git/rebase-apply &&
728         test_cmp expected another
729 '
730
731 test_expect_success 'am --resolved fails if index has no changes' '
732         rm -fr .git/rebase-apply &&
733         git reset --hard &&
734         git checkout lorem2^^ &&
735         test_must_fail git am lorem-move.patch &&
736         test_path_is_dir .git/rebase-apply &&
737         test_cmp_rev lorem2^^ HEAD &&
738         test_must_fail git am --resolved &&
739         test_path_is_dir .git/rebase-apply &&
740         test_cmp_rev lorem2^^ HEAD
741 '
742
743 test_expect_success 'am --resolved fails if index has unmerged entries' '
744         rm -fr .git/rebase-apply &&
745         git reset --hard &&
746         git checkout second &&
747         test_must_fail git am -3 lorem-move.patch &&
748         test_path_is_dir .git/rebase-apply &&
749         test_cmp_rev second HEAD &&
750         test_must_fail git am --resolved >err &&
751         test_path_is_dir .git/rebase-apply &&
752         test_cmp_rev second HEAD &&
753         test_i18ngrep "still have unmerged paths" err
754 '
755
756 test_expect_success 'am takes patches from a Pine mailbox' '
757         rm -fr .git/rebase-apply &&
758         git reset --hard &&
759         git checkout first &&
760         cat pine patch1 | git am &&
761         test_path_is_missing .git/rebase-apply &&
762         git diff --exit-code master^..HEAD
763 '
764
765 test_expect_success 'am fails on mail without patch' '
766         rm -fr .git/rebase-apply &&
767         git reset --hard &&
768         test_must_fail git am <failmail &&
769         git am --abort &&
770         test_path_is_missing .git/rebase-apply
771 '
772
773 test_expect_success 'am fails on empty patch' '
774         rm -fr .git/rebase-apply &&
775         git reset --hard &&
776         echo "---" >>failmail &&
777         test_must_fail git am <failmail &&
778         git am --skip &&
779         test_path_is_missing .git/rebase-apply
780 '
781
782 test_expect_success 'am works from stdin in subdirectory' '
783         rm -fr subdir &&
784         rm -fr .git/rebase-apply &&
785         git reset --hard &&
786         git checkout first &&
787         (
788                 mkdir -p subdir &&
789                 cd subdir &&
790                 git am <../patch1
791         ) &&
792         git diff --exit-code second
793 '
794
795 test_expect_success 'am works from file (relative path given) in subdirectory' '
796         rm -fr subdir &&
797         rm -fr .git/rebase-apply &&
798         git reset --hard &&
799         git checkout first &&
800         (
801                 mkdir -p subdir &&
802                 cd subdir &&
803                 git am ../patch1
804         ) &&
805         git diff --exit-code second
806 '
807
808 test_expect_success 'am works from file (absolute path given) in subdirectory' '
809         rm -fr subdir &&
810         rm -fr .git/rebase-apply &&
811         git reset --hard &&
812         git checkout first &&
813         P=$(pwd) &&
814         (
815                 mkdir -p subdir &&
816                 cd subdir &&
817                 git am "$P/patch1"
818         ) &&
819         git diff --exit-code second
820 '
821
822 test_expect_success 'am --committer-date-is-author-date' '
823         rm -fr .git/rebase-apply &&
824         git reset --hard &&
825         git checkout first &&
826         test_tick &&
827         git am --committer-date-is-author-date patch1 &&
828         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
829         sed -ne "/^author /s/.*> //p" head1 >at &&
830         sed -ne "/^committer /s/.*> //p" head1 >ct &&
831         test_cmp at ct
832 '
833
834 test_expect_success 'am without --committer-date-is-author-date' '
835         rm -fr .git/rebase-apply &&
836         git reset --hard &&
837         git checkout first &&
838         test_tick &&
839         git am patch1 &&
840         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
841         sed -ne "/^author /s/.*> //p" head1 >at &&
842         sed -ne "/^committer /s/.*> //p" head1 >ct &&
843         ! test_cmp at ct
844 '
845
846 # This checks for +0000 because TZ is set to UTC and that should
847 # show up when the current time is used. The date in message is set
848 # by test_tick that uses -0700 timezone; if this feature does not
849 # work, we will see that instead of +0000.
850 test_expect_success 'am --ignore-date' '
851         rm -fr .git/rebase-apply &&
852         git reset --hard &&
853         git checkout first &&
854         test_tick &&
855         git am --ignore-date patch1 &&
856         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
857         sed -ne "/^author /s/.*> //p" head1 >at &&
858         grep "+0000" at
859 '
860
861 test_expect_success 'am into an unborn branch' '
862         git rev-parse first^{tree} >expected &&
863         rm -fr .git/rebase-apply &&
864         git reset --hard &&
865         rm -fr subdir &&
866         mkdir subdir &&
867         git format-patch --numbered-files -o subdir -1 first &&
868         (
869                 cd subdir &&
870                 git init &&
871                 git am 1
872         ) &&
873         (
874                 cd subdir &&
875                 git rev-parse HEAD^{tree} >../actual
876         ) &&
877         test_cmp expected actual
878 '
879
880 test_expect_success 'am newline in subject' '
881         rm -fr .git/rebase-apply &&
882         git reset --hard &&
883         git checkout first &&
884         test_tick &&
885         sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
886         git am <patchnl >output.out 2>&1 &&
887         test_i18ngrep "^Applying: second \\\n foo$" output.out
888 '
889
890 test_expect_success 'am -q is quiet' '
891         rm -fr .git/rebase-apply &&
892         git reset --hard &&
893         git checkout first &&
894         test_tick &&
895         git am -q <patch1 >output.out 2>&1 &&
896         test_must_be_empty output.out
897 '
898
899 test_expect_success 'am empty-file does not infloop' '
900         rm -fr .git/rebase-apply &&
901         git reset --hard &&
902         touch empty-file &&
903         test_tick &&
904         test_must_fail git am empty-file 2>actual &&
905         echo Patch format detection failed. >expected &&
906         test_i18ncmp expected actual
907 '
908
909 test_expect_success 'am --message-id really adds the message id' '
910         rm -fr .git/rebase-apply &&
911         git reset --hard &&
912         git checkout HEAD^ &&
913         git am --message-id patch1.eml &&
914         test_path_is_missing .git/rebase-apply &&
915         git cat-file commit HEAD | tail -n1 >actual &&
916         grep Message-Id patch1.eml >expected &&
917         test_cmp expected actual
918 '
919
920 test_expect_success 'am.messageid really adds the message id' '
921         rm -fr .git/rebase-apply &&
922         git reset --hard &&
923         git checkout HEAD^ &&
924         test_config am.messageid true &&
925         git am patch1.eml &&
926         test_path_is_missing .git/rebase-apply &&
927         git cat-file commit HEAD | tail -n1 >actual &&
928         grep Message-Id patch1.eml >expected &&
929         test_cmp expected actual
930 '
931
932 test_expect_success 'am --message-id -s signs off after the message id' '
933         rm -fr .git/rebase-apply &&
934         git reset --hard &&
935         git checkout HEAD^ &&
936         git am -s --message-id patch1.eml &&
937         test_path_is_missing .git/rebase-apply &&
938         git cat-file commit HEAD | tail -n2 | head -n1 >actual &&
939         grep Message-Id patch1.eml >expected &&
940         test_cmp expected actual
941 '
942
943 test_expect_success 'am -3 works with rerere' '
944         rm -fr .git/rebase-apply &&
945         git reset --hard &&
946
947         # make patches one->two and two->three...
948         test_commit one file &&
949         test_commit two file &&
950         test_commit three file &&
951         git format-patch -2 --stdout >seq.patch &&
952
953         # and create a situation that conflicts...
954         git reset --hard one &&
955         test_commit other file &&
956
957         # enable rerere...
958         test_config rerere.enabled true &&
959         test_when_finished "rm -rf .git/rr-cache" &&
960
961         # ...and apply. Our resolution is to skip the first
962         # patch, and the rerere the second one.
963         test_must_fail git am -3 seq.patch &&
964         test_must_fail git am --skip &&
965         echo resolved >file &&
966         git add file &&
967         git am --resolved &&
968
969         # now apply again, and confirm that rerere engaged (we still
970         # expect failure from am because rerere does not auto-commit
971         # for us).
972         git reset --hard other &&
973         test_must_fail git am -3 seq.patch &&
974         test_must_fail git am --skip &&
975         echo resolved >expect &&
976         test_cmp expect file
977 '
978
979 test_expect_success 'am -s unexpected trailer block' '
980         rm -fr .git/rebase-apply &&
981         git reset --hard &&
982         echo signed >file &&
983         git add file &&
984         cat >msg <<-EOF &&
985         subject here
986
987         Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
988         [jc: tweaked log message]
989         Signed-off-by: J C H <j@c.h>
990         EOF
991         git commit -F msg &&
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                 cat original &&
999                 echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
1000         ) >expect &&
1001         git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
1002         test_cmp expect actual &&
1003
1004         cat >msg <<-\EOF &&
1005         subject here
1006
1007         We make sure that there is a blank line between the log
1008         message proper and Signed-off-by: line added.
1009         EOF
1010         git reset HEAD^ &&
1011         git commit -F msg file &&
1012         git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
1013         git format-patch --stdout -1 >patch &&
1014
1015         git reset --hard HEAD^ &&
1016         git am -s patch &&
1017
1018         (
1019                 cat original &&
1020                 echo &&
1021                 echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
1022         ) >expect &&
1023         git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
1024         test_cmp expect actual
1025 '
1026
1027 test_expect_success 'am --patch-format=mboxrd handles mboxrd' '
1028         rm -fr .git/rebase-apply &&
1029         git checkout -f first &&
1030         echo mboxrd >>file &&
1031         git add file &&
1032         cat >msg <<-\INPUT_END &&
1033         mboxrd should escape the body
1034
1035         From could trip up a loose mbox parser
1036         >From extra escape for reversibility
1037         INPUT_END
1038         git commit -F msg &&
1039         git format-patch --pretty=mboxrd --stdout -1 >mboxrd1 &&
1040         grep "^>From could trip up a loose mbox parser" mboxrd1 &&
1041         git checkout -f first &&
1042         git am --patch-format=mboxrd mboxrd1 &&
1043         git cat-file commit HEAD | tail -n4 >out &&
1044         test_cmp msg out
1045 '
1046
1047 test_expect_success 'am works with multi-line in-body headers' '
1048         FORTY="String that has a length of more than forty characters" &&
1049         LONG="$FORTY $FORTY" &&
1050         rm -fr .git/rebase-apply &&
1051         git checkout -f first &&
1052         echo one >> file &&
1053         git commit -am "$LONG
1054
1055     Body test" --author="$LONG <long@example.com>" &&
1056         git format-patch --stdout -1 >patch &&
1057         # bump from, date, and subject down to in-body header
1058         perl -lpe "
1059                 if (/^From:/) {
1060                         print \"From: x <x\@example.com>\";
1061                         print \"Date: Sat, 1 Jan 2000 00:00:00 +0000\";
1062                         print \"Subject: x\n\";
1063                 }
1064         " patch >msg &&
1065         git checkout HEAD^ &&
1066         git am msg &&
1067         # Ensure that the author and full message are present
1068         git cat-file commit HEAD | grep "^author.*long@example.com" &&
1069         git cat-file commit HEAD | grep "^$LONG$"
1070 '
1071
1072 test_expect_success 'am --quit keeps HEAD where it is' '
1073         mkdir .git/rebase-apply &&
1074         >.git/rebase-apply/last &&
1075         >.git/rebase-apply/next &&
1076         git rev-parse HEAD^ >.git/ORIG_HEAD &&
1077         git rev-parse HEAD >expected &&
1078         git am --quit &&
1079         test_path_is_missing .git/rebase-apply &&
1080         git rev-parse HEAD >actual &&
1081         test_cmp expected actual
1082 '
1083
1084 test_expect_success 'am and .gitattibutes' '
1085         test_create_repo attributes &&
1086         (
1087                 cd attributes &&
1088                 test_commit init &&
1089                 git config filter.test.clean "sed -e '\''s/smudged/clean/g'\''" &&
1090                 git config filter.test.smudge "sed -e '\''s/clean/smudged/g'\''" &&
1091
1092                 test_commit second &&
1093                 git checkout -b test HEAD^ &&
1094
1095                 echo "*.txt filter=test conflict-marker-size=10" >.gitattributes &&
1096                 git add .gitattributes &&
1097                 test_commit third &&
1098
1099                 echo "This text is smudged." >a.txt &&
1100                 git add a.txt &&
1101                 test_commit fourth &&
1102
1103                 git checkout -b removal HEAD^ &&
1104                 git rm .gitattributes &&
1105                 git add -u &&
1106                 test_commit fifth &&
1107                 git cherry-pick test &&
1108
1109                 git checkout -b conflict third &&
1110                 echo "This text is different." >a.txt &&
1111                 git add a.txt &&
1112                 test_commit sixth &&
1113
1114                 git checkout test &&
1115                 git format-patch --stdout master..HEAD >patches &&
1116                 git reset --hard master &&
1117                 git am patches &&
1118                 grep "smudged" a.txt &&
1119
1120                 git checkout removal &&
1121                 git reset --hard &&
1122                 git format-patch --stdout master..HEAD >patches &&
1123                 git reset --hard master &&
1124                 git am patches &&
1125                 grep "clean" a.txt &&
1126
1127                 git checkout conflict &&
1128                 git reset --hard &&
1129                 git format-patch --stdout master..HEAD >patches &&
1130                 git reset --hard fourth &&
1131                 test_must_fail git am -3 patches &&
1132                 grep "<<<<<<<<<<" a.txt
1133         )
1134 '
1135
1136 test_done