Merge branch 'jn/maint-do-not-match-with-unsanitized-searchtext' 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         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," 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\] third" actual
264 '
265
266 test_expect_success 'am -3 falls back to 3-way merge' '
267         rm -fr .git/rebase-apply &&
268         git reset --hard &&
269         git checkout -b lorem2 master2 &&
270         sed -n -e "3,\$p" msg >file &&
271         head -n 9 msg >>file &&
272         git add file &&
273         test_tick &&
274         git commit -m "copied stuff" &&
275         git am -3 lorem-move.patch &&
276         ! test -d .git/rebase-apply &&
277         git diff --exit-code lorem
278 '
279
280 test_expect_success 'am -3 -p0 can read --no-prefix patch' '
281         rm -fr .git/rebase-apply &&
282         git reset --hard &&
283         git checkout -b lorem3 master2 &&
284         sed -n -e "3,\$p" msg >file &&
285         head -n 9 msg >>file &&
286         git add file &&
287         test_tick &&
288         git commit -m "copied stuff" &&
289         git am -3 -p0 lorem-zero.patch &&
290         ! test -d .git/rebase-apply &&
291         git diff --exit-code lorem
292 '
293
294 test_expect_success 'am can rename a file' '
295         grep "^rename from" rename.patch &&
296         rm -fr .git/rebase-apply &&
297         git reset --hard &&
298         git checkout lorem^0 &&
299         git am rename.patch &&
300         ! test -d .git/rebase-apply &&
301         git update-index --refresh &&
302         git diff --exit-code rename
303 '
304
305 test_expect_success 'am -3 can rename a file' '
306         grep "^rename from" rename.patch &&
307         rm -fr .git/rebase-apply &&
308         git reset --hard &&
309         git checkout lorem^0 &&
310         git am -3 rename.patch &&
311         ! test -d .git/rebase-apply &&
312         git update-index --refresh &&
313         git diff --exit-code rename
314 '
315
316 test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
317         grep "^rename from" rename-add.patch &&
318         rm -fr .git/rebase-apply &&
319         git reset --hard &&
320         git checkout lorem^0 &&
321         git am -3 rename-add.patch &&
322         ! test -d .git/rebase-apply &&
323         git update-index --refresh &&
324         git diff --exit-code rename
325 '
326
327 test_expect_success 'am -3 -q is quiet' '
328         rm -fr .git/rebase-apply &&
329         git checkout -f lorem2 &&
330         git reset master2 --hard &&
331         sed -n -e "3,\$p" msg >file &&
332         head -n 9 msg >>file &&
333         git add file &&
334         test_tick &&
335         git commit -m "copied stuff" &&
336         git am -3 -q lorem-move.patch >output.out 2>&1 &&
337         ! test -s output.out
338 '
339
340 test_expect_success 'am pauses on conflict' '
341         rm -fr .git/rebase-apply &&
342         git reset --hard &&
343         git checkout lorem2^^ &&
344         test_must_fail git am lorem-move.patch &&
345         test -d .git/rebase-apply
346 '
347
348 test_expect_success 'am --skip works' '
349         echo goodbye >expected &&
350         git am --skip &&
351         ! test -d .git/rebase-apply &&
352         git diff --exit-code lorem2^^ -- file &&
353         test_cmp expected another
354 '
355
356 test_expect_success 'am --resolved works' '
357         echo goodbye >expected &&
358         rm -fr .git/rebase-apply &&
359         git reset --hard &&
360         git checkout lorem2^^ &&
361         test_must_fail git am lorem-move.patch &&
362         test -d .git/rebase-apply &&
363         echo resolved >>file &&
364         git add file &&
365         git am --resolved &&
366         ! test -d .git/rebase-apply &&
367         test_cmp expected another
368 '
369
370 test_expect_success 'am takes patches from a Pine mailbox' '
371         rm -fr .git/rebase-apply &&
372         git reset --hard &&
373         git checkout first &&
374         cat pine patch1 | git am &&
375         ! test -d .git/rebase-apply &&
376         git diff --exit-code master^..HEAD
377 '
378
379 test_expect_success 'am fails on mail without patch' '
380         rm -fr .git/rebase-apply &&
381         git reset --hard &&
382         test_must_fail git am <failmail &&
383         git am --abort &&
384         ! test -d .git/rebase-apply
385 '
386
387 test_expect_success 'am fails on empty patch' '
388         rm -fr .git/rebase-apply &&
389         git reset --hard &&
390         echo "---" >>failmail &&
391         test_must_fail git am <failmail &&
392         git am --skip &&
393         ! test -d .git/rebase-apply
394 '
395
396 test_expect_success 'am works from stdin in subdirectory' '
397         rm -fr subdir &&
398         rm -fr .git/rebase-apply &&
399         git reset --hard &&
400         git checkout first &&
401         (
402                 mkdir -p subdir &&
403                 cd subdir &&
404                 git am <../patch1
405         ) &&
406         git diff --exit-code second
407 '
408
409 test_expect_success 'am works from file (relative path given) in subdirectory' '
410         rm -fr subdir &&
411         rm -fr .git/rebase-apply &&
412         git reset --hard &&
413         git checkout first &&
414         (
415                 mkdir -p subdir &&
416                 cd subdir &&
417                 git am ../patch1
418         ) &&
419         git diff --exit-code second
420 '
421
422 test_expect_success 'am works from file (absolute path given) in subdirectory' '
423         rm -fr subdir &&
424         rm -fr .git/rebase-apply &&
425         git reset --hard &&
426         git checkout first &&
427         P=$(pwd) &&
428         (
429                 mkdir -p subdir &&
430                 cd subdir &&
431                 git am "$P/patch1"
432         ) &&
433         git diff --exit-code second
434 '
435
436 test_expect_success 'am --committer-date-is-author-date' '
437         rm -fr .git/rebase-apply &&
438         git reset --hard &&
439         git checkout first &&
440         test_tick &&
441         git am --committer-date-is-author-date patch1 &&
442         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
443         sed -ne "/^author /s/.*> //p" head1 >at &&
444         sed -ne "/^committer /s/.*> //p" head1 >ct &&
445         test_cmp at ct
446 '
447
448 test_expect_success 'am without --committer-date-is-author-date' '
449         rm -fr .git/rebase-apply &&
450         git reset --hard &&
451         git checkout first &&
452         test_tick &&
453         git am patch1 &&
454         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
455         sed -ne "/^author /s/.*> //p" head1 >at &&
456         sed -ne "/^committer /s/.*> //p" head1 >ct &&
457         ! test_cmp at ct
458 '
459
460 # This checks for +0000 because TZ is set to UTC and that should
461 # show up when the current time is used. The date in message is set
462 # by test_tick that uses -0700 timezone; if this feature does not
463 # work, we will see that instead of +0000.
464 test_expect_success 'am --ignore-date' '
465         rm -fr .git/rebase-apply &&
466         git reset --hard &&
467         git checkout first &&
468         test_tick &&
469         git am --ignore-date patch1 &&
470         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
471         sed -ne "/^author /s/.*> //p" head1 >at &&
472         grep "+0000" at
473 '
474
475 test_expect_success 'am into an unborn branch' '
476         git rev-parse first^{tree} >expected &&
477         rm -fr .git/rebase-apply &&
478         git reset --hard &&
479         rm -fr subdir &&
480         mkdir subdir &&
481         git format-patch --numbered-files -o subdir -1 first &&
482         (
483                 cd subdir &&
484                 git init &&
485                 git am 1
486         ) &&
487         (
488                 cd subdir &&
489                 git rev-parse HEAD^{tree} >../actual
490         ) &&
491         test_cmp expected actual
492 '
493
494 test_expect_success 'am newline in subject' '
495         rm -fr .git/rebase-apply &&
496         git reset --hard &&
497         git checkout first &&
498         test_tick &&
499         sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
500         git am <patchnl >output.out 2>&1 &&
501         test_i18ngrep "^Applying: second \\\n foo$" output.out
502 '
503
504 test_expect_success 'am -q is quiet' '
505         rm -fr .git/rebase-apply &&
506         git reset --hard &&
507         git checkout first &&
508         test_tick &&
509         git am -q <patch1 >output.out 2>&1 &&
510         ! test -s output.out
511 '
512
513 test_expect_success 'am empty-file does not infloop' '
514         rm -fr .git/rebase-apply &&
515         git reset --hard &&
516         touch empty-file &&
517         test_tick &&
518         { git am empty-file > actual 2>&1 && false || :; } &&
519         echo Patch format detection failed. >expected &&
520         test_cmp expected actual
521 '
522
523 test_done