1#!/bin/sh
2
3test_description='Test cherry-pick -x and -s'
4
5. ./test-lib.sh
6
7pristine_detach () {
8 git cherry-pick --quit &&
9 git checkout -f "$1^0" &&
10 git read-tree -u --reset HEAD &&
11 git clean -d -f -f -q -x
12}
13
14mesg_one_line='base: commit message'
15
16mesg_no_footer="$mesg_one_line
17
18OneWordBodyThatsNotA-S-o-B"
19
20mesg_with_footer="$mesg_no_footer
21
22Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
23Signed-off-by: A.U. Thor <author@example.com>
24Signed-off-by: B.U. Thor <buthor@example.com>"
25
26mesg_broken_footer="$mesg_no_footer
27
28This is not recognized as a footer because Myfooter is not a recognized token.
29Myfooter: A.U. Thor <author@example.com>"
30
31mesg_with_footer_sob="$mesg_with_footer
32Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
33
34mesg_with_cherry_footer="$mesg_with_footer_sob
35(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
36Tested-by: C.U. Thor <cuthor@example.com>"
37
38mesg_unclean="$mesg_one_line
39
40
41leading empty lines
42
43
44consecutive empty lines
45
46# hash tag comment
47
48trailing empty lines
49
50
51"
52
53test_expect_success setup '
54 git config advice.detachedhead false &&
55 echo unrelated >unrelated &&
56 git add unrelated &&
57 test_commit initial foo a &&
58 test_commit "$mesg_one_line" foo b mesg-one-line &&
59 git reset --hard initial &&
60 test_commit "$mesg_no_footer" foo b mesg-no-footer &&
61 git reset --hard initial &&
62 test_commit "$mesg_broken_footer" foo b mesg-broken-footer &&
63 git reset --hard initial &&
64 test_commit "$mesg_with_footer" foo b mesg-with-footer &&
65 git reset --hard initial &&
66 test_commit "$mesg_with_footer_sob" foo b mesg-with-footer-sob &&
67 git reset --hard initial &&
68 test_commit "$mesg_with_cherry_footer" foo b mesg-with-cherry-footer &&
69 git reset --hard initial &&
70 test_config commit.cleanup verbatim &&
71 test_commit "$mesg_unclean" foo b mesg-unclean &&
72 test_unconfig commit.cleanup &&
73 pristine_detach initial &&
74 test_commit conflicting unrelated
75'
76
77test_expect_success 'cherry-pick -x inserts blank line after one line subject' '
78 pristine_detach initial &&
79 sha1=$(git rev-parse mesg-one-line^0) &&
80 git cherry-pick -x mesg-one-line &&
81 cat <<-EOF >expect &&
82 $mesg_one_line
83
84 (cherry picked from commit $sha1)
85 EOF
86 git log -1 --pretty=format:%B >actual &&
87 test_cmp expect actual
88'
89
90test_expect_success 'cherry-pick -s inserts blank line after one line subject' '
91 pristine_detach initial &&
92 git cherry-pick -s mesg-one-line &&
93 cat <<-EOF >expect &&
94 $mesg_one_line
95
96 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
97 EOF
98 git log -1 --pretty=format:%B >actual &&
99 test_cmp expect actual
100'
101
102test_expect_success 'cherry-pick -s inserts blank line after non-conforming footer' '
103 pristine_detach initial &&
104 git cherry-pick -s mesg-broken-footer &&
105 cat <<-EOF >expect &&
106 $mesg_broken_footer
107
108 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
109 EOF
110 git log -1 --pretty=format:%B >actual &&
111 test_cmp expect actual
112'
113
114test_expect_success 'cherry-pick -s recognizes trailer config' '
115 pristine_detach initial &&
116 git -c "trailer.Myfooter.ifexists=add" cherry-pick -s mesg-broken-footer &&
117 cat <<-EOF >expect &&
118 $mesg_broken_footer
119 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
120 EOF
121 git log -1 --pretty=format:%B >actual &&
122 test_cmp expect actual
123'
124
125test_expect_success 'cherry-pick -x inserts blank line when conforming footer not found' '
126 pristine_detach initial &&
127 sha1=$(git rev-parse mesg-no-footer^0) &&
128 git cherry-pick -x mesg-no-footer &&
129 cat <<-EOF >expect &&
130 $mesg_no_footer
131
132 (cherry picked from commit $sha1)
133 EOF
134 git log -1 --pretty=format:%B >actual &&
135 test_cmp expect actual
136'
137
138test_expect_success 'cherry-pick -s inserts blank line when conforming footer not found' '
139 pristine_detach initial &&
140 git cherry-pick -s mesg-no-footer &&
141 cat <<-EOF >expect &&
142 $mesg_no_footer
143
144 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
145 EOF
146 git log -1 --pretty=format:%B >actual &&
147 test_cmp expect actual
148'
149
150test_expect_success 'cherry-pick -x -s inserts blank line when conforming footer not found' '
151 pristine_detach initial &&
152 sha1=$(git rev-parse mesg-no-footer^0) &&
153 git cherry-pick -x -s mesg-no-footer &&
154 cat <<-EOF >expect &&
155 $mesg_no_footer
156
157 (cherry picked from commit $sha1)
158 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
159 EOF
160 git log -1 --pretty=format:%B >actual &&
161 test_cmp expect actual
162'
163
164test_expect_success 'cherry-pick -s adds sob when last sob doesnt match committer' '
165 pristine_detach initial &&
166 git cherry-pick -s mesg-with-footer &&
167 cat <<-EOF >expect &&
168 $mesg_with_footer
169 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
170 EOF
171 git log -1 --pretty=format:%B >actual &&
172 test_cmp expect actual
173'
174
175test_expect_success 'cherry-pick -x -s adds sob when last sob doesnt match committer' '
176 pristine_detach initial &&
177 sha1=$(git rev-parse mesg-with-footer^0) &&
178 git cherry-pick -x -s mesg-with-footer &&
179 cat <<-EOF >expect &&
180 $mesg_with_footer
181 (cherry picked from commit $sha1)
182 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
183 EOF
184 git log -1 --pretty=format:%B >actual &&
185 test_cmp expect actual
186'
187
188test_expect_success 'cherry-pick -s refrains from adding duplicate trailing sob' '
189 pristine_detach initial &&
190 git cherry-pick -s mesg-with-footer-sob &&
191 cat <<-EOF >expect &&
192 $mesg_with_footer_sob
193 EOF
194 git log -1 --pretty=format:%B >actual &&
195 test_cmp expect actual
196'
197
198test_expect_success 'cherry-pick -x -s adds sob even when trailing sob exists for committer' '
199 pristine_detach initial &&
200 sha1=$(git rev-parse mesg-with-footer-sob^0) &&
201 git cherry-pick -x -s mesg-with-footer-sob &&
202 cat <<-EOF >expect &&
203 $mesg_with_footer_sob
204 (cherry picked from commit $sha1)
205 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
206 EOF
207 git log -1 --pretty=format:%B >actual &&
208 test_cmp expect actual
209'
210
211test_expect_success 'cherry-pick -x handles commits with no NL at end of message' '
212 pristine_detach initial &&
213 printf "title\n\nSigned-off-by: A <a@example.com>" >msg &&
214 sha1=$(git commit-tree -p initial mesg-with-footer^{tree} <msg) &&
215 git cherry-pick -x $sha1 &&
216 git log -1 --pretty=format:%B >actual &&
217
218 printf "\n(cherry picked from commit %s)\n" $sha1 >>msg &&
219 test_cmp msg actual
220'
221
222test_expect_success 'cherry-pick -x handles commits with no footer and no NL at end of message' '
223 pristine_detach initial &&
224 printf "title\n\nnot a footer" >msg &&
225 sha1=$(git commit-tree -p initial mesg-with-footer^{tree} <msg) &&
226 git cherry-pick -x $sha1 &&
227 git log -1 --pretty=format:%B >actual &&
228
229 printf "\n\n(cherry picked from commit %s)\n" $sha1 >>msg &&
230 test_cmp msg actual
231'
232
233test_expect_success 'cherry-pick -s handles commits with no NL at end of message' '
234 pristine_detach initial &&
235 printf "title\n\nSigned-off-by: A <a@example.com>" >msg &&
236 sha1=$(git commit-tree -p initial mesg-with-footer^{tree} <msg) &&
237 git cherry-pick -s $sha1 &&
238 git log -1 --pretty=format:%B >actual &&
239
240 printf "\nSigned-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\n" >>msg &&
241 test_cmp msg actual
242'
243
244test_expect_success 'cherry-pick -s handles commits with no footer and no NL at end of message' '
245 pristine_detach initial &&
246 printf "title\n\nnot a footer" >msg &&
247 sha1=$(git commit-tree -p initial mesg-with-footer^{tree} <msg) &&
248 git cherry-pick -s $sha1 &&
249 git log -1 --pretty=format:%B >actual &&
250
251 printf "\n\nSigned-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\n" >>msg &&
252 test_cmp msg actual
253'
254
255test_expect_success 'cherry-pick -x treats "(cherry picked from..." line as part of footer' '
256 pristine_detach initial &&
257 sha1=$(git rev-parse mesg-with-cherry-footer^0) &&
258 git cherry-pick -x mesg-with-cherry-footer &&
259 cat <<-EOF >expect &&
260 $mesg_with_cherry_footer
261 (cherry picked from commit $sha1)
262 EOF
263 git log -1 --pretty=format:%B >actual &&
264 test_cmp expect actual
265'
266
267test_expect_success 'cherry-pick -s treats "(cherry picked from..." line as part of footer' '
268 pristine_detach initial &&
269 git cherry-pick -s mesg-with-cherry-footer &&
270 cat <<-EOF >expect &&
271 $mesg_with_cherry_footer
272 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
273 EOF
274 git log -1 --pretty=format:%B >actual &&
275 test_cmp expect actual
276'
277
278test_expect_success 'cherry-pick -x -s treats "(cherry picked from..." line as part of footer' '
279 pristine_detach initial &&
280 sha1=$(git rev-parse mesg-with-cherry-footer^0) &&
281 git cherry-pick -x -s mesg-with-cherry-footer &&
282 cat <<-EOF >expect &&
283 $mesg_with_cherry_footer
284 (cherry picked from commit $sha1)
285 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
286 EOF
287 git log -1 --pretty=format:%B >actual &&
288 test_cmp expect actual
289'
290
291test_expect_success 'cherry-pick preserves commit message' '
292 pristine_detach initial &&
293 printf "$mesg_unclean" >expect &&
294 git log -1 --pretty=format:%B mesg-unclean >actual &&
295 test_cmp expect actual &&
296 git cherry-pick mesg-unclean &&
297 git log -1 --pretty=format:%B >actual &&
298 test_cmp expect actual
299'
300
301test_expect_success 'cherry-pick -x cleans commit message' '
302 pristine_detach initial &&
303 git cherry-pick -x mesg-unclean &&
304 git log -1 --pretty=format:%B >actual &&
305 printf "%s\n(cherry picked from commit %s)\n" \
306 "$mesg_unclean" $(git rev-parse mesg-unclean) |
307 git stripspace >expect &&
308 test_cmp expect actual
309'
310
311test_expect_success 'cherry-pick -x respects commit.cleanup' '
312 pristine_detach initial &&
313 git -c commit.cleanup=strip cherry-pick -x mesg-unclean &&
314 git log -1 --pretty=format:%B >actual &&
315 printf "%s\n(cherry picked from commit %s)\n" \
316 "$mesg_unclean" $(git rev-parse mesg-unclean) |
317 git stripspace -s >expect &&
318 test_cmp expect actual
319'
320
321test_done