Sync with 2.4.6
[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 -n -e "3,\$p" msg >file &&
109         git add file &&
110         test_tick &&
111         git commit -m third &&
112
113         git format-patch --stdout first >patch2 &&
114
115         git checkout -b lorem &&
116         sed -n -e "11,\$p" msg >file &&
117         head -n 9 msg >>file &&
118         test_tick &&
119         git commit -a -m "moved stuff" &&
120
121         echo goodbye >another &&
122         git add another &&
123         test_tick &&
124         git commit -m "added another file" &&
125
126         git format-patch --stdout master >lorem-move.patch &&
127         git format-patch --no-prefix --stdout master >lorem-zero.patch &&
128
129         git checkout -b rename &&
130         git mv file renamed &&
131         git commit -m "renamed a file" &&
132
133         git format-patch -M --stdout lorem >rename.patch &&
134
135         git reset --soft lorem^ &&
136         git commit -m "renamed a file and added another" &&
137
138         git format-patch -M --stdout lorem^ >rename-add.patch &&
139
140         # reset time
141         sane_unset test_tick &&
142         test_tick
143 '
144
145 test_expect_success 'am applies patch correctly' '
146         rm -fr .git/rebase-apply &&
147         git reset --hard &&
148         git checkout first &&
149         test_tick &&
150         git am <patch1 &&
151         test_path_is_missing .git/rebase-apply &&
152         git diff --exit-code second &&
153         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
154         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
155 '
156
157 test_expect_success 'am applies patch e-mail not in a mbox' '
158         rm -fr .git/rebase-apply &&
159         git reset --hard &&
160         git checkout first &&
161         git am patch1.eml &&
162         test_path_is_missing .git/rebase-apply &&
163         git diff --exit-code second &&
164         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
165         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
166 '
167
168 test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
169         rm -fr .git/rebase-apply &&
170         git reset --hard &&
171         git checkout first &&
172         git am patch1-crlf.eml &&
173         test_path_is_missing .git/rebase-apply &&
174         git diff --exit-code second &&
175         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
176         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
177 '
178
179 test_expect_success 'am applies patch e-mail with preceding whitespace' '
180         rm -fr .git/rebase-apply &&
181         git reset --hard &&
182         git checkout first &&
183         git am patch1-ws.eml &&
184         test_path_is_missing .git/rebase-apply &&
185         git diff --exit-code second &&
186         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
187         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
188 '
189
190 test_expect_success 'setup: new author and committer' '
191         GIT_AUTHOR_NAME="Another Thor" &&
192         GIT_AUTHOR_EMAIL="a.thor@example.com" &&
193         GIT_COMMITTER_NAME="Co M Miter" &&
194         GIT_COMMITTER_EMAIL="c.miter@example.com" &&
195         export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
196 '
197
198 compare () {
199         a=$(git cat-file commit "$2" | grep "^$1 ") &&
200         b=$(git cat-file commit "$3" | grep "^$1 ") &&
201         test "$a" = "$b"
202 }
203
204 test_expect_success 'am changes committer and keeps author' '
205         test_tick &&
206         rm -fr .git/rebase-apply &&
207         git reset --hard &&
208         git checkout first &&
209         git am patch2 &&
210         test_path_is_missing .git/rebase-apply &&
211         test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
212         git diff --exit-code master..HEAD &&
213         git diff --exit-code master^..HEAD^ &&
214         compare author master HEAD &&
215         compare author master^ HEAD^ &&
216         test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
217              "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
218 '
219
220 test_expect_success 'am --signoff adds Signed-off-by: line' '
221         rm -fr .git/rebase-apply &&
222         git reset --hard &&
223         git checkout -b master2 first &&
224         git am --signoff <patch2 &&
225         printf "%s\n" "$signoff" >expected &&
226         echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected &&
227         git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
228         test_cmp expected actual &&
229         echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
230         git cat-file commit HEAD | grep "Signed-off-by:" >actual &&
231         test_cmp expected actual
232 '
233
234 test_expect_success 'am stays in branch' '
235         echo refs/heads/master2 >expected &&
236         git symbolic-ref HEAD >actual &&
237         test_cmp expected actual
238 '
239
240 test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
241         git format-patch --stdout HEAD^ >patch3 &&
242         sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," patch3 >patch4 &&
243         rm -fr .git/rebase-apply &&
244         git reset --hard &&
245         git checkout HEAD^ &&
246         git am --signoff patch4 &&
247         git cat-file commit HEAD >actual &&
248         test $(grep -c "^Signed-off-by:" actual) -eq 1
249 '
250
251 test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
252         git rev-parse HEAD >expected &&
253         git rev-parse master2 >actual &&
254         test_cmp expected actual
255 '
256
257 test_expect_success 'am --keep really keeps the subject' '
258         rm -fr .git/rebase-apply &&
259         git reset --hard &&
260         git checkout HEAD^ &&
261         git am --keep patch4 &&
262         test_path_is_missing .git/rebase-apply &&
263         git cat-file commit HEAD >actual &&
264         grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual
265 '
266
267 test_expect_success 'am --keep-non-patch really keeps the non-patch part' '
268         rm -fr .git/rebase-apply &&
269         git reset --hard &&
270         git checkout HEAD^ &&
271         git am --keep-non-patch patch4 &&
272         test_path_is_missing .git/rebase-apply &&
273         git cat-file commit HEAD >actual &&
274         grep "^\[foo\] third" actual
275 '
276
277 test_expect_success 'setup am -3' '
278         rm -fr .git/rebase-apply &&
279         git reset --hard &&
280         git checkout -b base3way master2 &&
281         sed -n -e "3,\$p" msg >file &&
282         head -n 9 msg >>file &&
283         git add file &&
284         test_tick &&
285         git commit -m "copied stuff"
286 '
287
288 test_expect_success 'am -3 falls back to 3-way merge' '
289         rm -fr .git/rebase-apply &&
290         git reset --hard &&
291         git checkout -b lorem2 base3way &&
292         git am -3 lorem-move.patch &&
293         test_path_is_missing .git/rebase-apply &&
294         git diff --exit-code lorem
295 '
296
297 test_expect_success 'am -3 -p0 can read --no-prefix patch' '
298         rm -fr .git/rebase-apply &&
299         git reset --hard &&
300         git checkout -b lorem3 base3way &&
301         git am -3 -p0 lorem-zero.patch &&
302         test_path_is_missing .git/rebase-apply &&
303         git diff --exit-code lorem
304 '
305
306 test_expect_success 'am with config am.threeWay falls back to 3-way merge' '
307         rm -fr .git/rebase-apply &&
308         git reset --hard &&
309         git checkout -b lorem4 base3way &&
310         test_config am.threeWay 1 &&
311         git am lorem-move.patch &&
312         test_path_is_missing .git/rebase-apply &&
313         git diff --exit-code lorem
314 '
315
316 test_expect_success 'am with config am.threeWay overridden by --no-3way' '
317         rm -fr .git/rebase-apply &&
318         git reset --hard &&
319         git checkout -b lorem5 base3way &&
320         test_config am.threeWay 1 &&
321         test_must_fail git am --no-3way lorem-move.patch &&
322         test_path_is_dir .git/rebase-apply
323 '
324
325 test_expect_success 'am can rename a file' '
326         grep "^rename from" rename.patch &&
327         rm -fr .git/rebase-apply &&
328         git reset --hard &&
329         git checkout lorem^0 &&
330         git am rename.patch &&
331         test_path_is_missing .git/rebase-apply &&
332         git update-index --refresh &&
333         git diff --exit-code rename
334 '
335
336 test_expect_success 'am -3 can rename a file' '
337         grep "^rename from" rename.patch &&
338         rm -fr .git/rebase-apply &&
339         git reset --hard &&
340         git checkout lorem^0 &&
341         git am -3 rename.patch &&
342         test_path_is_missing .git/rebase-apply &&
343         git update-index --refresh &&
344         git diff --exit-code rename
345 '
346
347 test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
348         grep "^rename from" rename-add.patch &&
349         rm -fr .git/rebase-apply &&
350         git reset --hard &&
351         git checkout lorem^0 &&
352         git am -3 rename-add.patch &&
353         test_path_is_missing .git/rebase-apply &&
354         git update-index --refresh &&
355         git diff --exit-code rename
356 '
357
358 test_expect_success 'am -3 -q is quiet' '
359         rm -fr .git/rebase-apply &&
360         git checkout -f lorem2 &&
361         git reset base3way --hard &&
362         git am -3 -q lorem-move.patch >output.out 2>&1 &&
363         ! test -s output.out
364 '
365
366 test_expect_success 'am pauses on conflict' '
367         rm -fr .git/rebase-apply &&
368         git reset --hard &&
369         git checkout lorem2^^ &&
370         test_must_fail git am lorem-move.patch &&
371         test -d .git/rebase-apply
372 '
373
374 test_expect_success 'am --skip works' '
375         echo goodbye >expected &&
376         git am --skip &&
377         test_path_is_missing .git/rebase-apply &&
378         git diff --exit-code lorem2^^ -- file &&
379         test_cmp expected another
380 '
381
382 test_expect_success 'am --abort removes a stray directory' '
383         mkdir .git/rebase-apply &&
384         git am --abort &&
385         test_path_is_missing .git/rebase-apply
386 '
387
388 test_expect_success 'am --resolved works' '
389         echo goodbye >expected &&
390         rm -fr .git/rebase-apply &&
391         git reset --hard &&
392         git checkout lorem2^^ &&
393         test_must_fail git am lorem-move.patch &&
394         test -d .git/rebase-apply &&
395         echo resolved >>file &&
396         git add file &&
397         git am --resolved &&
398         test_path_is_missing .git/rebase-apply &&
399         test_cmp expected another
400 '
401
402 test_expect_success 'am takes patches from a Pine mailbox' '
403         rm -fr .git/rebase-apply &&
404         git reset --hard &&
405         git checkout first &&
406         cat pine patch1 | git am &&
407         test_path_is_missing .git/rebase-apply &&
408         git diff --exit-code master^..HEAD
409 '
410
411 test_expect_success 'am fails on mail without patch' '
412         rm -fr .git/rebase-apply &&
413         git reset --hard &&
414         test_must_fail git am <failmail &&
415         git am --abort &&
416         test_path_is_missing .git/rebase-apply
417 '
418
419 test_expect_success 'am fails on empty patch' '
420         rm -fr .git/rebase-apply &&
421         git reset --hard &&
422         echo "---" >>failmail &&
423         test_must_fail git am <failmail &&
424         git am --skip &&
425         test_path_is_missing .git/rebase-apply
426 '
427
428 test_expect_success 'am works from stdin in subdirectory' '
429         rm -fr subdir &&
430         rm -fr .git/rebase-apply &&
431         git reset --hard &&
432         git checkout first &&
433         (
434                 mkdir -p subdir &&
435                 cd subdir &&
436                 git am <../patch1
437         ) &&
438         git diff --exit-code second
439 '
440
441 test_expect_success 'am works from file (relative path given) in subdirectory' '
442         rm -fr subdir &&
443         rm -fr .git/rebase-apply &&
444         git reset --hard &&
445         git checkout first &&
446         (
447                 mkdir -p subdir &&
448                 cd subdir &&
449                 git am ../patch1
450         ) &&
451         git diff --exit-code second
452 '
453
454 test_expect_success 'am works from file (absolute path given) in subdirectory' '
455         rm -fr subdir &&
456         rm -fr .git/rebase-apply &&
457         git reset --hard &&
458         git checkout first &&
459         P=$(pwd) &&
460         (
461                 mkdir -p subdir &&
462                 cd subdir &&
463                 git am "$P/patch1"
464         ) &&
465         git diff --exit-code second
466 '
467
468 test_expect_success 'am --committer-date-is-author-date' '
469         rm -fr .git/rebase-apply &&
470         git reset --hard &&
471         git checkout first &&
472         test_tick &&
473         git am --committer-date-is-author-date patch1 &&
474         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
475         sed -ne "/^author /s/.*> //p" head1 >at &&
476         sed -ne "/^committer /s/.*> //p" head1 >ct &&
477         test_cmp at ct
478 '
479
480 test_expect_success 'am without --committer-date-is-author-date' '
481         rm -fr .git/rebase-apply &&
482         git reset --hard &&
483         git checkout first &&
484         test_tick &&
485         git am patch1 &&
486         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
487         sed -ne "/^author /s/.*> //p" head1 >at &&
488         sed -ne "/^committer /s/.*> //p" head1 >ct &&
489         ! test_cmp at ct
490 '
491
492 # This checks for +0000 because TZ is set to UTC and that should
493 # show up when the current time is used. The date in message is set
494 # by test_tick that uses -0700 timezone; if this feature does not
495 # work, we will see that instead of +0000.
496 test_expect_success 'am --ignore-date' '
497         rm -fr .git/rebase-apply &&
498         git reset --hard &&
499         git checkout first &&
500         test_tick &&
501         git am --ignore-date patch1 &&
502         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
503         sed -ne "/^author /s/.*> //p" head1 >at &&
504         grep "+0000" at
505 '
506
507 test_expect_success 'am into an unborn branch' '
508         git rev-parse first^{tree} >expected &&
509         rm -fr .git/rebase-apply &&
510         git reset --hard &&
511         rm -fr subdir &&
512         mkdir subdir &&
513         git format-patch --numbered-files -o subdir -1 first &&
514         (
515                 cd subdir &&
516                 git init &&
517                 git am 1
518         ) &&
519         (
520                 cd subdir &&
521                 git rev-parse HEAD^{tree} >../actual
522         ) &&
523         test_cmp expected actual
524 '
525
526 test_expect_success 'am newline in subject' '
527         rm -fr .git/rebase-apply &&
528         git reset --hard &&
529         git checkout first &&
530         test_tick &&
531         sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
532         git am <patchnl >output.out 2>&1 &&
533         test_i18ngrep "^Applying: second \\\n foo$" output.out
534 '
535
536 test_expect_success 'am -q is quiet' '
537         rm -fr .git/rebase-apply &&
538         git reset --hard &&
539         git checkout first &&
540         test_tick &&
541         git am -q <patch1 >output.out 2>&1 &&
542         ! test -s output.out
543 '
544
545 test_expect_success 'am empty-file does not infloop' '
546         rm -fr .git/rebase-apply &&
547         git reset --hard &&
548         touch empty-file &&
549         test_tick &&
550         test_must_fail git am empty-file 2>actual &&
551         echo Patch format detection failed. >expected &&
552         test_i18ncmp expected actual
553 '
554
555 test_expect_success 'am --message-id really adds the message id' '
556         rm -fr .git/rebase-apply &&
557         git reset --hard &&
558         git checkout HEAD^ &&
559         git am --message-id patch1.eml &&
560         test_path_is_missing .git/rebase-apply &&
561         git cat-file commit HEAD | tail -n1 >actual &&
562         grep Message-Id patch1.eml >expected &&
563         test_cmp expected actual
564 '
565
566 test_expect_success 'am --message-id -s signs off after the message id' '
567         rm -fr .git/rebase-apply &&
568         git reset --hard &&
569         git checkout HEAD^ &&
570         git am -s --message-id patch1.eml &&
571         test_path_is_missing .git/rebase-apply &&
572         git cat-file commit HEAD | tail -n2 | head -n1 >actual &&
573         grep Message-Id patch1.eml >expected &&
574         test_cmp expected actual
575 '
576
577 test_done