]> git.proxmox.com Git - libgit2.git/blame - tests/merge/merge_helpers.c
New upstream version 1.4.3+dfsg.1
[libgit2.git] / tests / merge / merge_helpers.c
CommitLineData
bec65a5e 1#include "clar_libgit2.h"
22a2d3d5 2#include "futils.h"
bec65a5e
ET
3#include "refs.h"
4#include "tree.h"
5#include "merge_helpers.h"
6#include "merge.h"
86c8d02c 7#include "index.h"
bec65a5e 8#include "git2/merge.h"
75d1c8c6 9#include "git2/sys/index.h"
18b00406 10#include "git2/annotated_commit.h"
bec65a5e
ET
11
12int merge_trees_from_branches(
13 git_index **index, git_repository *repo,
14 const char *ours_name, const char *theirs_name,
5aa2ac6d 15 git_merge_options *opts)
bec65a5e
ET
16{
17 git_commit *our_commit, *their_commit, *ancestor_commit = NULL;
18 git_tree *our_tree, *their_tree, *ancestor_tree = NULL;
19 git_oid our_oid, their_oid, ancestor_oid;
e579e0f7 20 git_str branch_buf = GIT_STR_INIT;
bec65a5e
ET
21 int error;
22
e579e0f7 23 git_str_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours_name);
bec65a5e
ET
24 cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr));
25 cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid));
26
e579e0f7
MB
27 git_str_clear(&branch_buf);
28 git_str_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs_name);
bec65a5e
ET
29 cl_git_pass(git_reference_name_to_id(&their_oid, repo, branch_buf.ptr));
30 cl_git_pass(git_commit_lookup(&their_commit, repo, &their_oid));
31
32 error = git_merge_base(&ancestor_oid, repo, git_commit_id(our_commit), git_commit_id(their_commit));
33
34 if (error != GIT_ENOTFOUND) {
35 cl_git_pass(error);
36
37 cl_git_pass(git_commit_lookup(&ancestor_commit, repo, &ancestor_oid));
38 cl_git_pass(git_commit_tree(&ancestor_tree, ancestor_commit));
39 }
40
41 cl_git_pass(git_commit_tree(&our_tree, our_commit));
42 cl_git_pass(git_commit_tree(&their_tree, their_commit));
43
8683d31f 44 error = git_merge_trees(index, repo, ancestor_tree, our_tree, their_tree, opts);
bec65a5e 45
e579e0f7 46 git_str_dispose(&branch_buf);
bec65a5e
ET
47 git_tree_free(our_tree);
48 git_tree_free(their_tree);
49 git_tree_free(ancestor_tree);
50 git_commit_free(our_commit);
51 git_commit_free(their_commit);
52 git_commit_free(ancestor_commit);
53
8683d31f 54 return error;
bec65a5e
ET
55}
56
eac938d9
ET
57int merge_commits_from_branches(
58 git_index **index, git_repository *repo,
59 const char *ours_name, const char *theirs_name,
5aa2ac6d 60 git_merge_options *opts)
eac938d9
ET
61{
62 git_commit *our_commit, *their_commit;
63 git_oid our_oid, their_oid;
e579e0f7 64 git_str branch_buf = GIT_STR_INIT;
8683d31f 65 int error;
eac938d9 66
e579e0f7 67 git_str_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours_name);
eac938d9
ET
68 cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr));
69 cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid));
70
e579e0f7
MB
71 git_str_clear(&branch_buf);
72 git_str_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs_name);
eac938d9
ET
73 cl_git_pass(git_reference_name_to_id(&their_oid, repo, branch_buf.ptr));
74 cl_git_pass(git_commit_lookup(&their_commit, repo, &their_oid));
75
8683d31f 76 error = git_merge_commits(index, repo, our_commit, their_commit, opts);
eac938d9 77
e579e0f7 78 git_str_dispose(&branch_buf);
eac938d9
ET
79 git_commit_free(our_commit);
80 git_commit_free(their_commit);
81
8683d31f 82 return error;
eac938d9
ET
83}
84
d9fdee6e 85int merge_branches(git_repository *repo,
02105a27 86 const char *ours_branch, const char *theirs_branch,
5aa2ac6d 87 git_merge_options *merge_opts, git_checkout_options *checkout_opts)
039db728
ET
88{
89 git_reference *head_ref, *theirs_ref;
18b00406 90 git_annotated_commit *theirs_head;
6affd71f 91 git_checkout_options head_checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
039db728
ET
92
93 head_checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
94
659cf202 95 cl_git_pass(git_reference_symbolic_create(&head_ref, repo, "HEAD", ours_branch, 1, NULL));
039db728
ET
96 cl_git_pass(git_checkout_head(repo, &head_checkout_opts));
97
98 cl_git_pass(git_reference_lookup(&theirs_ref, repo, theirs_branch));
18b00406 99 cl_git_pass(git_annotated_commit_from_ref(&theirs_head, repo, theirs_ref));
039db728 100
18b00406 101 cl_git_pass(git_merge(repo, (const git_annotated_commit **)&theirs_head, 1, merge_opts, checkout_opts));
039db728
ET
102
103 git_reference_free(head_ref);
104 git_reference_free(theirs_ref);
18b00406 105 git_annotated_commit_free(theirs_head);
039db728
ET
106
107 return 0;
108}
109
e1807113 110void merge__dump_index_entries(git_vector *index_entries)
0462fba5
ET
111{
112 size_t i;
113 const git_index_entry *index_entry;
1fed6b07 114
768f8be3 115 printf ("\nINDEX [%"PRIuZ"]:\n", index_entries->length);
0462fba5
ET
116 for (i = 0; i < index_entries->length; i++) {
117 index_entry = index_entries->contents[i];
1fed6b07 118
0462fba5 119 printf("%o ", index_entry->mode);
d541170c 120 printf("%s ", git_oid_allocfmt(&index_entry->id));
0462fba5
ET
121 printf("%d ", git_index_entry_stage(index_entry));
122 printf("%s ", index_entry->path);
123 printf("\n");
124 }
125 printf("\n");
126}
127
e1807113 128void merge__dump_names(git_index *index)
0462fba5
ET
129{
130 size_t i;
131 const git_index_name_entry *conflict_name;
132
133 for (i = 0; i < git_index_name_entrycount(index); i++) {
134 conflict_name = git_index_name_get_byindex(index, i);
1fed6b07 135
0462fba5
ET
136 printf("%s %s %s\n", conflict_name->ancestor, conflict_name->ours, conflict_name->theirs);
137 }
138 printf("\n");
139}
140
e1807113 141void merge__dump_reuc(git_index *index)
0462fba5
ET
142{
143 size_t i;
144 const git_index_reuc_entry *reuc;
145
146 printf ("\nREUC:\n");
147 for (i = 0; i < git_index_reuc_entrycount(index); i++) {
148 reuc = git_index_reuc_get_byindex(index, i);
1fed6b07 149
0462fba5
ET
150 printf("%s ", reuc->path);
151 printf("%o ", reuc->mode[0]);
152 printf("%s\n", git_oid_allocfmt(&reuc->oid[0]));
153 printf(" %o ", reuc->mode[1]);
154 printf(" %s\n", git_oid_allocfmt(&reuc->oid[1]));
155 printf(" %o ", reuc->mode[2]);
156 printf(" %s ", git_oid_allocfmt(&reuc->oid[2]));
157 printf("\n");
158 }
159 printf("\n");
160}
161
bec65a5e
ET
162static int index_entry_eq_merge_index_entry(const struct merge_index_entry *expected, const git_index_entry *actual)
163{
164 git_oid expected_oid;
0462fba5 165 bool test_oid;
bec65a5e
ET
166
167 if (strlen(expected->oid_str) != 0) {
168 cl_git_pass(git_oid_fromstr(&expected_oid, expected->oid_str));
169 test_oid = 1;
170 } else
171 test_oid = 0;
1fed6b07 172
bec65a5e 173 if (actual->mode != expected->mode ||
d541170c 174 (test_oid && git_oid_cmp(&actual->id, &expected_oid) != 0) ||
bec65a5e
ET
175 git_index_entry_stage(actual) != expected->stage)
176 return 0;
1fed6b07 177
bec65a5e
ET
178 if (actual->mode == 0 && (actual->path != NULL || strlen(expected->path) > 0))
179 return 0;
180
181 if (actual->mode != 0 && (strcmp(actual->path, expected->path) != 0))
182 return 0;
1fed6b07 183
bec65a5e
ET
184 return 1;
185}
186
187static int name_entry_eq(const char *expected, const char *actual)
188{
189 if (strlen(expected) == 0)
190 return (actual == NULL) ? 1 : 0;
1fed6b07 191
bec65a5e
ET
192 return (strcmp(expected, actual) == 0) ? 1 : 0;
193}
194
0462fba5
ET
195static int name_entry_eq_merge_name_entry(const struct merge_name_entry *expected, const git_index_name_entry *actual)
196{
197 if (name_entry_eq(expected->ancestor_path, actual->ancestor) == 0 ||
198 name_entry_eq(expected->our_path, actual->ours) == 0 ||
199 name_entry_eq(expected->their_path, actual->theirs) == 0)
200 return 0;
201
202 return 1;
203}
204
bec65a5e
ET
205static int index_conflict_data_eq_merge_diff(const struct merge_index_conflict_data *expected, git_merge_diff *actual)
206{
4e7c1560
ET
207 if (!index_entry_eq_merge_index_entry(&expected->ancestor.entry, &actual->ancestor_entry) ||
208 !index_entry_eq_merge_index_entry(&expected->ours.entry, &actual->our_entry) ||
209 !index_entry_eq_merge_index_entry(&expected->theirs.entry, &actual->their_entry))
bec65a5e 210 return 0;
1fed6b07 211
bec65a5e
ET
212 if (expected->ours.status != actual->our_status ||
213 expected->theirs.status != actual->their_status)
214 return 0;
1fed6b07 215
bec65a5e
ET
216 return 1;
217}
218
219int merge_test_merge_conflicts(git_vector *conflicts, const struct merge_index_conflict_data expected[], size_t expected_len)
220{
221 git_merge_diff *actual;
222 size_t i;
1fed6b07 223
bec65a5e
ET
224 if (conflicts->length != expected_len)
225 return 0;
226
227 for (i = 0; i < expected_len; i++) {
228 actual = conflicts->contents[i];
1fed6b07 229
bec65a5e
ET
230 if (!index_conflict_data_eq_merge_diff(&expected[i], actual))
231 return 0;
232 }
233
1fed6b07 234 return 1;
bec65a5e
ET
235}
236
237int merge_test_index(git_index *index, const struct merge_index_entry expected[], size_t expected_len)
238{
1fed6b07 239 size_t i;
240 const git_index_entry *index_entry;
241
bec65a5e 242 /*
86c8d02c 243 merge__dump_index_entries(&index->entries);
bec65a5e
ET
244 */
245
1fed6b07 246 if (git_index_entrycount(index) != expected_len)
247 return 0;
248
249 for (i = 0; i < expected_len; i++) {
250 if ((index_entry = git_index_get_byindex(index, i)) == NULL)
251 return 0;
252
bec65a5e
ET
253 if (!index_entry_eq_merge_index_entry(&expected[i], index_entry))
254 return 0;
1fed6b07 255 }
256
257 return 1;
bec65a5e
ET
258}
259
0462fba5
ET
260int merge_test_names(git_index *index, const struct merge_name_entry expected[], size_t expected_len)
261{
262 size_t i;
263 const git_index_name_entry *name_entry;
1fed6b07 264
0462fba5
ET
265 /*
266 dump_names(index);
267 */
268
269 if (git_index_name_entrycount(index) != expected_len)
270 return 0;
271
272 for (i = 0; i < expected_len; i++) {
273 if ((name_entry = git_index_name_get_byindex(index, i)) == NULL)
274 return 0;
275
276 if (! name_entry_eq_merge_name_entry(&expected[i], name_entry))
277 return 0;
278 }
1fed6b07 279
0462fba5
ET
280 return 1;
281}
282
bec65a5e
ET
283int merge_test_reuc(git_index *index, const struct merge_reuc_entry expected[], size_t expected_len)
284{
1fed6b07 285 size_t i;
bec65a5e 286 const git_index_reuc_entry *reuc_entry;
1fed6b07 287 git_oid expected_oid;
288
bec65a5e
ET
289 /*
290 dump_reuc(index);
291 */
1fed6b07 292
293 if (git_index_reuc_entrycount(index) != expected_len)
294 return 0;
295
296 for (i = 0; i < expected_len; i++) {
297 if ((reuc_entry = git_index_reuc_get_byindex(index, i)) == NULL)
298 return 0;
bec65a5e
ET
299
300 if (strcmp(reuc_entry->path, expected[i].path) != 0 ||
301 reuc_entry->mode[0] != expected[i].ancestor_mode ||
302 reuc_entry->mode[1] != expected[i].our_mode ||
303 reuc_entry->mode[2] != expected[i].their_mode)
304 return 0;
305
306 if (expected[i].ancestor_mode > 0) {
307 cl_git_pass(git_oid_fromstr(&expected_oid, expected[i].ancestor_oid_str));
308
309 if (git_oid_cmp(&reuc_entry->oid[0], &expected_oid) != 0)
310 return 0;
311 }
312
313 if (expected[i].our_mode > 0) {
314 cl_git_pass(git_oid_fromstr(&expected_oid, expected[i].our_oid_str));
315
316 if (git_oid_cmp(&reuc_entry->oid[1], &expected_oid) != 0)
317 return 0;
318 }
319
320 if (expected[i].their_mode > 0) {
321 cl_git_pass(git_oid_fromstr(&expected_oid, expected[i].their_oid_str));
322
323 if (git_oid_cmp(&reuc_entry->oid[2], &expected_oid) != 0)
324 return 0;
325 }
1fed6b07 326 }
327
328 return 1;
bec65a5e
ET
329}
330
e579e0f7 331static int dircount(void *payload, git_str *pathbuf)
bec65a5e 332{
d99e5471 333 size_t *entries = payload;
e579e0f7 334 size_t len = git_str_len(pathbuf);
1fed6b07 335
e579e0f7 336 if (len < 5 || strcmp(pathbuf->ptr + (git_str_len(pathbuf) - 5), "/.git") != 0)
bec65a5e 337 (*entries)++;
1fed6b07 338
bec65a5e
ET
339 return 0;
340}
341
342int merge_test_workdir(git_repository *repo, const struct merge_index_entry expected[], size_t expected_len)
343{
344 size_t actual_len = 0, i;
345 git_oid actual_oid, expected_oid;
e579e0f7 346 git_str wd = GIT_STR_INIT;
1fed6b07 347
e579e0f7
MB
348 git_str_puts(&wd, repo->workdir);
349 git_fs_path_direach(&wd, 0, dircount, &actual_len);
1fed6b07 350
bec65a5e
ET
351 if (actual_len != expected_len)
352 return 0;
1fed6b07 353
bec65a5e 354 for (i = 0; i < expected_len; i++) {
22a2d3d5 355 git_blob_create_from_workdir(&actual_oid, repo, expected[i].path);
bec65a5e 356 git_oid_fromstr(&expected_oid, expected[i].oid_str);
1fed6b07 357
bec65a5e
ET
358 if (git_oid_cmp(&actual_oid, &expected_oid) != 0)
359 return 0;
360 }
1fed6b07 361
e579e0f7 362 git_str_dispose(&wd);
1fed6b07 363
bec65a5e
ET
364 return 1;
365}