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