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