]> git.proxmox.com Git - libgit2.git/blob - tests/cherrypick/workdir.c
Merge pull request #2484 from libgit2/fix-git-status-list-new-unreadable-folder
[libgit2.git] / tests / cherrypick / workdir.c
1 #include "clar.h"
2 #include "clar_libgit2.h"
3
4 #include "buffer.h"
5 #include "fileops.h"
6 #include "git2/cherrypick.h"
7
8 #include "../merge/merge_helpers.h"
9
10 #define TEST_REPO_PATH "cherrypick"
11
12 static git_repository *repo;
13 static git_index *repo_index;
14
15 // Fixture setup and teardown
16 void test_cherrypick_workdir__initialize(void)
17 {
18 repo = cl_git_sandbox_init(TEST_REPO_PATH);
19 git_repository_index(&repo_index, repo);
20 }
21
22 void test_cherrypick_workdir__cleanup(void)
23 {
24 git_index_free(repo_index);
25 cl_git_sandbox_cleanup();
26 }
27
28 /* git reset --hard d3d77487660ee3c0194ee01dc5eaf478782b1c7e
29 * git cherry-pick cfc4f0999a8367568e049af4f72e452d40828a15
30 * git cherry-pick 964ea3da044d9083181a88ba6701de9e35778bf4
31 * git cherry-pick a43a050c588d4e92f11a6b139680923e9728477d
32 */
33 void test_cherrypick_workdir__automerge(void)
34 {
35 git_oid head_oid;
36 git_signature *signature = NULL;
37 size_t i;
38
39 const char *cherrypick_oids[] = {
40 "cfc4f0999a8367568e049af4f72e452d40828a15",
41 "964ea3da044d9083181a88ba6701de9e35778bf4",
42 "a43a050c588d4e92f11a6b139680923e9728477d",
43 };
44
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" },
49
50 { 0100644, "38c05a857e831a7e759d83778bfc85d003e21c45", 0, "file1.txt" },
51 { 0100644, "bd8fc3c59fb52d3c8b5907ace7defa5803f82419", 0, "file2.txt" },
52 { 0100644, "df6b290e0bd6a89b01d69f66687e8abf385283ca", 0, "file3.txt" },
53
54 { 0100644, "f06427bee380364bc7e0cb26a9245158e4726ce0", 0, "file1.txt" },
55 { 0100644, "bd8fc3c59fb52d3c8b5907ace7defa5803f82419", 0, "file2.txt" },
56 { 0100644, "df6b290e0bd6a89b01d69f66687e8abf385283ca", 0, "file3.txt" },
57 };
58
59 cl_git_pass(git_signature_new(&signature, "Picker", "picker@example.org", time(NULL), 0));
60
61 git_oid_fromstr(&head_oid, "d3d77487660ee3c0194ee01dc5eaf478782b1c7e");
62
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;
67
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));
70
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));
74
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"));
77
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));
82
83 cl_assert(merge_test_index(repo_index, merge_index_entries + i * 3, 3));
84
85 git_oid_cpy(&head_oid, &cherrypicked_oid);
86
87 git_tree_free(cherrypicked_tree);
88 git_commit_free(head);
89 git_commit_free(commit);
90 }
91
92 git_signature_free(signature);
93 }
94
95 /* git reset --hard bafbf6912c09505ac60575cd43d3f2aba3bd84d8
96 * git cherry-pick e9b63f3655b2ad80c0ff587389b5a9589a3a7110
97 */
98 void test_cherrypick_workdir__conflicts(void)
99 {
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;
103
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" },
112 };
113
114 git_oid_fromstr(&head_oid, "bafbf6912c09505ac60575cd43d3f2aba3bd84d8");
115
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));
118
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));
122
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"));
125
126 cl_assert(merge_test_index(repo_index, merge_index_entries, 7));
127
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" \
132 "\n" \
133 "Conflicts:\n" \
134 "\tfile2.txt\n" \
135 "\tfile3.txt\n") == 0);
136
137 cl_git_pass(git_futils_readbuffer(&conflicting_buf,
138 TEST_REPO_PATH "/file2.txt"));
139
140 cl_assert(strcmp(git_buf_cstr(&conflicting_buf),
141 "!File 2\n" \
142 "File 2\n" \
143 "File 2\n" \
144 "File 2\n" \
145 "File 2\n" \
146 "File 2\n" \
147 "File 2\n" \
148 "File 2\n" \
149 "File 2\n" \
150 "File 2\n" \
151 "File 2!!\n" \
152 "File 2\n" \
153 "File 2\n" \
154 "File 2\n" \
155 "<<<<<<< HEAD\n" \
156 "File 2\n" \
157 "=======\n" \
158 "File 2!\n" \
159 "File 2\n" \
160 "File 2!\n" \
161 ">>>>>>> e9b63f3... Change all files\n") == 0);
162
163 cl_git_pass(git_futils_readbuffer(&conflicting_buf,
164 TEST_REPO_PATH "/file3.txt"));
165
166 cl_assert(strcmp(git_buf_cstr(&conflicting_buf),
167 "!File 3\n" \
168 "File 3\n" \
169 "File 3\n" \
170 "File 3\n" \
171 "File 3\n" \
172 "File 3\n" \
173 "File 3\n" \
174 "File 3\n" \
175 "File 3\n" \
176 "File 3\n" \
177 "File 3\n" \
178 "File 3!!\n" \
179 "File 3\n" \
180 "File 3\n" \
181 "File 3\n" \
182 "<<<<<<< HEAD\n" \
183 "=======\n" \
184 "File 3!\n" \
185 "File 3!\n" \
186 ">>>>>>> e9b63f3... Change all files\n") == 0);
187
188 git_commit_free(commit);
189 git_commit_free(head);
190 git_buf_free(&mergemsg_buf);
191 git_buf_free(&conflicting_buf);
192 }
193
194 /* git reset --hard bafbf6912c09505ac60575cd43d3f2aba3bd84d8
195 * git cherry-pick -X ours e9b63f3655b2ad80c0ff587389b5a9589a3a7110
196 */
197 void test_cherrypick_workdir__conflict_use_ours(void)
198 {
199 git_commit *head = NULL, *commit = NULL;
200 git_oid head_oid, cherry_oid;
201 git_cherrypick_options opts = GIT_CHERRYPICK_OPTIONS_INIT;
202
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" },
211 };
212
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" },
217 };
218
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;
221
222 git_oid_fromstr(&head_oid, "bafbf6912c09505ac60575cd43d3f2aba3bd84d8");
223
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));
226
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));
230
231 cl_assert(merge_test_index(repo_index, merge_index_entries, 7));
232 cl_assert(merge_test_workdir(repo, merge_filesystem_entries, 3));
233
234 /* resolve conflicts in the index by taking "ours" */
235 opts.merge_opts.file_favor = GIT_MERGE_FILE_FAVOR_OURS;
236
237 cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
238 cl_git_pass(git_cherrypick(repo, commit, &opts));
239
240 cl_assert(merge_test_index(repo_index, merge_filesystem_entries, 3));
241 cl_assert(merge_test_workdir(repo, merge_filesystem_entries, 3));
242
243 git_commit_free(commit);
244 git_commit_free(head);
245 }
246
247 /* git reset --hard cfc4f0999a8367568e049af4f72e452d40828a15
248 * git cherry-pick 2a26c7e88b285613b302ba76712bc998863f3cbc
249 */
250 void test_cherrypick_workdir__rename(void)
251 {
252 git_commit *head, *commit;
253 git_oid head_oid, cherry_oid;
254 git_cherrypick_options opts = GIT_CHERRYPICK_OPTIONS_INIT;
255
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" },
260 };
261
262 opts.merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
263 opts.merge_opts.rename_threshold = 50;
264
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));
268
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));
272
273 cl_assert(merge_test_index(repo_index, merge_index_entries, 3));
274
275 git_commit_free(commit);
276 git_commit_free(head);
277 }
278
279 /* git reset --hard 44cd2ed2052c9c68f9a439d208e9614dc2a55c70
280 * git cherry-pick 2a26c7e88b285613b302ba76712bc998863f3cbc
281 */
282 void test_cherrypick_workdir__both_renamed(void)
283 {
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;
288
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" },
295 };
296
297 opts.merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
298 opts.merge_opts.rename_threshold = 50;
299
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));
303
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));
307
308 cl_assert(merge_test_index(repo_index, merge_index_entries, 5));
309
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" \
314 "\n" \
315 "Conflicts:\n" \
316 "\tfile3.txt\n" \
317 "\tfile3.txt.renamed\n" \
318 "\tfile3.txt.renamed_on_branch\n") == 0);
319
320 git_buf_free(&mergemsg_buf);
321 git_commit_free(commit);
322 git_commit_free(head);
323 }
324
325 void test_cherrypick_workdir__nonmerge_fails_mainline_specified(void)
326 {
327 git_reference *head;
328 git_commit *commit;
329 git_cherrypick_options opts = GIT_CHERRYPICK_OPTIONS_INIT;
330
331 cl_git_pass(git_repository_head(&head, repo));
332 cl_git_pass(git_reference_peel((git_object **)&commit, head, GIT_OBJ_COMMIT));
333
334 opts.mainline = 1;
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"));
338
339 git_reference_free(head);
340 git_commit_free(commit);
341 }
342
343 /* git reset --hard cfc4f0999a8367568e049af4f72e452d40828a15
344 * git cherry-pick abe4603bc7cd5b8167a267e0e2418fd2348f8cff
345 */
346 void test_cherrypick_workdir__merge_fails_without_mainline_specified(void)
347 {
348 git_commit *head, *commit;
349 git_oid head_oid, cherry_oid;
350
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));
354
355 git_oid_fromstr(&cherry_oid, "abe4603bc7cd5b8167a267e0e2418fd2348f8cff");
356 cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
357
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"));
361
362 git_commit_free(commit);
363 git_commit_free(head);
364 }
365
366 /* git reset --hard cfc4f0999a8367568e049af4f72e452d40828a15
367 * git cherry-pick -m1 abe4603bc7cd5b8167a267e0e2418fd2348f8cff
368 */
369 void test_cherrypick_workdir__merge_first_parent(void)
370 {
371 git_commit *head, *commit;
372 git_oid head_oid, cherry_oid;
373 git_cherrypick_options opts = GIT_CHERRYPICK_OPTIONS_INIT;
374
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" },
379 };
380
381 opts.mainline = 1;
382
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));
386
387 git_oid_fromstr(&cherry_oid, "abe4603bc7cd5b8167a267e0e2418fd2348f8cff");
388 cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
389
390 cl_git_pass(git_cherrypick(repo, commit, &opts));
391
392 cl_assert(merge_test_index(repo_index, merge_index_entries, 3));
393
394 git_commit_free(commit);
395 git_commit_free(head);
396 }
397
398 /* git reset --hard cfc4f0999a8367568e049af4f72e452d40828a15
399 * git cherry-pick -m2 abe4603bc7cd5b8167a267e0e2418fd2348f8cff
400 */
401 void test_cherrypick_workdir__merge_second_parent(void)
402 {
403 git_commit *head, *commit;
404 git_oid head_oid, cherry_oid;
405 git_cherrypick_options opts = GIT_CHERRYPICK_OPTIONS_INIT;
406
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" },
411 };
412
413 opts.mainline = 2;
414
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));
418
419 git_oid_fromstr(&cherry_oid, "abe4603bc7cd5b8167a267e0e2418fd2348f8cff");
420 cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
421
422 cl_git_pass(git_cherrypick(repo, commit, &opts));
423
424 cl_assert(merge_test_index(repo_index, merge_index_entries, 3));
425
426 git_commit_free(commit);
427 git_commit_free(head);
428 }
429