2 #include "clar_libgit2.h"
6 #include "git2/cherrypick.h"
8 #include "../merge/merge_helpers.h"
10 #define TEST_REPO_PATH "cherrypick"
12 static git_repository
*repo
;
13 static git_index
*repo_index
;
15 // Fixture setup and teardown
16 void test_cherrypick_workdir__initialize(void)
18 repo
= cl_git_sandbox_init(TEST_REPO_PATH
);
19 git_repository_index(&repo_index
, repo
);
22 void test_cherrypick_workdir__cleanup(void)
24 git_index_free(repo_index
);
25 cl_git_sandbox_cleanup();
28 /* git reset --hard d3d77487660ee3c0194ee01dc5eaf478782b1c7e
29 * git cherry-pick cfc4f0999a8367568e049af4f72e452d40828a15
30 * git cherry-pick 964ea3da044d9083181a88ba6701de9e35778bf4
31 * git cherry-pick a43a050c588d4e92f11a6b139680923e9728477d
33 void test_cherrypick_workdir__automerge(void)
36 git_signature
*signature
= NULL
;
39 const char *cherrypick_oids
[] = {
40 "cfc4f0999a8367568e049af4f72e452d40828a15",
41 "964ea3da044d9083181a88ba6701de9e35778bf4",
42 "a43a050c588d4e92f11a6b139680923e9728477d",
45 struct merge_index_entry merge_index_entries
[] = {
46 { 0100644, "38c05a857e831a7e759d83778bfc85d003e21c45", 0, "file1.txt" },
47 { 0100644, "a661b5dec1004e2c62654ded3762370c27cf266b", 0, "file2.txt" },
48 { 0100644, "df6b290e0bd6a89b01d69f66687e8abf385283ca", 0, "file3.txt" },
50 { 0100644, "38c05a857e831a7e759d83778bfc85d003e21c45", 0, "file1.txt" },
51 { 0100644, "bd8fc3c59fb52d3c8b5907ace7defa5803f82419", 0, "file2.txt" },
52 { 0100644, "df6b290e0bd6a89b01d69f66687e8abf385283ca", 0, "file3.txt" },
54 { 0100644, "f06427bee380364bc7e0cb26a9245158e4726ce0", 0, "file1.txt" },
55 { 0100644, "bd8fc3c59fb52d3c8b5907ace7defa5803f82419", 0, "file2.txt" },
56 { 0100644, "df6b290e0bd6a89b01d69f66687e8abf385283ca", 0, "file3.txt" },
59 cl_git_pass(git_signature_new(&signature
, "Picker", "picker@example.org", time(NULL
), 0));
61 git_oid_fromstr(&head_oid
, "d3d77487660ee3c0194ee01dc5eaf478782b1c7e");
63 for (i
= 0; i
< 3; ++i
) {
64 git_commit
*head
= NULL
, *commit
= NULL
;
65 git_oid cherry_oid
, cherrypicked_oid
, cherrypicked_tree_oid
;
66 git_tree
*cherrypicked_tree
= NULL
;
68 cl_git_pass(git_commit_lookup(&head
, repo
, &head_oid
));
69 cl_git_pass(git_reset(repo
, (git_object
*)head
, GIT_RESET_HARD
, NULL
, NULL
));
71 git_oid_fromstr(&cherry_oid
, cherrypick_oids
[i
]);
72 cl_git_pass(git_commit_lookup(&commit
, repo
, &cherry_oid
));
73 cl_git_pass(git_cherrypick(repo
, commit
, NULL
));
75 cl_assert(git_path_exists(TEST_REPO_PATH
"/.git/CHERRY_PICK_HEAD"));
76 cl_assert(git_path_exists(TEST_REPO_PATH
"/.git/MERGE_MSG"));
78 cl_git_pass(git_index_write_tree(&cherrypicked_tree_oid
, repo_index
));
79 cl_git_pass(git_tree_lookup(&cherrypicked_tree
, repo
, &cherrypicked_tree_oid
));
80 cl_git_pass(git_commit_create(&cherrypicked_oid
, repo
, "HEAD", signature
, signature
, NULL
,
81 "Cherry picked!", cherrypicked_tree
, 1, (const git_commit
**)&head
));
83 cl_assert(merge_test_index(repo_index
, merge_index_entries
+ i
* 3, 3));
85 git_oid_cpy(&head_oid
, &cherrypicked_oid
);
87 git_tree_free(cherrypicked_tree
);
88 git_commit_free(head
);
89 git_commit_free(commit
);
92 git_signature_free(signature
);
95 /* git reset --hard bafbf6912c09505ac60575cd43d3f2aba3bd84d8
96 * git cherry-pick e9b63f3655b2ad80c0ff587389b5a9589a3a7110
98 void test_cherrypick_workdir__conflicts(void)
100 git_commit
*head
= NULL
, *commit
= NULL
;
101 git_oid head_oid
, cherry_oid
;
102 git_buf conflicting_buf
= GIT_BUF_INIT
, mergemsg_buf
= GIT_BUF_INIT
;
104 struct merge_index_entry merge_index_entries
[] = {
105 { 0100644, "242e7977ba73637822ffb265b46004b9b0e5153b", 0, "file1.txt" },
106 { 0100644, "a58ca3fee5eb68b11adc2703e5843f968c9dad1e", 1, "file2.txt" },
107 { 0100644, "bd6ffc8c6c41f0f85ff9e3d61c9479516bac0024", 2, "file2.txt" },
108 { 0100644, "563f6473a3858f99b80e5f93c660512ed38e1e6f", 3, "file2.txt" },
109 { 0100644, "28d9eb4208074ad1cc84e71ccc908b34573f05d2", 1, "file3.txt" },
110 { 0100644, "1124c2c1ae07b26fded662d6c3f3631d9dc16f88", 2, "file3.txt" },
111 { 0100644, "e233b9ed408a95e9d4b65fec7fc34943a556deb2", 3, "file3.txt" },
114 git_oid_fromstr(&head_oid
, "bafbf6912c09505ac60575cd43d3f2aba3bd84d8");
116 cl_git_pass(git_commit_lookup(&head
, repo
, &head_oid
));
117 cl_git_pass(git_reset(repo
, (git_object
*)head
, GIT_RESET_HARD
, NULL
, NULL
));
119 git_oid_fromstr(&cherry_oid
, "e9b63f3655b2ad80c0ff587389b5a9589a3a7110");
120 cl_git_pass(git_commit_lookup(&commit
, repo
, &cherry_oid
));
121 cl_git_pass(git_cherrypick(repo
, commit
, NULL
));
123 cl_assert(git_path_exists(TEST_REPO_PATH
"/.git/CHERRY_PICK_HEAD"));
124 cl_assert(git_path_exists(TEST_REPO_PATH
"/.git/MERGE_MSG"));
126 cl_assert(merge_test_index(repo_index
, merge_index_entries
, 7));
128 cl_git_pass(git_futils_readbuffer(&mergemsg_buf
,
129 TEST_REPO_PATH
"/.git/MERGE_MSG"));
130 cl_assert(strcmp(git_buf_cstr(&mergemsg_buf
),
131 "Change all files\n" \
135 "\tfile3.txt\n") == 0);
137 cl_git_pass(git_futils_readbuffer(&conflicting_buf
,
138 TEST_REPO_PATH
"/file2.txt"));
140 cl_assert(strcmp(git_buf_cstr(&conflicting_buf
),
161 ">>>>>>> e9b63f3... Change all files\n") == 0);
163 cl_git_pass(git_futils_readbuffer(&conflicting_buf
,
164 TEST_REPO_PATH
"/file3.txt"));
166 cl_assert(strcmp(git_buf_cstr(&conflicting_buf
),
186 ">>>>>>> e9b63f3... Change all files\n") == 0);
188 git_commit_free(commit
);
189 git_commit_free(head
);
190 git_buf_free(&mergemsg_buf
);
191 git_buf_free(&conflicting_buf
);
194 /* git reset --hard bafbf6912c09505ac60575cd43d3f2aba3bd84d8
195 * git cherry-pick -X ours e9b63f3655b2ad80c0ff587389b5a9589a3a7110
197 void test_cherrypick_workdir__conflict_use_ours(void)
199 git_commit
*head
= NULL
, *commit
= NULL
;
200 git_oid head_oid
, cherry_oid
;
201 git_cherrypick_options opts
= GIT_CHERRYPICK_OPTIONS_INIT
;
203 struct merge_index_entry merge_index_entries
[] = {
204 { 0100644, "242e7977ba73637822ffb265b46004b9b0e5153b", 0, "file1.txt" },
205 { 0100644, "a58ca3fee5eb68b11adc2703e5843f968c9dad1e", 1, "file2.txt" },
206 { 0100644, "bd6ffc8c6c41f0f85ff9e3d61c9479516bac0024", 2, "file2.txt" },
207 { 0100644, "563f6473a3858f99b80e5f93c660512ed38e1e6f", 3, "file2.txt" },
208 { 0100644, "28d9eb4208074ad1cc84e71ccc908b34573f05d2", 1, "file3.txt" },
209 { 0100644, "1124c2c1ae07b26fded662d6c3f3631d9dc16f88", 2, "file3.txt" },
210 { 0100644, "e233b9ed408a95e9d4b65fec7fc34943a556deb2", 3, "file3.txt" },
213 struct merge_index_entry merge_filesystem_entries
[] = {
214 { 0100644, "242e7977ba73637822ffb265b46004b9b0e5153b", 0, "file1.txt" },
215 { 0100644, "bd6ffc8c6c41f0f85ff9e3d61c9479516bac0024", 0, "file2.txt" },
216 { 0100644, "1124c2c1ae07b26fded662d6c3f3631d9dc16f88", 0, "file3.txt" },
219 /* leave the index in a conflicted state, but checkout "ours" to the workdir */
220 opts
.checkout_opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
| GIT_CHECKOUT_USE_OURS
;
222 git_oid_fromstr(&head_oid
, "bafbf6912c09505ac60575cd43d3f2aba3bd84d8");
224 cl_git_pass(git_commit_lookup(&head
, repo
, &head_oid
));
225 cl_git_pass(git_reset(repo
, (git_object
*)head
, GIT_RESET_HARD
, NULL
, NULL
));
227 git_oid_fromstr(&cherry_oid
, "e9b63f3655b2ad80c0ff587389b5a9589a3a7110");
228 cl_git_pass(git_commit_lookup(&commit
, repo
, &cherry_oid
));
229 cl_git_pass(git_cherrypick(repo
, commit
, &opts
));
231 cl_assert(merge_test_index(repo_index
, merge_index_entries
, 7));
232 cl_assert(merge_test_workdir(repo
, merge_filesystem_entries
, 3));
234 /* resolve conflicts in the index by taking "ours" */
235 opts
.merge_opts
.file_favor
= GIT_MERGE_FILE_FAVOR_OURS
;
237 cl_git_pass(git_reset(repo
, (git_object
*)head
, GIT_RESET_HARD
, NULL
, NULL
));
238 cl_git_pass(git_cherrypick(repo
, commit
, &opts
));
240 cl_assert(merge_test_index(repo_index
, merge_filesystem_entries
, 3));
241 cl_assert(merge_test_workdir(repo
, merge_filesystem_entries
, 3));
243 git_commit_free(commit
);
244 git_commit_free(head
);
247 /* git reset --hard cfc4f0999a8367568e049af4f72e452d40828a15
248 * git cherry-pick 2a26c7e88b285613b302ba76712bc998863f3cbc
250 void test_cherrypick_workdir__rename(void)
252 git_commit
*head
, *commit
;
253 git_oid head_oid
, cherry_oid
;
254 git_cherrypick_options opts
= GIT_CHERRYPICK_OPTIONS_INIT
;
256 struct merge_index_entry merge_index_entries
[] = {
257 { 0100644, "19c5c7207054604b69c84d08a7571ef9672bb5c2", 0, "file1.txt" },
258 { 0100644, "a58ca3fee5eb68b11adc2703e5843f968c9dad1e", 0, "file2.txt" },
259 { 0100644, "28d9eb4208074ad1cc84e71ccc908b34573f05d2", 0, "file3.txt.renamed" },
262 opts
.merge_opts
.flags
|= GIT_MERGE_TREE_FIND_RENAMES
;
263 opts
.merge_opts
.rename_threshold
= 50;
265 git_oid_fromstr(&head_oid
, "cfc4f0999a8367568e049af4f72e452d40828a15");
266 cl_git_pass(git_commit_lookup(&head
, repo
, &head_oid
));
267 cl_git_pass(git_reset(repo
, (git_object
*)head
, GIT_RESET_HARD
, NULL
, NULL
));
269 git_oid_fromstr(&cherry_oid
, "2a26c7e88b285613b302ba76712bc998863f3cbc");
270 cl_git_pass(git_commit_lookup(&commit
, repo
, &cherry_oid
));
271 cl_git_pass(git_cherrypick(repo
, commit
, &opts
));
273 cl_assert(merge_test_index(repo_index
, merge_index_entries
, 3));
275 git_commit_free(commit
);
276 git_commit_free(head
);
279 /* git reset --hard 44cd2ed2052c9c68f9a439d208e9614dc2a55c70
280 * git cherry-pick 2a26c7e88b285613b302ba76712bc998863f3cbc
282 void test_cherrypick_workdir__both_renamed(void)
284 git_commit
*head
, *commit
;
285 git_oid head_oid
, cherry_oid
;
286 git_buf mergemsg_buf
= GIT_BUF_INIT
;
287 git_cherrypick_options opts
= GIT_CHERRYPICK_OPTIONS_INIT
;
289 struct merge_index_entry merge_index_entries
[] = {
290 { 0100644, "19c5c7207054604b69c84d08a7571ef9672bb5c2", 0, "file1.txt" },
291 { 0100644, "a58ca3fee5eb68b11adc2703e5843f968c9dad1e", 0, "file2.txt" },
292 { 0100644, "e233b9ed408a95e9d4b65fec7fc34943a556deb2", 1, "file3.txt" },
293 { 0100644, "e233b9ed408a95e9d4b65fec7fc34943a556deb2", 3, "file3.txt.renamed" },
294 { 0100644, "28d9eb4208074ad1cc84e71ccc908b34573f05d2", 2, "file3.txt.renamed_on_branch" },
297 opts
.merge_opts
.flags
|= GIT_MERGE_TREE_FIND_RENAMES
;
298 opts
.merge_opts
.rename_threshold
= 50;
300 git_oid_fromstr(&head_oid
, "44cd2ed2052c9c68f9a439d208e9614dc2a55c70");
301 cl_git_pass(git_commit_lookup(&head
, repo
, &head_oid
));
302 cl_git_pass(git_reset(repo
, (git_object
*)head
, GIT_RESET_HARD
, NULL
, NULL
));
304 git_oid_fromstr(&cherry_oid
, "2a26c7e88b285613b302ba76712bc998863f3cbc");
305 cl_git_pass(git_commit_lookup(&commit
, repo
, &cherry_oid
));
306 cl_git_pass(git_cherrypick(repo
, commit
, &opts
));
308 cl_assert(merge_test_index(repo_index
, merge_index_entries
, 5));
310 cl_git_pass(git_futils_readbuffer(&mergemsg_buf
,
311 TEST_REPO_PATH
"/.git/MERGE_MSG"));
312 cl_assert(strcmp(git_buf_cstr(&mergemsg_buf
),
313 "Renamed file3.txt -> file3.txt.renamed\n" \
317 "\tfile3.txt.renamed\n" \
318 "\tfile3.txt.renamed_on_branch\n") == 0);
320 git_buf_free(&mergemsg_buf
);
321 git_commit_free(commit
);
322 git_commit_free(head
);
325 void test_cherrypick_workdir__nonmerge_fails_mainline_specified(void)
329 git_cherrypick_options opts
= GIT_CHERRYPICK_OPTIONS_INIT
;
331 cl_git_pass(git_repository_head(&head
, repo
));
332 cl_git_pass(git_reference_peel((git_object
**)&commit
, head
, GIT_OBJ_COMMIT
));
335 cl_must_fail(git_cherrypick(repo
, commit
, &opts
));
336 cl_assert(!git_path_exists(TEST_REPO_PATH
"/.git/CHERRY_PICK_HEAD"));
337 cl_assert(!git_path_exists(TEST_REPO_PATH
"/.git/MERGE_MSG"));
339 git_reference_free(head
);
340 git_commit_free(commit
);
343 /* git reset --hard cfc4f0999a8367568e049af4f72e452d40828a15
344 * git cherry-pick abe4603bc7cd5b8167a267e0e2418fd2348f8cff
346 void test_cherrypick_workdir__merge_fails_without_mainline_specified(void)
348 git_commit
*head
, *commit
;
349 git_oid head_oid
, cherry_oid
;
351 git_oid_fromstr(&head_oid
, "cfc4f0999a8367568e049af4f72e452d40828a15");
352 cl_git_pass(git_commit_lookup(&head
, repo
, &head_oid
));
353 cl_git_pass(git_reset(repo
, (git_object
*)head
, GIT_RESET_HARD
, NULL
, NULL
));
355 git_oid_fromstr(&cherry_oid
, "abe4603bc7cd5b8167a267e0e2418fd2348f8cff");
356 cl_git_pass(git_commit_lookup(&commit
, repo
, &cherry_oid
));
358 cl_must_fail(git_cherrypick(repo
, commit
, NULL
));
359 cl_assert(!git_path_exists(TEST_REPO_PATH
"/.git/CHERRY_PICK_HEAD"));
360 cl_assert(!git_path_exists(TEST_REPO_PATH
"/.git/MERGE_MSG"));
362 git_commit_free(commit
);
363 git_commit_free(head
);
366 /* git reset --hard cfc4f0999a8367568e049af4f72e452d40828a15
367 * git cherry-pick -m1 abe4603bc7cd5b8167a267e0e2418fd2348f8cff
369 void test_cherrypick_workdir__merge_first_parent(void)
371 git_commit
*head
, *commit
;
372 git_oid head_oid
, cherry_oid
;
373 git_cherrypick_options opts
= GIT_CHERRYPICK_OPTIONS_INIT
;
375 struct merge_index_entry merge_index_entries
[] = {
376 { 0100644, "f90f9dcbdac2cce5cc166346160e19cb693ef4e8", 0, "file1.txt" },
377 { 0100644, "563f6473a3858f99b80e5f93c660512ed38e1e6f", 0, "file2.txt" },
378 { 0100644, "e233b9ed408a95e9d4b65fec7fc34943a556deb2", 0, "file3.txt" },
383 git_oid_fromstr(&head_oid
, "cfc4f0999a8367568e049af4f72e452d40828a15");
384 cl_git_pass(git_commit_lookup(&head
, repo
, &head_oid
));
385 cl_git_pass(git_reset(repo
, (git_object
*)head
, GIT_RESET_HARD
, NULL
, NULL
));
387 git_oid_fromstr(&cherry_oid
, "abe4603bc7cd5b8167a267e0e2418fd2348f8cff");
388 cl_git_pass(git_commit_lookup(&commit
, repo
, &cherry_oid
));
390 cl_git_pass(git_cherrypick(repo
, commit
, &opts
));
392 cl_assert(merge_test_index(repo_index
, merge_index_entries
, 3));
394 git_commit_free(commit
);
395 git_commit_free(head
);
398 /* git reset --hard cfc4f0999a8367568e049af4f72e452d40828a15
399 * git cherry-pick -m2 abe4603bc7cd5b8167a267e0e2418fd2348f8cff
401 void test_cherrypick_workdir__merge_second_parent(void)
403 git_commit
*head
, *commit
;
404 git_oid head_oid
, cherry_oid
;
405 git_cherrypick_options opts
= GIT_CHERRYPICK_OPTIONS_INIT
;
407 struct merge_index_entry merge_index_entries
[] = {
408 { 0100644, "487434cace79238a7091e2220611d4f20a765690", 0, "file1.txt" },
409 { 0100644, "e5183bfd18e3a0a691fadde2f0d5610b73282d31", 0, "file2.txt" },
410 { 0100644, "409a1bec58bf35348e8b62b72bb9c1f45cf5a587", 0, "file3.txt" },
415 git_oid_fromstr(&head_oid
, "cfc4f0999a8367568e049af4f72e452d40828a15");
416 cl_git_pass(git_commit_lookup(&head
, repo
, &head_oid
));
417 cl_git_pass(git_reset(repo
, (git_object
*)head
, GIT_RESET_HARD
, NULL
, NULL
));
419 git_oid_fromstr(&cherry_oid
, "abe4603bc7cd5b8167a267e0e2418fd2348f8cff");
420 cl_git_pass(git_commit_lookup(&commit
, repo
, &cherry_oid
));
422 cl_git_pass(git_cherrypick(repo
, commit
, &opts
));
424 cl_assert(merge_test_index(repo_index
, merge_index_entries
, 3));
426 git_commit_free(commit
);
427 git_commit_free(head
);