Merge branch 'nd/parse-options-aliases'
[git] / t / t3511-cherry-pick-x.sh
1 #!/bin/sh
2
3 test_description='Test cherry-pick -x and -s'
4
5 . ./test-lib.sh
6
7 pristine_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
14 mesg_one_line='base: commit message'
15
16 mesg_no_footer="$mesg_one_line
17
18 OneWordBodyThatsNotA-S-o-B"
19
20 mesg_with_footer="$mesg_no_footer
21
22 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
23 Signed-off-by: A.U. Thor <author@example.com>
24 Signed-off-by: B.U. Thor <buthor@example.com>"
25
26 mesg_broken_footer="$mesg_no_footer
27
28 This is not recognized as a footer because Myfooter is not a recognized token.
29 Myfooter: A.U. Thor <author@example.com>"
30
31 mesg_with_footer_sob="$mesg_with_footer
32 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
33
34 mesg_with_cherry_footer="$mesg_with_footer_sob
35 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
36 Tested-by: C.U. Thor <cuthor@example.com>"
37
38 mesg_unclean="$mesg_one_line
39
40
41 leading empty lines
42
43
44 consecutive empty lines
45
46 # hash tag comment
47
48 trailing empty lines
49
50
51 "
52
53 test_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
77 test_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
90 test_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
102 test_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
114 test_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
125 test_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
138 test_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
150 test_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
164 test_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
175 test_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
188 test_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
198 test_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
211 test_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
222 test_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
233 test_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
244 test_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
255 test_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
267 test_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
278 test_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
291 test_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
301 test_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
311 test_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
321 test_done