Merge branch 'pt/am-foreign'
[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         EOF
44
45         cat >failmail <<-\EOF &&
46         From foo@example.com Fri May 23 10:43:49 2008
47         From:   foo@example.com
48         To:     bar@example.com
49         Subject: Re: [RFC/PATCH] git-foo.sh
50         Date:   Fri, 23 May 2008 05:23:42 +0200
51
52         Sometimes we have to find out that there'\''s nothing left.
53
54         EOF
55
56         cat >pine <<-\EOF &&
57         From MAILER-DAEMON Fri May 23 10:43:49 2008
58         Date: 23 May 2008 05:23:42 +0200
59         From: Mail System Internal Data <MAILER-DAEMON@example.com>
60         Subject: DON'\''T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA
61         Message-ID: <foo-0001@example.com>
62
63         This text is part of the internal format of your mail folder, and is not
64         a real message.  It is created automatically by the mail system software.
65         If deleted, important folder data will be lost, and it will be re-created
66         with the data reset to initial values.
67
68         EOF
69
70         signoff="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
71 '
72
73 test_expect_success setup '
74         echo hello >file &&
75         git add file &&
76         test_tick &&
77         git commit -m first &&
78         git tag first &&
79
80         echo world >>file &&
81         git add file &&
82         test_tick &&
83         git commit -s -F msg &&
84         git tag second &&
85
86         git format-patch --stdout first >patch1 &&
87         {
88                 echo "Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>" &&
89                 echo "X-Fake-Field: Line One" &&
90                 echo "X-Fake-Field: Line Two" &&
91                 echo "X-Fake-Field: Line Three" &&
92                 git format-patch --stdout first | sed -e "1d"
93         } > patch1.eml &&
94         {
95                 echo "X-Fake-Field: Line One" &&
96                 echo "X-Fake-Field: Line Two" &&
97                 echo "X-Fake-Field: Line Three" &&
98                 git format-patch --stdout first | sed -e "1d"
99         } | append_cr >patch1-crlf.eml &&
100         {
101                 printf "%255s\\n" ""
102                 echo "X-Fake-Field: Line One" &&
103                 echo "X-Fake-Field: Line Two" &&
104                 echo "X-Fake-Field: Line Three" &&
105                 git format-patch --stdout first | sed -e "1d"
106         } > patch1-ws.eml &&
107         {
108                 sed -ne "1p" msg &&
109                 echo &&
110                 echo "From: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" &&
111                 echo "Date: $GIT_AUTHOR_DATE" &&
112                 echo &&
113                 sed -e "1,2d" msg &&
114                 echo &&
115                 echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" &&
116                 echo "---" &&
117                 git diff-tree --no-commit-id --stat -p second
118         } >patch1-stgit.eml &&
119         mkdir stgit-series &&
120         cp patch1-stgit.eml stgit-series/patch &&
121         {
122                 echo "# This series applies on GIT commit $(git rev-parse first)" &&
123                 echo "patch"
124         } >stgit-series/series &&
125         {
126                 echo "# HG changeset patch" &&
127                 echo "# User $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" &&
128                 echo "# Date $test_tick 25200" &&
129                 echo "#      $(git show --pretty="%aD" -s second)" &&
130                 echo "# Node ID $_z40" &&
131                 echo "# Parent  $_z40" &&
132                 cat msg &&
133                 echo &&
134                 echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" &&
135                 echo &&
136                 git diff-tree --no-commit-id -p second
137         } >patch1-hg.eml &&
138
139
140         sed -n -e "3,\$p" msg >file &&
141         git add file &&
142         test_tick &&
143         git commit -m third &&
144
145         git format-patch --stdout first >patch2 &&
146
147         git checkout -b lorem &&
148         sed -n -e "11,\$p" msg >file &&
149         head -n 9 msg >>file &&
150         test_tick &&
151         git commit -a -m "moved stuff" &&
152
153         echo goodbye >another &&
154         git add another &&
155         test_tick &&
156         git commit -m "added another file" &&
157
158         git format-patch --stdout master >lorem-move.patch &&
159         git format-patch --no-prefix --stdout master >lorem-zero.patch &&
160
161         git checkout -b rename &&
162         git mv file renamed &&
163         git commit -m "renamed a file" &&
164
165         git format-patch -M --stdout lorem >rename.patch &&
166
167         git reset --soft lorem^ &&
168         git commit -m "renamed a file and added another" &&
169
170         git format-patch -M --stdout lorem^ >rename-add.patch &&
171
172         # reset time
173         sane_unset test_tick &&
174         test_tick
175 '
176
177 test_expect_success 'am applies patch correctly' '
178         rm -fr .git/rebase-apply &&
179         git reset --hard &&
180         git checkout first &&
181         test_tick &&
182         git am <patch1 &&
183         test_path_is_missing .git/rebase-apply &&
184         git diff --exit-code second &&
185         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
186         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
187 '
188
189 test_expect_success 'am applies patch e-mail not in a mbox' '
190         rm -fr .git/rebase-apply &&
191         git reset --hard &&
192         git checkout first &&
193         git am patch1.eml &&
194         test_path_is_missing .git/rebase-apply &&
195         git diff --exit-code second &&
196         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
197         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
198 '
199
200 test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
201         rm -fr .git/rebase-apply &&
202         git reset --hard &&
203         git checkout first &&
204         git am patch1-crlf.eml &&
205         test_path_is_missing .git/rebase-apply &&
206         git diff --exit-code second &&
207         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
208         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
209 '
210
211 test_expect_success 'am applies patch e-mail with preceding whitespace' '
212         rm -fr .git/rebase-apply &&
213         git reset --hard &&
214         git checkout first &&
215         git am patch1-ws.eml &&
216         test_path_is_missing .git/rebase-apply &&
217         git diff --exit-code second &&
218         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
219         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
220 '
221
222 test_expect_success 'am applies stgit patch' '
223         rm -fr .git/rebase-apply &&
224         git checkout -f first &&
225         git am patch1-stgit.eml &&
226         test_path_is_missing .git/rebase-apply &&
227         git diff --exit-code second &&
228         test_cmp_rev second HEAD &&
229         test_cmp_rev second^ HEAD^
230 '
231
232 test_expect_success 'am --patch-format=stgit applies stgit patch' '
233         rm -fr .git/rebase-apply &&
234         git checkout -f first &&
235         git am --patch-format=stgit <patch1-stgit.eml &&
236         test_path_is_missing .git/rebase-apply &&
237         git diff --exit-code second &&
238         test_cmp_rev second HEAD &&
239         test_cmp_rev second^ HEAD^
240 '
241
242 test_expect_success 'am applies stgit series' '
243         rm -fr .git/rebase-apply &&
244         git checkout -f first &&
245         git am stgit-series/series &&
246         test_path_is_missing .git/rebase-apply &&
247         git diff --exit-code second &&
248         test_cmp_rev second HEAD &&
249         test_cmp_rev second^ HEAD^
250 '
251
252 test_expect_success 'am applies hg patch' '
253         rm -fr .git/rebase-apply &&
254         git checkout -f first &&
255         git am patch1-hg.eml &&
256         test_path_is_missing .git/rebase-apply &&
257         git diff --exit-code second &&
258         test_cmp_rev second HEAD &&
259         test_cmp_rev second^ HEAD^
260 '
261
262 test_expect_success 'am --patch-format=hg applies hg patch' '
263         rm -fr .git/rebase-apply &&
264         git checkout -f first &&
265         git am --patch-format=hg <patch1-hg.eml &&
266         test_path_is_missing .git/rebase-apply &&
267         git diff --exit-code second &&
268         test_cmp_rev second HEAD &&
269         test_cmp_rev second^ HEAD^
270 '
271
272 test_expect_success 'setup: new author and committer' '
273         GIT_AUTHOR_NAME="Another Thor" &&
274         GIT_AUTHOR_EMAIL="a.thor@example.com" &&
275         GIT_COMMITTER_NAME="Co M Miter" &&
276         GIT_COMMITTER_EMAIL="c.miter@example.com" &&
277         export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
278 '
279
280 compare () {
281         a=$(git cat-file commit "$2" | grep "^$1 ") &&
282         b=$(git cat-file commit "$3" | grep "^$1 ") &&
283         test "$a" = "$b"
284 }
285
286 test_expect_success 'am changes committer and keeps author' '
287         test_tick &&
288         rm -fr .git/rebase-apply &&
289         git reset --hard &&
290         git checkout first &&
291         git am patch2 &&
292         test_path_is_missing .git/rebase-apply &&
293         test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
294         git diff --exit-code master..HEAD &&
295         git diff --exit-code master^..HEAD^ &&
296         compare author master HEAD &&
297         compare author master^ HEAD^ &&
298         test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
299              "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
300 '
301
302 test_expect_success 'am --signoff adds Signed-off-by: line' '
303         rm -fr .git/rebase-apply &&
304         git reset --hard &&
305         git checkout -b master2 first &&
306         git am --signoff <patch2 &&
307         printf "%s\n" "$signoff" >expected &&
308         echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected &&
309         git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
310         test_cmp expected actual &&
311         echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
312         git cat-file commit HEAD | grep "Signed-off-by:" >actual &&
313         test_cmp expected actual
314 '
315
316 test_expect_success 'am stays in branch' '
317         echo refs/heads/master2 >expected &&
318         git symbolic-ref HEAD >actual &&
319         test_cmp expected actual
320 '
321
322 test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
323         git format-patch --stdout HEAD^ >patch3 &&
324         sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," patch3 >patch4 &&
325         rm -fr .git/rebase-apply &&
326         git reset --hard &&
327         git checkout HEAD^ &&
328         git am --signoff patch4 &&
329         git cat-file commit HEAD >actual &&
330         test $(grep -c "^Signed-off-by:" actual) -eq 1
331 '
332
333 test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
334         git rev-parse HEAD >expected &&
335         git rev-parse master2 >actual &&
336         test_cmp expected actual
337 '
338
339 test_expect_success 'am --keep really keeps the subject' '
340         rm -fr .git/rebase-apply &&
341         git reset --hard &&
342         git checkout HEAD^ &&
343         git am --keep patch4 &&
344         test_path_is_missing .git/rebase-apply &&
345         git cat-file commit HEAD >actual &&
346         grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual
347 '
348
349 test_expect_success 'am --keep-non-patch really keeps the non-patch part' '
350         rm -fr .git/rebase-apply &&
351         git reset --hard &&
352         git checkout HEAD^ &&
353         git am --keep-non-patch patch4 &&
354         test_path_is_missing .git/rebase-apply &&
355         git cat-file commit HEAD >actual &&
356         grep "^\[foo\] third" actual
357 '
358
359 test_expect_success 'setup am -3' '
360         rm -fr .git/rebase-apply &&
361         git reset --hard &&
362         git checkout -b base3way master2 &&
363         sed -n -e "3,\$p" msg >file &&
364         head -n 9 msg >>file &&
365         git add file &&
366         test_tick &&
367         git commit -m "copied stuff"
368 '
369
370 test_expect_success 'am -3 falls back to 3-way merge' '
371         rm -fr .git/rebase-apply &&
372         git reset --hard &&
373         git checkout -b lorem2 base3way &&
374         git am -3 lorem-move.patch &&
375         test_path_is_missing .git/rebase-apply &&
376         git diff --exit-code lorem
377 '
378
379 test_expect_success 'am -3 -p0 can read --no-prefix patch' '
380         rm -fr .git/rebase-apply &&
381         git reset --hard &&
382         git checkout -b lorem3 base3way &&
383         git am -3 -p0 lorem-zero.patch &&
384         test_path_is_missing .git/rebase-apply &&
385         git diff --exit-code lorem
386 '
387
388 test_expect_success 'am can rename a file' '
389         grep "^rename from" rename.patch &&
390         rm -fr .git/rebase-apply &&
391         git reset --hard &&
392         git checkout lorem^0 &&
393         git am rename.patch &&
394         test_path_is_missing .git/rebase-apply &&
395         git update-index --refresh &&
396         git diff --exit-code rename
397 '
398
399 test_expect_success 'am -3 can rename a file' '
400         grep "^rename from" rename.patch &&
401         rm -fr .git/rebase-apply &&
402         git reset --hard &&
403         git checkout lorem^0 &&
404         git am -3 rename.patch &&
405         test_path_is_missing .git/rebase-apply &&
406         git update-index --refresh &&
407         git diff --exit-code rename
408 '
409
410 test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
411         grep "^rename from" rename-add.patch &&
412         rm -fr .git/rebase-apply &&
413         git reset --hard &&
414         git checkout lorem^0 &&
415         git am -3 rename-add.patch &&
416         test_path_is_missing .git/rebase-apply &&
417         git update-index --refresh &&
418         git diff --exit-code rename
419 '
420
421 test_expect_success 'am -3 -q is quiet' '
422         rm -fr .git/rebase-apply &&
423         git checkout -f lorem2 &&
424         git reset base3way --hard &&
425         git am -3 -q lorem-move.patch >output.out 2>&1 &&
426         ! test -s output.out
427 '
428
429 test_expect_success 'am pauses on conflict' '
430         rm -fr .git/rebase-apply &&
431         git reset --hard &&
432         git checkout lorem2^^ &&
433         test_must_fail git am lorem-move.patch &&
434         test -d .git/rebase-apply
435 '
436
437 test_expect_success 'am --skip works' '
438         echo goodbye >expected &&
439         git am --skip &&
440         test_path_is_missing .git/rebase-apply &&
441         git diff --exit-code lorem2^^ -- file &&
442         test_cmp expected another
443 '
444
445 test_expect_success 'am --abort removes a stray directory' '
446         mkdir .git/rebase-apply &&
447         git am --abort &&
448         test_path_is_missing .git/rebase-apply
449 '
450
451 test_expect_success 'am --resolved works' '
452         echo goodbye >expected &&
453         rm -fr .git/rebase-apply &&
454         git reset --hard &&
455         git checkout lorem2^^ &&
456         test_must_fail git am lorem-move.patch &&
457         test -d .git/rebase-apply &&
458         echo resolved >>file &&
459         git add file &&
460         git am --resolved &&
461         test_path_is_missing .git/rebase-apply &&
462         test_cmp expected another
463 '
464
465 test_expect_success 'am takes patches from a Pine mailbox' '
466         rm -fr .git/rebase-apply &&
467         git reset --hard &&
468         git checkout first &&
469         cat pine patch1 | git am &&
470         test_path_is_missing .git/rebase-apply &&
471         git diff --exit-code master^..HEAD
472 '
473
474 test_expect_success 'am fails on mail without patch' '
475         rm -fr .git/rebase-apply &&
476         git reset --hard &&
477         test_must_fail git am <failmail &&
478         git am --abort &&
479         test_path_is_missing .git/rebase-apply
480 '
481
482 test_expect_success 'am fails on empty patch' '
483         rm -fr .git/rebase-apply &&
484         git reset --hard &&
485         echo "---" >>failmail &&
486         test_must_fail git am <failmail &&
487         git am --skip &&
488         test_path_is_missing .git/rebase-apply
489 '
490
491 test_expect_success 'am works from stdin in subdirectory' '
492         rm -fr subdir &&
493         rm -fr .git/rebase-apply &&
494         git reset --hard &&
495         git checkout first &&
496         (
497                 mkdir -p subdir &&
498                 cd subdir &&
499                 git am <../patch1
500         ) &&
501         git diff --exit-code second
502 '
503
504 test_expect_success 'am works from file (relative path given) in subdirectory' '
505         rm -fr subdir &&
506         rm -fr .git/rebase-apply &&
507         git reset --hard &&
508         git checkout first &&
509         (
510                 mkdir -p subdir &&
511                 cd subdir &&
512                 git am ../patch1
513         ) &&
514         git diff --exit-code second
515 '
516
517 test_expect_success 'am works from file (absolute path given) in subdirectory' '
518         rm -fr subdir &&
519         rm -fr .git/rebase-apply &&
520         git reset --hard &&
521         git checkout first &&
522         P=$(pwd) &&
523         (
524                 mkdir -p subdir &&
525                 cd subdir &&
526                 git am "$P/patch1"
527         ) &&
528         git diff --exit-code second
529 '
530
531 test_expect_success 'am --committer-date-is-author-date' '
532         rm -fr .git/rebase-apply &&
533         git reset --hard &&
534         git checkout first &&
535         test_tick &&
536         git am --committer-date-is-author-date patch1 &&
537         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
538         sed -ne "/^author /s/.*> //p" head1 >at &&
539         sed -ne "/^committer /s/.*> //p" head1 >ct &&
540         test_cmp at ct
541 '
542
543 test_expect_success 'am without --committer-date-is-author-date' '
544         rm -fr .git/rebase-apply &&
545         git reset --hard &&
546         git checkout first &&
547         test_tick &&
548         git am patch1 &&
549         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
550         sed -ne "/^author /s/.*> //p" head1 >at &&
551         sed -ne "/^committer /s/.*> //p" head1 >ct &&
552         ! test_cmp at ct
553 '
554
555 # This checks for +0000 because TZ is set to UTC and that should
556 # show up when the current time is used. The date in message is set
557 # by test_tick that uses -0700 timezone; if this feature does not
558 # work, we will see that instead of +0000.
559 test_expect_success 'am --ignore-date' '
560         rm -fr .git/rebase-apply &&
561         git reset --hard &&
562         git checkout first &&
563         test_tick &&
564         git am --ignore-date patch1 &&
565         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
566         sed -ne "/^author /s/.*> //p" head1 >at &&
567         grep "+0000" at
568 '
569
570 test_expect_success 'am into an unborn branch' '
571         git rev-parse first^{tree} >expected &&
572         rm -fr .git/rebase-apply &&
573         git reset --hard &&
574         rm -fr subdir &&
575         mkdir subdir &&
576         git format-patch --numbered-files -o subdir -1 first &&
577         (
578                 cd subdir &&
579                 git init &&
580                 git am 1
581         ) &&
582         (
583                 cd subdir &&
584                 git rev-parse HEAD^{tree} >../actual
585         ) &&
586         test_cmp expected actual
587 '
588
589 test_expect_success 'am newline in subject' '
590         rm -fr .git/rebase-apply &&
591         git reset --hard &&
592         git checkout first &&
593         test_tick &&
594         sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
595         git am <patchnl >output.out 2>&1 &&
596         test_i18ngrep "^Applying: second \\\n foo$" output.out
597 '
598
599 test_expect_success 'am -q is quiet' '
600         rm -fr .git/rebase-apply &&
601         git reset --hard &&
602         git checkout first &&
603         test_tick &&
604         git am -q <patch1 >output.out 2>&1 &&
605         ! test -s output.out
606 '
607
608 test_expect_success 'am empty-file does not infloop' '
609         rm -fr .git/rebase-apply &&
610         git reset --hard &&
611         touch empty-file &&
612         test_tick &&
613         test_must_fail git am empty-file 2>actual &&
614         echo Patch format detection failed. >expected &&
615         test_i18ncmp expected actual
616 '
617
618 test_expect_success 'am --message-id really adds the message id' '
619         rm -fr .git/rebase-apply &&
620         git reset --hard &&
621         git checkout HEAD^ &&
622         git am --message-id patch1.eml &&
623         test_path_is_missing .git/rebase-apply &&
624         git cat-file commit HEAD | tail -n1 >actual &&
625         grep Message-Id patch1.eml >expected &&
626         test_cmp expected actual
627 '
628
629 test_expect_success 'am --message-id -s signs off after the message id' '
630         rm -fr .git/rebase-apply &&
631         git reset --hard &&
632         git checkout HEAD^ &&
633         git am -s --message-id patch1.eml &&
634         test_path_is_missing .git/rebase-apply &&
635         git cat-file commit HEAD | tail -n2 | head -n1 >actual &&
636         grep Message-Id patch1.eml >expected &&
637         test_cmp expected actual
638 '
639
640 test_done