1 #!/bin/sh
3 test_description='git am running'
5 . ./test-lib.sh
7 test_expect_success 'setup: messages' '
8 cat >msg <<-\EOF &&
9 second
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.
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 &&
29 Lorem ipsum dolor sit amet,
30 consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
31 laoreet dolore magna aliquam erat volutpat.
33 git
34 ---
35 +++
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
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
52 Sometimes we have to find out that there'\''s nothing left.
54 EOF
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>
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.
68 EOF
70 signoff="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
71 '
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 &&
80 echo world >>file &&
81 git add file &&
82 test_tick &&
83 git commit -s -F msg &&
84 git tag second &&
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 &&
100 sed -n -e "3,\$p" msg >file &&
101 git add file &&
102 test_tick &&
103 git commit -m third &&
105 git format-patch --stdout first >patch2 &&
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" &&
113 echo goodbye >another &&
114 git add another &&
115 test_tick &&
116 git commit -m "added another file" &&
118 git format-patch --stdout master >lorem-move.patch &&
119 # reset time
120 unset test_tick &&
121 test_tick
122 '
124 test_expect_success 'am applies patch correctly' '
125 git checkout first &&
126 test_tick &&
127 git am <patch1 &&
128 ! test -d .git/rebase-apply &&
129 git diff --exit-code second &&
130 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
131 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
132 '
134 test_expect_success 'am applies patch e-mail not in a mbox' '
135 git checkout first &&
136 git am patch1.eml &&
137 ! test -d .git/rebase-apply &&
138 git diff --exit-code second &&
139 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
140 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
141 '
143 test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
144 git checkout first &&
145 git am patch1-crlf.eml &&
146 ! test -d .git/rebase-apply &&
147 git diff --exit-code second &&
148 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
149 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
150 '
152 test_expect_success 'setup: new author and committer' '
153 GIT_AUTHOR_NAME="Another Thor" &&
154 GIT_AUTHOR_EMAIL="a.thor@example.com" &&
155 GIT_COMMITTER_NAME="Co M Miter" &&
156 GIT_COMMITTER_EMAIL="c.miter@example.com" &&
157 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
158 '
160 compare () {
161 a=$(git cat-file commit "$2" | grep "^$1 ") &&
162 b=$(git cat-file commit "$3" | grep "^$1 ") &&
163 test "$a" = "$b"
164 }
166 test_expect_success 'am changes committer and keeps author' '
167 test_tick &&
168 git checkout first &&
169 git am patch2 &&
170 ! test -d .git/rebase-apply &&
171 test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
172 git diff --exit-code master..HEAD &&
173 git diff --exit-code master^..HEAD^ &&
174 compare author master HEAD &&
175 compare author master^ HEAD^ &&
176 test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
177 "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
178 '
180 test_expect_success 'am --signoff adds Signed-off-by: line' '
181 git checkout -b master2 first &&
182 git am --signoff <patch2 &&
183 printf "%s\n" "$signoff" >expected &&
184 echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected &&
185 git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
186 test_cmp expected actual &&
187 echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
188 git cat-file commit HEAD | grep "Signed-off-by:" >actual &&
189 test_cmp expected actual
190 '
192 test_expect_success 'am stays in branch' '
193 echo refs/heads/master2 >expected &&
194 git symbolic-ref HEAD >actual &&
195 test_cmp expected actual
196 '
198 test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
199 git format-patch --stdout HEAD^ >patch3 &&
200 sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2," patch3 >patch4
201 git checkout HEAD^ &&
202 git am --signoff patch4 &&
203 git cat-file commit HEAD >actual &&
204 test $(grep -c "^Signed-off-by:" actual) -eq 1
205 '
207 test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
208 git rev-parse HEAD >expected &&
209 git rev-parse master2 >actual &&
210 test_cmp expected actual
211 '
213 test_expect_success 'am --keep really keeps the subject' '
214 git checkout HEAD^ &&
215 git am --keep patch4 &&
216 ! test -d .git/rebase-apply &&
217 git cat-file commit HEAD >actual &&
218 grep "Re: Re: Re: \[PATCH 1/5 v2\] third" actual
219 '
221 test_expect_success 'am -3 falls back to 3-way merge' '
222 git checkout -b lorem2 master2 &&
223 sed -n -e "3,\$p" msg >file &&
224 head -n 9 msg >>file &&
225 git add file &&
226 test_tick &&
227 git commit -m "copied stuff" &&
228 git am -3 lorem-move.patch &&
229 ! test -d .git/rebase-apply &&
230 git diff --exit-code lorem
231 '
233 test_expect_success 'am -3 -q is quiet' '
234 git reset master2 --hard &&
235 sed -n -e "3,\$p" msg >file &&
236 head -n 9 msg >>file &&
237 git add file &&
238 test_tick &&
239 git commit -m "copied stuff" &&
240 git am -3 -q lorem-move.patch >output.out 2>&1 &&
241 ! test -s output.out
242 '
244 test_expect_success 'am pauses on conflict' '
245 git checkout lorem2^^ &&
246 test_must_fail git am lorem-move.patch &&
247 test -d .git/rebase-apply
248 '
250 test_expect_success 'am --skip works' '
251 echo goodbye >expected &&
252 git am --skip &&
253 ! test -d .git/rebase-apply &&
254 git diff --exit-code lorem2^^ -- file &&
255 test_cmp expected another
256 '
258 test_expect_success 'am --resolved works' '
259 echo goodbye >expected &&
260 git checkout lorem2^^ &&
261 test_must_fail git am lorem-move.patch &&
262 test -d .git/rebase-apply &&
263 echo resolved >>file &&
264 git add file &&
265 git am --resolved &&
266 ! test -d .git/rebase-apply &&
267 test_cmp expected another
268 '
270 test_expect_success 'am takes patches from a Pine mailbox' '
271 git checkout first &&
272 cat pine patch1 | git am &&
273 ! test -d .git/rebase-apply &&
274 git diff --exit-code master^..HEAD
275 '
277 test_expect_success 'am fails on mail without patch' '
278 test_must_fail git am <failmail &&
279 rm -r .git/rebase-apply/
280 '
282 test_expect_success 'am fails on empty patch' '
283 echo "---" >>failmail &&
284 test_must_fail git am <failmail &&
285 git am --skip &&
286 ! test -d .git/rebase-apply
287 '
289 test_expect_success 'am works from stdin in subdirectory' '
290 rm -fr subdir &&
291 git checkout first &&
292 (
293 mkdir -p subdir &&
294 cd subdir &&
295 git am <../patch1
296 ) &&
297 git diff --exit-code second
298 '
300 test_expect_success 'am works from file (relative path given) in subdirectory' '
301 rm -fr subdir &&
302 git checkout first &&
303 (
304 mkdir -p subdir &&
305 cd subdir &&
306 git am ../patch1
307 ) &&
308 git diff --exit-code second
309 '
311 test_expect_success 'am works from file (absolute path given) in subdirectory' '
312 rm -fr subdir &&
313 git checkout first &&
314 P=$(pwd) &&
315 (
316 mkdir -p subdir &&
317 cd subdir &&
318 git am "$P/patch1"
319 ) &&
320 git diff --exit-code second
321 '
323 test_expect_success 'am --committer-date-is-author-date' '
324 git checkout first &&
325 test_tick &&
326 git am --committer-date-is-author-date patch1 &&
327 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
328 sed -ne "/^author /s/.*> //p" head1 >at &&
329 sed -ne "/^committer /s/.*> //p" head1 >ct &&
330 test_cmp at ct
331 '
333 test_expect_success 'am without --committer-date-is-author-date' '
334 git checkout first &&
335 test_tick &&
336 git am patch1 &&
337 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
338 sed -ne "/^author /s/.*> //p" head1 >at &&
339 sed -ne "/^committer /s/.*> //p" head1 >ct &&
340 ! test_cmp at ct
341 '
343 # This checks for +0000 because TZ is set to UTC and that should
344 # show up when the current time is used. The date in message is set
345 # by test_tick that uses -0700 timezone; if this feature does not
346 # work, we will see that instead of +0000.
347 test_expect_success 'am --ignore-date' '
348 git checkout first &&
349 test_tick &&
350 git am --ignore-date patch1 &&
351 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
352 sed -ne "/^author /s/.*> //p" head1 >at &&
353 grep "+0000" at
354 '
356 test_expect_success 'am into an unborn branch' '
357 git rev-parse first^{tree} >expected &&
358 rm -fr subdir &&
359 mkdir subdir &&
360 git format-patch --numbered-files -o subdir -1 first &&
361 (
362 cd subdir &&
363 git init &&
364 git am 1
365 ) &&
366 (
367 cd subdir &&
368 git rev-parse HEAD^{tree} >../actual
369 ) &&
370 test_cmp expected actual
371 '
373 test_expect_success 'am newline in subject' '
374 git checkout first &&
375 test_tick &&
376 sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
377 git am <patchnl >output.out 2>&1 &&
378 grep "^Applying: second \\\n foo$" output.out
379 '
381 test_expect_success 'am -q is quiet' '
382 git checkout first &&
383 test_tick &&
384 git am -q <patch1 >output.out 2>&1 &&
385 ! test -s output.out
386 '
388 test_done