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