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