File Coverage

deps/libgit2/src/merge.c
Criterion Covered Total %
statement 1024 1623 63.0
branch 582 1306 44.5
condition n/a
subroutine n/a
pod n/a
total 1606 2929 54.8


line stmt bran cond sub pod time code
1             /*
2             * Copyright (C) the libgit2 contributors. All rights reserved.
3             *
4             * This file is part of libgit2, distributed under the GNU GPL v2 with
5             * a Linking Exception. For full terms see the included COPYING file.
6             */
7              
8             #include "merge.h"
9              
10             #include "posix.h"
11             #include "buffer.h"
12             #include "repository.h"
13             #include "revwalk.h"
14             #include "commit_list.h"
15             #include "path.h"
16             #include "refs.h"
17             #include "object.h"
18             #include "iterator.h"
19             #include "refs.h"
20             #include "diff.h"
21             #include "diff_generate.h"
22             #include "diff_tform.h"
23             #include "checkout.h"
24             #include "tree.h"
25             #include "blob.h"
26             #include "oid.h"
27             #include "index.h"
28             #include "filebuf.h"
29             #include "config.h"
30             #include "oidarray.h"
31             #include "annotated_commit.h"
32             #include "commit.h"
33             #include "oidarray.h"
34             #include "merge_driver.h"
35             #include "oidmap.h"
36             #include "array.h"
37              
38             #include "git2/types.h"
39             #include "git2/repository.h"
40             #include "git2/object.h"
41             #include "git2/commit.h"
42             #include "git2/merge.h"
43             #include "git2/refs.h"
44             #include "git2/reset.h"
45             #include "git2/checkout.h"
46             #include "git2/signature.h"
47             #include "git2/config.h"
48             #include "git2/tree.h"
49             #include "git2/oidarray.h"
50             #include "git2/annotated_commit.h"
51             #include "git2/sys/index.h"
52             #include "git2/sys/hashsig.h"
53              
54             #define GIT_MERGE_INDEX_ENTRY_EXISTS(X) ((X).mode != 0)
55             #define GIT_MERGE_INDEX_ENTRY_ISFILE(X) S_ISREG((X).mode)
56              
57              
58             typedef enum {
59             TREE_IDX_ANCESTOR = 0,
60             TREE_IDX_OURS = 1,
61             TREE_IDX_THEIRS = 2
62             } merge_tree_index_t;
63              
64             /* Tracks D/F conflicts */
65             struct merge_diff_df_data {
66             const char *df_path;
67             const char *prev_path;
68             git_merge_diff *prev_conflict;
69             };
70              
71             /*
72             * This acts as a negative cache entry marker. In case we've tried to calculate
73             * similarity metrics for a given blob already but `git_hashsig` determined
74             * that it's too small in order to have a meaningful hash signature, we will
75             * insert the address of this marker instead of `NULL`. Like this, we can
76             * easily check whether we have checked a gien entry already and skip doing the
77             * calculation again and again.
78             */
79             static int cache_invalid_marker;
80              
81             /* Merge base computation */
82              
83 19           int merge_bases_many(git_commit_list **out, git_revwalk **walk_out, git_repository *repo, size_t length, const git_oid input_array[])
84             {
85 19           git_revwalk *walk = NULL;
86             git_vector list;
87 19           git_commit_list *result = NULL;
88             git_commit_list_node *commit;
89 19           int error = -1;
90             unsigned int i;
91              
92 19 50         if (length < 2) {
93 0           git_error_set(GIT_ERROR_INVALID, "at least two commits are required to find an ancestor");
94 0           return -1;
95             }
96              
97 19 50         if (git_vector_init(&list, length - 1, NULL) < 0)
98 0           return -1;
99              
100 19 50         if (git_revwalk_new(&walk, repo) < 0)
101 0           goto on_error;
102              
103 38 100         for (i = 1; i < length; i++) {
104 19           commit = git_revwalk__commit_lookup(walk, &input_array[i]);
105 19 50         if (commit == NULL)
106 0           goto on_error;
107              
108 19           git_vector_insert(&list, commit);
109             }
110              
111 19           commit = git_revwalk__commit_lookup(walk, &input_array[0]);
112 19 50         if (commit == NULL)
113 0           goto on_error;
114              
115 19 50         if (git_merge__bases_many(&result, walk, commit, &list) < 0)
116 0           goto on_error;
117              
118 19 50         if (!result) {
119 0           git_error_set(GIT_ERROR_MERGE, "no merge base found");
120 0           error = GIT_ENOTFOUND;
121 0           goto on_error;
122             }
123              
124 19           *out = result;
125 19           *walk_out = walk;
126              
127 19           git_vector_free(&list);
128 19           return 0;
129              
130             on_error:
131 0           git_vector_free(&list);
132 0           git_revwalk_free(walk);
133 19           return error;
134             }
135              
136 13           int git_merge_base_many(git_oid *out, git_repository *repo, size_t length, const git_oid input_array[])
137             {
138             git_revwalk *walk;
139 13           git_commit_list *result = NULL;
140 13           int error = 0;
141              
142 13 50         assert(out && repo && input_array);
    50          
    50          
143              
144 13 50         if ((error = merge_bases_many(&result, &walk, repo, length, input_array)) < 0)
145 0           return error;
146              
147 13           git_oid_cpy(out, &result->item->oid);
148              
149 13           git_commit_list_free(&result);
150 13           git_revwalk_free(walk);
151              
152 13           return 0;
153             }
154              
155 6           int git_merge_bases_many(git_oidarray *out, git_repository *repo, size_t length, const git_oid input_array[])
156             {
157             git_revwalk *walk;
158 6           git_commit_list *list, *result = NULL;
159 6           int error = 0;
160             git_array_oid_t array;
161              
162 6 50         assert(out && repo && input_array);
    50          
    50          
163              
164 6 50         if ((error = merge_bases_many(&result, &walk, repo, length, input_array)) < 0)
165 0           return error;
166              
167 6           git_array_init(array);
168              
169 6           list = result;
170 12 100         while (list) {
171 6 50         git_oid *id = git_array_alloc(array);
    0          
172 6 50         if (id == NULL) {
173 0           error = -1;
174 0           goto cleanup;
175             }
176              
177 6           git_oid_cpy(id, &list->item->oid);
178 6           list = list->next;
179             }
180              
181 6           git_oidarray__from_array(out, &array);
182              
183             cleanup:
184 6           git_commit_list_free(&result);
185 6           git_revwalk_free(walk);
186              
187 6           return error;
188             }
189              
190 0           int git_merge_base_octopus(git_oid *out, git_repository *repo, size_t length, const git_oid input_array[])
191             {
192             git_oid result;
193             unsigned int i;
194 0           int error = -1;
195              
196 0 0         assert(out && repo && input_array);
    0          
    0          
197              
198 0 0         if (length < 2) {
199 0           git_error_set(GIT_ERROR_INVALID, "at least two commits are required to find an ancestor");
200 0           return -1;
201             }
202              
203 0           result = input_array[0];
204 0 0         for (i = 1; i < length; i++) {
205 0           error = git_merge_base(&result, repo, &result, &input_array[i]);
206 0 0         if (error < 0)
207 0           return error;
208             }
209              
210 0           *out = result;
211              
212 0           return 0;
213             }
214              
215 20           static int merge_bases(git_commit_list **out, git_revwalk **walk_out, git_repository *repo, const git_oid *one, const git_oid *two)
216             {
217             git_revwalk *walk;
218             git_vector list;
219 20           git_commit_list *result = NULL;
220             git_commit_list_node *commit;
221             void *contents[1];
222              
223 20 50         if (git_revwalk_new(&walk, repo) < 0)
224 0           return -1;
225              
226 20           commit = git_revwalk__commit_lookup(walk, two);
227 20 50         if (commit == NULL)
228 0           goto on_error;
229              
230             /* This is just one value, so we can do it on the stack */
231 20           memset(&list, 0x0, sizeof(git_vector));
232 20           contents[0] = commit;
233 20           list.length = 1;
234 20           list.contents = contents;
235              
236 20           commit = git_revwalk__commit_lookup(walk, one);
237 20 50         if (commit == NULL)
238 0           goto on_error;
239              
240 20 50         if (git_merge__bases_many(&result, walk, commit, &list) < 0)
241 0           goto on_error;
242              
243 20 50         if (!result) {
244 0           git_revwalk_free(walk);
245 0           git_error_set(GIT_ERROR_MERGE, "no merge base found");
246 0           return GIT_ENOTFOUND;
247             }
248              
249 20           *out = result;
250 20           *walk_out = walk;
251              
252 20           return 0;
253              
254             on_error:
255 0           git_revwalk_free(walk);
256 20           return -1;
257              
258             }
259              
260 20           int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const git_oid *two)
261             {
262             int error;
263             git_revwalk *walk;
264             git_commit_list *result;
265              
266 20 50         if ((error = merge_bases(&result, &walk, repo, one, two)) < 0)
267 0           return error;
268              
269 20           git_oid_cpy(out, &result->item->oid);
270 20           git_commit_list_free(&result);
271 20           git_revwalk_free(walk);
272              
273 20           return 0;
274             }
275              
276 0           int git_merge_bases(git_oidarray *out, git_repository *repo, const git_oid *one, const git_oid *two)
277             {
278             int error;
279             git_revwalk *walk;
280             git_commit_list *result, *list;
281             git_array_oid_t array;
282              
283 0           git_array_init(array);
284              
285 0 0         if ((error = merge_bases(&result, &walk, repo, one, two)) < 0)
286 0           return error;
287              
288 0           list = result;
289 0 0         while (list) {
290 0 0         git_oid *id = git_array_alloc(array);
    0          
291 0 0         if (id == NULL)
292 0           goto on_error;
293              
294 0           git_oid_cpy(id, &list->item->oid);
295 0           list = list->next;
296             }
297              
298 0           git_oidarray__from_array(out, &array);
299 0           git_commit_list_free(&result);
300 0           git_revwalk_free(walk);
301              
302 0           return 0;
303              
304             on_error:
305 0           git_commit_list_free(&result);
306 0           git_revwalk_free(walk);
307 0           return -1;
308             }
309              
310 194           static int interesting(git_pqueue *list)
311             {
312             size_t i;
313              
314 203 100         for (i = 0; i < git_pqueue_size(list); i++) {
315 164           git_commit_list_node *commit = git_pqueue_get(list, i);
316 164 100         if ((commit->flags & STALE) == 0)
317 155           return 1;
318             }
319              
320 39           return 0;
321             }
322              
323 0           static int clear_commit_marks_1(git_commit_list **plist,
324             git_commit_list_node *commit, unsigned int mark)
325             {
326 0 0         while (commit) {
327             unsigned int i;
328              
329 0 0         if (!(mark & commit->flags))
330 0           return 0;
331              
332 0           commit->flags &= ~mark;
333              
334 0 0         for (i = 1; i < commit->out_degree; i++) {
335 0           git_commit_list_node *p = commit->parents[i];
336 0 0         if (git_commit_list_insert(p, plist) == NULL)
337 0           return -1;
338             }
339              
340 0 0         commit = commit->out_degree ? commit->parents[0] : NULL;
341             }
342              
343 0           return 0;
344             }
345              
346 0           static int clear_commit_marks_many(git_vector *commits, unsigned int mark)
347             {
348 0           git_commit_list *list = NULL;
349             git_commit_list_node *c;
350             unsigned int i;
351              
352 0 0         git_vector_foreach(commits, i, c) {
353 0 0         if (git_commit_list_insert(c, &list) == NULL)
354 0           return -1;
355             }
356              
357 0 0         while (list)
358 0 0         if (clear_commit_marks_1(&list, git_commit_list_pop(&list), mark) < 0)
359 0           return -1;
360 0           return 0;
361             }
362              
363 0           static int clear_commit_marks(git_commit_list_node *commit, unsigned int mark)
364             {
365 0           git_commit_list *list = NULL;
366 0 0         if (git_commit_list_insert(commit, &list) == NULL)
367 0           return -1;
368 0 0         while (list)
369 0 0         if (clear_commit_marks_1(&list, git_commit_list_pop(&list), mark) < 0)
370 0           return -1;
371 0           return 0;
372             }
373              
374 39           static int paint_down_to_common(
375             git_commit_list **out, git_revwalk *walk, git_commit_list_node *one, git_vector *twos)
376             {
377             git_pqueue list;
378 39           git_commit_list *result = NULL;
379             git_commit_list_node *two;
380              
381             int error;
382             unsigned int i;
383              
384 39 50         if (git_pqueue_init(&list, 0, twos->length * 2, git_commit_list_time_cmp) < 0)
385 0           return -1;
386              
387 39           one->flags |= PARENT1;
388 39 50         if (git_pqueue_insert(&list, one) < 0)
389 0           return -1;
390              
391 78 100         git_vector_foreach(twos, i, two) {
392 39 50         if (git_commit_list_parse(walk, two) < 0)
393 0           return -1;
394              
395 39           two->flags |= PARENT2;
396              
397 39 50         if (git_pqueue_insert(&list, two) < 0)
398 0           return -1;
399             }
400              
401             /* as long as there are non-STALE commits */
402 194 100         while (interesting(&list)) {
403 155           git_commit_list_node *commit = git_pqueue_pop(&list);
404             int flags;
405              
406 155 50         if (commit == NULL)
407 0           break;
408              
409 155           flags = commit->flags & (PARENT1 | PARENT2 | STALE);
410 155 100         if (flags == (PARENT1 | PARENT2)) {
411 66 100         if (!(commit->flags & RESULT)) {
412 39           commit->flags |= RESULT;
413 39 50         if (git_commit_list_insert(commit, &result) == NULL)
414 0           return -1;
415             }
416             /* we mark the parents of a merge stale */
417 66           flags |= STALE;
418             }
419              
420 252 100         for (i = 0; i < commit->out_degree; i++) {
421 97           git_commit_list_node *p = commit->parents[i];
422 97 100         if ((p->flags & flags) == flags)
423 16           continue;
424              
425 81 50         if ((error = git_commit_list_parse(walk, p)) < 0)
426 0           return error;
427              
428 81           p->flags |= flags;
429 81 50         if (git_pqueue_insert(&list, p) < 0)
430 0           return -1;
431             }
432             }
433              
434 39           git_pqueue_free(&list);
435 39           *out = result;
436 39           return 0;
437             }
438              
439 0           static int remove_redundant(git_revwalk *walk, git_vector *commits)
440             {
441 0           git_vector work = GIT_VECTOR_INIT;
442             unsigned char *redundant;
443             unsigned int *filled_index;
444             unsigned int i, j;
445 0           int error = 0;
446              
447 0           redundant = git__calloc(commits->length, 1);
448 0 0         GIT_ERROR_CHECK_ALLOC(redundant);
449 0           filled_index = git__calloc((commits->length - 1), sizeof(unsigned int));
450 0 0         GIT_ERROR_CHECK_ALLOC(filled_index);
451              
452 0 0         for (i = 0; i < commits->length; ++i) {
453 0 0         if ((error = git_commit_list_parse(walk, commits->contents[i])) < 0)
454 0           goto done;
455             }
456              
457 0 0         for (i = 0; i < commits->length; ++i) {
458 0           git_commit_list *common = NULL;
459 0           git_commit_list_node *commit = commits->contents[i];
460              
461 0 0         if (redundant[i])
462 0           continue;
463              
464 0           git_vector_clear(&work);
465              
466 0 0         for (j = 0; j < commits->length; j++) {
467 0 0         if (i == j || redundant[j])
    0          
468 0           continue;
469              
470 0           filled_index[work.length] = j;
471 0 0         if ((error = git_vector_insert(&work, commits->contents[j])) < 0)
472 0           goto done;
473             }
474              
475 0           error = paint_down_to_common(&common, walk, commit, &work);
476 0 0         if (error < 0)
477 0           goto done;
478              
479 0 0         if (commit->flags & PARENT2)
480 0           redundant[i] = 1;
481              
482 0 0         for (j = 0; j < work.length; j++) {
483 0           git_commit_list_node *w = work.contents[j];
484 0 0         if (w->flags & PARENT1)
485 0           redundant[filled_index[j]] = 1;
486             }
487              
488 0           git_commit_list_free(&common);
489              
490 0 0         if ((error = clear_commit_marks(commit, ALL_FLAGS)) < 0 ||
    0          
491             (error = clear_commit_marks_many(&work, ALL_FLAGS)) < 0)
492             goto done;
493             }
494              
495 0 0         for (i = 0; i < commits->length; ++i) {
496 0 0         if (redundant[i])
497 0           commits->contents[i] = NULL;
498             }
499              
500             done:
501 0           git__free(redundant);
502 0           git__free(filled_index);
503 0           git_vector_free(&work);
504 0           return error;
505             }
506              
507 39           int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_list_node *one, git_vector *twos)
508             {
509             int error;
510             unsigned int i;
511             git_commit_list_node *two;
512 39           git_commit_list *result = NULL, *tmp = NULL;
513              
514             /* If there's only the one commit, there can be no merge bases */
515 39 50         if (twos->length == 0) {
516 0           *out = NULL;
517 0           return 0;
518             }
519              
520             /* if the commit is repeated, we have a our merge base already */
521 78 100         git_vector_foreach(twos, i, two) {
522 39 50         if (one == two)
523 0 0         return git_commit_list_insert(one, out) ? 0 : -1;
524             }
525              
526 39 50         if (git_commit_list_parse(walk, one) < 0)
527 0           return -1;
528              
529 39           error = paint_down_to_common(&result, walk, one, twos);
530 39 50         if (error < 0)
531 0           return error;
532              
533             /* filter out any stale commits in the results */
534 39           tmp = result;
535 39           result = NULL;
536              
537 78 100         while (tmp) {
538 39           git_commit_list_node *c = git_commit_list_pop(&tmp);
539 39 50         if (!(c->flags & STALE))
540 39 50         if (git_commit_list_insert_by_date(c, &result) == NULL)
541 0           return -1;
542             }
543              
544             /*
545             * more than one merge base -- see if there are redundant merge
546             * bases and remove them
547             */
548 39 50         if (result && result->next) {
    50          
549 0           git_vector redundant = GIT_VECTOR_INIT;
550              
551 0 0         while (result)
552 0           git_vector_insert(&redundant, git_commit_list_pop(&result));
553              
554 0 0         if ((error = clear_commit_marks(one, ALL_FLAGS)) < 0 ||
    0          
555 0 0         (error = clear_commit_marks_many(twos, ALL_FLAGS)) < 0 ||
556             (error = remove_redundant(walk, &redundant)) < 0) {
557 0           git_vector_free(&redundant);
558 0           return error;
559             }
560              
561 0 0         git_vector_foreach(&redundant, i, two) {
562 0 0         if (two != NULL)
563 0           git_commit_list_insert_by_date(two, &result);
564             }
565              
566 0           git_vector_free(&redundant);
567             }
568              
569 39           *out = result;
570 39           return 0;
571             }
572              
573 0           int git_repository_mergehead_foreach(
574             git_repository *repo,
575             git_repository_mergehead_foreach_cb cb,
576             void *payload)
577             {
578 0           git_buf merge_head_path = GIT_BUF_INIT, merge_head_file = GIT_BUF_INIT;
579             char *buffer, *line;
580 0           size_t line_num = 1;
581             git_oid oid;
582 0           int error = 0;
583              
584 0 0         assert(repo && cb);
    0          
585              
586 0 0         if ((error = git_buf_joinpath(&merge_head_path, repo->gitdir,
587             GIT_MERGE_HEAD_FILE)) < 0)
588 0           return error;
589              
590 0 0         if ((error = git_futils_readbuffer(&merge_head_file,
591             git_buf_cstr(&merge_head_path))) < 0)
592 0           goto cleanup;
593              
594 0           buffer = merge_head_file.ptr;
595              
596 0 0         while ((line = git__strsep(&buffer, "\n")) != NULL) {
597 0 0         if (strlen(line) != GIT_OID_HEXSZ) {
598 0           git_error_set(GIT_ERROR_INVALID, "unable to parse OID - invalid length");
599 0           error = -1;
600 0           goto cleanup;
601             }
602              
603 0 0         if ((error = git_oid_fromstr(&oid, line)) < 0)
604 0           goto cleanup;
605              
606 0 0         if ((error = cb(&oid, payload)) != 0) {
607 0           git_error_set_after_callback(error);
608 0           goto cleanup;
609             }
610              
611 0           ++line_num;
612             }
613              
614 0 0         if (*buffer) {
615 0           git_error_set(GIT_ERROR_MERGE, "no EOL at line %"PRIuZ, line_num);
616 0           error = -1;
617 0           goto cleanup;
618             }
619              
620             cleanup:
621 0           git_buf_dispose(&merge_head_path);
622 0           git_buf_dispose(&merge_head_file);
623              
624 0           return error;
625             }
626              
627 89           GIT_INLINE(int) index_entry_cmp(const git_index_entry *a, const git_index_entry *b)
628             {
629 89           int value = 0;
630              
631 89 100         if (a->path == NULL)
632 1           return (b->path == NULL) ? 0 : 1;
633              
634 88 50         if ((value = a->mode - b->mode) == 0 &&
    100          
635 88           (value = git_oid__cmp(&a->id, &b->id)) == 0)
636 64           value = strcmp(a->path, b->path);
637              
638 88           return value;
639             }
640              
641             /* Conflict resolution */
642              
643 22           static int merge_conflict_resolve_trivial(
644             int *resolved,
645             git_merge_diff_list *diff_list,
646             const git_merge_diff *conflict)
647             {
648             int ours_empty, theirs_empty;
649             int ours_changed, theirs_changed, ours_theirs_differ;
650 22           git_index_entry const *result = NULL;
651 22           int error = 0;
652              
653 22 50         assert(resolved && diff_list && conflict);
    50          
    50          
654              
655 22           *resolved = 0;
656              
657 22 50         if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE ||
    50          
658 22           conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
659 0           return 0;
660              
661 22 50         if (conflict->our_status == GIT_DELTA_RENAMED ||
    50          
662 22           conflict->their_status == GIT_DELTA_RENAMED)
663 0           return 0;
664              
665 22           ours_empty = !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry);
666 22           theirs_empty = !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry);
667              
668 22           ours_changed = (conflict->our_status != GIT_DELTA_UNMODIFIED);
669 22           theirs_changed = (conflict->their_status != GIT_DELTA_UNMODIFIED);
670 30 100         ours_theirs_differ = ours_changed && theirs_changed &&
671 8           index_entry_cmp(&conflict->our_entry, &conflict->their_entry);
672              
673             /*
674             * Note: with only one ancestor, some cases are not distinct:
675             *
676             * 16: ancest:anc1/anc2, head:anc1, remote:anc2 = result:no merge
677             * 3: ancest:(empty)^, head:head, remote:(empty) = result:no merge
678             * 2: ancest:(empty)^, head:(empty), remote:remote = result:no merge
679             *
680             * Note that the two cases that take D/F conflicts into account
681             * specifically do not need to be explicitly tested, as D/F conflicts
682             * would fail the *empty* test:
683             *
684             * 3ALT: ancest:(empty)+, head:head, remote:*empty* = result:head
685             * 2ALT: ancest:(empty)+, head:*empty*, remote:remote = result:remote
686             *
687             * Note that many of these cases need not be explicitly tested, as
688             * they simply degrade to "all different" cases (eg, 11):
689             *
690             * 4: ancest:(empty)^, head:head, remote:remote = result:no merge
691             * 7: ancest:ancest+, head:(empty), remote:remote = result:no merge
692             * 9: ancest:ancest+, head:head, remote:(empty) = result:no merge
693             * 11: ancest:ancest+, head:head, remote:remote = result:no merge
694             */
695              
696             /* 5ALT: ancest:*, head:head, remote:head = result:head */
697 22 100         if (ours_changed && !ours_empty && !ours_theirs_differ)
    100          
    100          
698 1           result = &conflict->our_entry;
699             /* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */
700 21 100         else if (ours_changed && ours_empty && theirs_empty)
    100          
    50          
701 0           *resolved = 0;
702             /* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */
703 21 100         else if (ours_empty && !theirs_changed)
    50          
704 0           *resolved = 0;
705             /* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */
706 21 100         else if (!ours_changed && theirs_empty)
    50          
707 0           *resolved = 0;
708             /* 13: ancest:ancest+, head:head, remote:ancest = result:head */
709 21 100         else if (ours_changed && !theirs_changed)
    50          
710 0           result = &conflict->our_entry;
711             /* 14: ancest:ancest+, head:ancest, remote:remote = result:remote */
712 21 100         else if (!ours_changed && theirs_changed)
    50          
713 14           result = &conflict->their_entry;
714             else
715 7           *resolved = 0;
716              
717 22 100         if (result != NULL &&
    50          
718 15 50         GIT_MERGE_INDEX_ENTRY_EXISTS(*result) &&
719 15           (error = git_vector_insert(&diff_list->staged, (void *)result)) >= 0)
720 15           *resolved = 1;
721              
722             /* Note: trivial resolution does not update the REUC. */
723              
724 22           return error;
725             }
726              
727 7           static int merge_conflict_resolve_one_removed(
728             int *resolved,
729             git_merge_diff_list *diff_list,
730             const git_merge_diff *conflict)
731             {
732             int ours_empty, theirs_empty;
733             int ours_changed, theirs_changed;
734 7           int error = 0;
735              
736 7 50         assert(resolved && diff_list && conflict);
    50          
    50          
737              
738 7           *resolved = 0;
739              
740 7 50         if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE ||
    50          
741 7           conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
742 0           return 0;
743              
744 7           ours_empty = !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry);
745 7           theirs_empty = !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry);
746              
747 7           ours_changed = (conflict->our_status != GIT_DELTA_UNMODIFIED);
748 7           theirs_changed = (conflict->their_status != GIT_DELTA_UNMODIFIED);
749              
750             /* Removed in both */
751 7 50         if (ours_changed && ours_empty && theirs_empty)
    100          
    50          
752 0           *resolved = 1;
753             /* Removed in ours */
754 7 100         else if (ours_empty && !theirs_changed)
    50          
755 0           *resolved = 1;
756             /* Removed in theirs */
757 7 50         else if (!ours_changed && theirs_empty)
    0          
758 0           *resolved = 1;
759              
760 7 50         if (*resolved)
761 0           git_vector_insert(&diff_list->resolved, (git_merge_diff *)conflict);
762              
763 7           return error;
764             }
765              
766 7           static int merge_conflict_resolve_one_renamed(
767             int *resolved,
768             git_merge_diff_list *diff_list,
769             const git_merge_diff *conflict)
770             {
771             int ours_renamed, theirs_renamed;
772             int ours_changed, theirs_changed;
773             git_index_entry *merged;
774 7           int error = 0;
775              
776 7 50         assert(resolved && diff_list && conflict);
    50          
    50          
777              
778 7           *resolved = 0;
779              
780 7 100         if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ||
    50          
781 6           !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry))
782 1           return 0;
783              
784 6           ours_renamed = (conflict->our_status == GIT_DELTA_RENAMED);
785 6           theirs_renamed = (conflict->their_status == GIT_DELTA_RENAMED);
786              
787 6 50         if (!ours_renamed && !theirs_renamed)
    50          
788 6           return 0;
789              
790             /* Reject one file in a 2->1 conflict */
791 0 0         if (conflict->type == GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1 ||
    0          
792 0 0         conflict->type == GIT_MERGE_DIFF_BOTH_RENAMED_1_TO_2 ||
793 0           conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
794 0           return 0;
795              
796 0           ours_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->our_entry.id) != 0);
797 0           theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->their_entry.id) != 0);
798              
799             /* if both are modified (and not to a common target) require a merge */
800 0 0         if (ours_changed && theirs_changed &&
801 0           git_oid__cmp(&conflict->our_entry.id, &conflict->their_entry.id) != 0)
802 0           return 0;
803              
804 0 0         if ((merged = git_pool_malloc(&diff_list->pool, sizeof(git_index_entry))) == NULL)
805 0           return -1;
806              
807 0 0         if (ours_changed)
808 0           memcpy(merged, &conflict->our_entry, sizeof(git_index_entry));
809             else
810 0           memcpy(merged, &conflict->their_entry, sizeof(git_index_entry));
811              
812 0 0         if (ours_renamed)
813 0           merged->path = conflict->our_entry.path;
814             else
815 0           merged->path = conflict->their_entry.path;
816              
817 0           *resolved = 1;
818              
819 0           git_vector_insert(&diff_list->staged, merged);
820 0           git_vector_insert(&diff_list->resolved, (git_merge_diff *)conflict);
821              
822 0           return error;
823             }
824              
825 7           static bool merge_conflict_can_resolve_contents(
826             const git_merge_diff *conflict)
827             {
828 7 100         if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ||
    50          
829 6           !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry))
830 1           return false;
831              
832             /* Reject D/F conflicts */
833 6 50         if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE)
834 0           return false;
835              
836             /* Reject submodules. */
837 6 50         if (S_ISGITLINK(conflict->ancestor_entry.mode) ||
    50          
838 6 50         S_ISGITLINK(conflict->our_entry.mode) ||
839 6           S_ISGITLINK(conflict->their_entry.mode))
840 0           return false;
841              
842             /* Reject link/file conflicts. */
843 6 50         if ((S_ISLNK(conflict->ancestor_entry.mode) ^
844 6 50         S_ISLNK(conflict->our_entry.mode)) ||
845 6           (S_ISLNK(conflict->ancestor_entry.mode) ^
846 6           S_ISLNK(conflict->their_entry.mode)))
847 0           return false;
848              
849             /* Reject name conflicts */
850 6 50         if (conflict->type == GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1 ||
    50          
851 6           conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
852 0           return false;
853              
854 6 50         if ((conflict->our_status & GIT_DELTA_RENAMED) == GIT_DELTA_RENAMED &&
    0          
855 0 0         (conflict->their_status & GIT_DELTA_RENAMED) == GIT_DELTA_RENAMED &&
856 0           strcmp(conflict->ancestor_entry.path, conflict->their_entry.path) != 0)
857 0           return false;
858              
859 6           return true;
860             }
861              
862 6           static int merge_conflict_invoke_driver(
863             git_index_entry **out,
864             const char *name,
865             git_merge_driver *driver,
866             git_merge_diff_list *diff_list,
867             git_merge_driver_source *src)
868             {
869             git_index_entry *result;
870 6           git_buf buf = GIT_BUF_INIT;
871             const char *path;
872             uint32_t mode;
873 6           git_odb *odb = NULL;
874             git_oid oid;
875             int error;
876              
877 6           *out = NULL;
878              
879 6 100         if ((error = driver->apply(driver, &path, &mode, &buf, name, src)) < 0 ||
    50          
880 2 50         (error = git_repository_odb(&odb, src->repo)) < 0 ||
881 2           (error = git_odb_write(&oid, odb, buf.ptr, buf.size, GIT_OBJECT_BLOB)) < 0)
882             goto done;
883              
884 2           result = git_pool_mallocz(&diff_list->pool, sizeof(git_index_entry));
885 2 50         GIT_ERROR_CHECK_ALLOC(result);
886              
887 2           git_oid_cpy(&result->id, &oid);
888 2           result->mode = mode;
889 2           result->file_size = (uint32_t)buf.size;
890              
891 2           result->path = git_pool_strdup(&diff_list->pool, path);
892 2 50         GIT_ERROR_CHECK_ALLOC(result->path);
893              
894 2           *out = result;
895              
896             done:
897 6           git_buf_dispose(&buf);
898 6           git_odb_free(odb);
899              
900 6           return error;
901             }
902              
903 7           static int merge_conflict_resolve_contents(
904             int *resolved,
905             git_merge_diff_list *diff_list,
906             const git_merge_diff *conflict,
907             const git_merge_options *merge_opts,
908             const git_merge_file_options *file_opts)
909             {
910 7           git_merge_driver_source source = {0};
911 7           git_merge_file_result result = {0};
912             git_merge_driver *driver;
913 7           git_merge_driver__builtin builtin = {{0}};
914             git_index_entry *merge_result;
915 7           git_odb *odb = NULL;
916             const char *name;
917 7           bool fallback = false;
918             int error;
919              
920 7 50         assert(resolved && diff_list && conflict);
    50          
    50          
921              
922 7           *resolved = 0;
923              
924 7 100         if (!merge_conflict_can_resolve_contents(conflict))
925 1           return 0;
926              
927 6           source.repo = diff_list->repo;
928 6           source.default_driver = merge_opts->default_driver;
929 6           source.file_opts = file_opts;
930 12           source.ancestor = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
931 6 50         &conflict->ancestor_entry : NULL;
932 12           source.ours = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
933 6 50         &conflict->our_entry : NULL;
934 12           source.theirs = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
935 6 50         &conflict->their_entry : NULL;
936              
937 6 100         if (file_opts->favor != GIT_MERGE_FILE_FAVOR_NORMAL) {
938             /* if the user requested a particular type of resolution (via the
939             * favor flag) then let that override the gitattributes and use
940             * the builtin driver.
941             */
942 2           name = "text";
943 2           builtin.base.apply = git_merge_driver__builtin_apply;
944 2           builtin.favor = file_opts->favor;
945              
946 2           driver = &builtin.base;
947             } else {
948             /* find the merge driver for this file */
949 4 50         if ((error = git_merge_driver_for_source(&name, &driver, &source)) < 0)
950 0           goto done;
951              
952 4 50         if (driver == NULL)
953 0           fallback = true;
954             }
955              
956 6 50         if (driver) {
957 6           error = merge_conflict_invoke_driver(&merge_result, name, driver,
958             diff_list, &source);
959              
960 6 50         if (error == GIT_PASSTHROUGH)
961 0           fallback = true;
962             }
963              
964 6 50         if (fallback) {
965 0           error = merge_conflict_invoke_driver(&merge_result, "text",
966             &git_merge_driver__text.base, diff_list, &source);
967             }
968              
969 6 100         if (error < 0) {
970 4 50         if (error == GIT_EMERGECONFLICT)
971 4           error = 0;
972              
973 4           goto done;
974             }
975              
976 2           git_vector_insert(&diff_list->staged, merge_result);
977 2           git_vector_insert(&diff_list->resolved, (git_merge_diff *)conflict);
978              
979 2           *resolved = 1;
980              
981             done:
982 6           git_merge_file_result_free(&result);
983 6           git_odb_free(odb);
984              
985 7           return error;
986             }
987              
988 22           static int merge_conflict_resolve(
989             int *out,
990             git_merge_diff_list *diff_list,
991             const git_merge_diff *conflict,
992             const git_merge_options *merge_opts,
993             const git_merge_file_options *file_opts)
994             {
995 22           int resolved = 0;
996 22           int error = 0;
997              
998 22           *out = 0;
999              
1000 22 50         if ((error = merge_conflict_resolve_trivial(
1001             &resolved, diff_list, conflict)) < 0)
1002 0           goto done;
1003              
1004 22 100         if (!resolved && (error = merge_conflict_resolve_one_removed(
    50          
1005             &resolved, diff_list, conflict)) < 0)
1006 0           goto done;
1007              
1008 22 100         if (!resolved && (error = merge_conflict_resolve_one_renamed(
    50          
1009             &resolved, diff_list, conflict)) < 0)
1010 0           goto done;
1011              
1012 22 100         if (!resolved && (error = merge_conflict_resolve_contents(
    50          
1013             &resolved, diff_list, conflict, merge_opts, file_opts)) < 0)
1014 0           goto done;
1015              
1016 22           *out = resolved;
1017              
1018             done:
1019 22           return error;
1020             }
1021              
1022             /* Rename detection and coalescing */
1023              
1024             struct merge_diff_similarity {
1025             unsigned char similarity;
1026             size_t other_idx;
1027             };
1028              
1029 0           static int index_entry_similarity_calc(
1030             void **out,
1031             git_repository *repo,
1032             git_index_entry *entry,
1033             const git_merge_options *opts)
1034             {
1035             git_blob *blob;
1036 0           git_diff_file diff_file = {{{0}}};
1037             git_object_size_t blobsize;
1038             int error;
1039              
1040 0 0         if (*out || *out == &cache_invalid_marker)
    0          
1041 0           return 0;
1042              
1043 0           *out = NULL;
1044              
1045 0 0         if ((error = git_blob_lookup(&blob, repo, &entry->id)) < 0)
1046 0           return error;
1047              
1048 0           git_oid_cpy(&diff_file.id, &entry->id);
1049 0           diff_file.path = entry->path;
1050 0           diff_file.size = entry->file_size;
1051 0           diff_file.mode = entry->mode;
1052 0           diff_file.flags = 0;
1053              
1054 0           blobsize = git_blob_rawsize(blob);
1055              
1056             /* file too big for rename processing */
1057 0 0         if (!git__is_sizet(blobsize))
1058 0           return 0;
1059              
1060 0           error = opts->metric->buffer_signature(out, &diff_file,
1061 0           git_blob_rawcontent(blob), (size_t)blobsize,
1062 0           opts->metric->payload);
1063 0 0         if (error == GIT_EBUFS)
1064 0           *out = &cache_invalid_marker;
1065              
1066 0           git_blob_free(blob);
1067              
1068 0           return error;
1069             }
1070              
1071 0           static int index_entry_similarity_inexact(
1072             git_repository *repo,
1073             git_index_entry *a,
1074             size_t a_idx,
1075             git_index_entry *b,
1076             size_t b_idx,
1077             void **cache,
1078             const git_merge_options *opts)
1079             {
1080 0           int score = 0;
1081 0           int error = 0;
1082              
1083 0 0         if (!GIT_MODE_ISBLOB(a->mode) || !GIT_MODE_ISBLOB(b->mode))
    0          
1084 0           return 0;
1085              
1086             /* update signature cache if needed */
1087 0 0         if ((error = index_entry_similarity_calc(&cache[a_idx], repo, a, opts)) < 0 ||
    0          
1088 0           (error = index_entry_similarity_calc(&cache[b_idx], repo, b, opts)) < 0)
1089 0           return error;
1090              
1091             /* some metrics may not wish to process this file (too big / too small) */
1092 0 0         if (cache[a_idx] == &cache_invalid_marker || cache[b_idx] == &cache_invalid_marker)
    0          
1093 0           return 0;
1094              
1095             /* compare signatures */
1096 0 0         if (opts->metric->similarity(&score, cache[a_idx], cache[b_idx], opts->metric->payload) < 0)
1097 0           return -1;
1098              
1099             /* clip score */
1100 0 0         if (score < 0)
1101 0           score = 0;
1102 0 0         else if (score > 100)
1103 0           score = 100;
1104              
1105 0           return score;
1106             }
1107              
1108             /* Tracks deletes by oid for merge_diff_mark_similarity_exact(). This is a
1109             * non-shrinking queue where next_pos is the next position to dequeue.
1110             */
1111             typedef struct {
1112             git_array_t(size_t) arr;
1113             size_t next_pos;
1114             size_t first_entry;
1115             } deletes_by_oid_queue;
1116              
1117 44           static void deletes_by_oid_free(git_oidmap *map) {
1118             deletes_by_oid_queue *queue;
1119              
1120 44 50         if (!map)
1121 0           return;
1122              
1123 45 100         git_oidmap_foreach_value(map, queue, {
1124             git_array_clear(queue->arr);
1125             });
1126 44           git_oidmap_free(map);
1127             }
1128              
1129 1           static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid *id, size_t idx)
1130             {
1131             deletes_by_oid_queue *queue;
1132             size_t *array_entry;
1133              
1134 1 50         if ((queue = git_oidmap_get(map, id)) == NULL) {
1135 1           queue = git_pool_malloc(pool, sizeof(deletes_by_oid_queue));
1136 1 50         GIT_ERROR_CHECK_ALLOC(queue);
1137              
1138 1           git_array_init(queue->arr);
1139 1           queue->next_pos = 0;
1140 1           queue->first_entry = idx;
1141              
1142 1 50         if (git_oidmap_set(map, id, queue) < 0)
1143 0           return -1;
1144             } else {
1145 0 0         array_entry = git_array_alloc(queue->arr);
    0          
1146 0 0         GIT_ERROR_CHECK_ALLOC(array_entry);
1147 0           *array_entry = idx;
1148             }
1149              
1150 1           return 0;
1151             }
1152              
1153 3           static int deletes_by_oid_dequeue(size_t *idx, git_oidmap *map, const git_oid *id)
1154             {
1155             deletes_by_oid_queue *queue;
1156             size_t *array_entry;
1157              
1158 3 50         if ((queue = git_oidmap_get(map, id)) == NULL)
1159 3           return GIT_ENOTFOUND;
1160              
1161 0 0         if (queue->next_pos == 0) {
1162 0           *idx = queue->first_entry;
1163             } else {
1164 0 0         array_entry = git_array_get(queue->arr, queue->next_pos - 1);
1165 0 0         if (array_entry == NULL)
1166 0           return GIT_ENOTFOUND;
1167              
1168 0           *idx = *array_entry;
1169             }
1170              
1171 0           queue->next_pos++;
1172 0           return 0;
1173             }
1174              
1175 22           static int merge_diff_mark_similarity_exact(
1176             git_merge_diff_list *diff_list,
1177             struct merge_diff_similarity *similarity_ours,
1178             struct merge_diff_similarity *similarity_theirs)
1179             {
1180             size_t i, j;
1181             git_merge_diff *conflict_src, *conflict_tgt;
1182 22           git_oidmap *ours_deletes_by_oid = NULL, *theirs_deletes_by_oid = NULL;
1183 22           int error = 0;
1184              
1185 44           if (git_oidmap_new(&ours_deletes_by_oid) < 0 ||
1186 22           git_oidmap_new(&theirs_deletes_by_oid) < 0) {
1187 0           error = -1;
1188 0           goto done;
1189             }
1190              
1191             /* Build a map of object ids to conflicts */
1192 44 100         git_vector_foreach(&diff_list->conflicts, i, conflict_src) {
1193             /* Items can be the source of a rename iff they have an item in the
1194             * ancestor slot and lack an item in the ours or theirs slot. */
1195 22 100         if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->ancestor_entry))
1196 3           continue;
1197              
1198 19 100         if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->our_entry)) {
1199 1           error = deletes_by_oid_enqueue(ours_deletes_by_oid, &diff_list->pool, &conflict_src->ancestor_entry.id, i);
1200 1 50         if (error < 0)
1201 0           goto done;
1202             }
1203              
1204 19 50         if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->their_entry)) {
1205 0           error = deletes_by_oid_enqueue(theirs_deletes_by_oid, &diff_list->pool, &conflict_src->ancestor_entry.id, i);
1206 0 0         if (error < 0)
1207 0           goto done;
1208             }
1209             }
1210              
1211 44 100         git_vector_foreach(&diff_list->conflicts, j, conflict_tgt) {
1212 22 100         if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->ancestor_entry))
1213 19           continue;
1214              
1215 3 50         if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->our_entry)) {
1216 0 0         if (deletes_by_oid_dequeue(&i, ours_deletes_by_oid, &conflict_tgt->our_entry.id) == 0) {
1217 0           similarity_ours[i].similarity = 100;
1218 0           similarity_ours[i].other_idx = j;
1219              
1220 0           similarity_ours[j].similarity = 100;
1221 0           similarity_ours[j].other_idx = i;
1222             }
1223             }
1224              
1225 3 50         if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->their_entry)) {
1226 3 50         if (deletes_by_oid_dequeue(&i, theirs_deletes_by_oid, &conflict_tgt->their_entry.id) == 0) {
1227 0           similarity_theirs[i].similarity = 100;
1228 0           similarity_theirs[i].other_idx = j;
1229              
1230 0           similarity_theirs[j].similarity = 100;
1231 0           similarity_theirs[j].other_idx = i;
1232             }
1233             }
1234             }
1235              
1236             done:
1237 22           deletes_by_oid_free(ours_deletes_by_oid);
1238 22           deletes_by_oid_free(theirs_deletes_by_oid);
1239              
1240 22           return error;
1241             }
1242              
1243 22           static int merge_diff_mark_similarity_inexact(
1244             git_repository *repo,
1245             git_merge_diff_list *diff_list,
1246             struct merge_diff_similarity *similarity_ours,
1247             struct merge_diff_similarity *similarity_theirs,
1248             void **cache,
1249             const git_merge_options *opts)
1250             {
1251             size_t i, j;
1252             git_merge_diff *conflict_src, *conflict_tgt;
1253             int similarity;
1254              
1255 44 100         git_vector_foreach(&diff_list->conflicts, i, conflict_src) {
1256             /* Items can be the source of a rename iff they have an item in the
1257             * ancestor slot and lack an item in the ours or theirs slot. */
1258 22 100         if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->ancestor_entry) ||
    100          
1259 18 50         (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->our_entry) &&
1260 18           GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->their_entry)))
1261 21           continue;
1262              
1263 2 100         git_vector_foreach(&diff_list->conflicts, j, conflict_tgt) {
1264 1           size_t our_idx = diff_list->conflicts.length + j;
1265 1           size_t their_idx = (diff_list->conflicts.length * 2) + j;
1266              
1267 1 50         if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->ancestor_entry))
1268 1           continue;
1269              
1270 0 0         if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->our_entry) &&
    0          
1271 0           !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->our_entry)) {
1272 0           similarity = index_entry_similarity_inexact(repo, &conflict_src->ancestor_entry, i, &conflict_tgt->our_entry, our_idx, cache, opts);
1273              
1274 0 0         if (similarity == GIT_EBUFS)
1275 0           continue;
1276 0 0         else if (similarity < 0)
1277 0           return similarity;
1278              
1279 0 0         if (similarity > similarity_ours[i].similarity &&
    0          
1280 0           similarity > similarity_ours[j].similarity) {
1281             /* Clear previous best similarity */
1282 0 0         if (similarity_ours[i].similarity > 0)
1283 0           similarity_ours[similarity_ours[i].other_idx].similarity = 0;
1284              
1285 0 0         if (similarity_ours[j].similarity > 0)
1286 0           similarity_ours[similarity_ours[j].other_idx].similarity = 0;
1287              
1288 0           similarity_ours[i].similarity = similarity;
1289 0           similarity_ours[i].other_idx = j;
1290              
1291 0           similarity_ours[j].similarity = similarity;
1292 0           similarity_ours[j].other_idx = i;
1293             }
1294             }
1295              
1296 0 0         if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->their_entry) &&
    0          
1297 0           !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->their_entry)) {
1298 0           similarity = index_entry_similarity_inexact(repo, &conflict_src->ancestor_entry, i, &conflict_tgt->their_entry, their_idx, cache, opts);
1299              
1300 0 0         if (similarity > similarity_theirs[i].similarity &&
    0          
1301 0           similarity > similarity_theirs[j].similarity) {
1302             /* Clear previous best similarity */
1303 0 0         if (similarity_theirs[i].similarity > 0)
1304 0           similarity_theirs[similarity_theirs[i].other_idx].similarity = 0;
1305              
1306 0 0         if (similarity_theirs[j].similarity > 0)
1307 0           similarity_theirs[similarity_theirs[j].other_idx].similarity = 0;
1308              
1309 0           similarity_theirs[i].similarity = similarity;
1310 0           similarity_theirs[i].other_idx = j;
1311              
1312 0           similarity_theirs[j].similarity = similarity;
1313 0           similarity_theirs[j].other_idx = i;
1314             }
1315             }
1316             }
1317             }
1318              
1319 22           return 0;
1320             }
1321              
1322             /*
1323             * Rename conflicts:
1324             *
1325             * Ancestor Ours Theirs
1326             *
1327             * 0a A A A No rename
1328             * b A A* A No rename (ours was rewritten)
1329             * c A A A* No rename (theirs rewritten)
1330             * 1a A A B[A] Rename or rename/edit
1331             * b A B[A] A (automergeable)
1332             * 2 A B[A] B[A] Both renamed (automergeable)
1333             * 3a A B[A] Rename/delete
1334             * b A B[A] (same)
1335             * 4a A B[A] B Rename/add [B~ours B~theirs]
1336             * b A B B[A] (same)
1337             * 5 A B[A] C[A] Both renamed ("1 -> 2")
1338             * 6 A C[A] Both renamed ("2 -> 1")
1339             * B C[B] [C~ours C~theirs] (automergeable)
1340             */
1341 22           static void merge_diff_mark_rename_conflict(
1342             git_merge_diff_list *diff_list,
1343             struct merge_diff_similarity *similarity_ours,
1344             bool ours_renamed,
1345             size_t ours_source_idx,
1346             struct merge_diff_similarity *similarity_theirs,
1347             bool theirs_renamed,
1348             size_t theirs_source_idx,
1349             git_merge_diff *target,
1350             const git_merge_options *opts)
1351             {
1352 22           git_merge_diff *ours_source = NULL, *theirs_source = NULL;
1353              
1354 22 50         if (ours_renamed)
1355 0           ours_source = diff_list->conflicts.contents[ours_source_idx];
1356              
1357 22 50         if (theirs_renamed)
1358 0           theirs_source = diff_list->conflicts.contents[theirs_source_idx];
1359              
1360             /* Detect 2->1 conflicts */
1361 22 50         if (ours_renamed && theirs_renamed) {
    0          
1362             /* Both renamed to the same target name. */
1363 0 0         if (ours_source_idx == theirs_source_idx)
1364 0           ours_source->type = GIT_MERGE_DIFF_BOTH_RENAMED;
1365             else {
1366 0           ours_source->type = GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1;
1367 0           theirs_source->type = GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1;
1368             }
1369 22 50         } else if (ours_renamed) {
1370             /* If our source was also renamed in theirs, this is a 1->2 */
1371 0 0         if (similarity_theirs[ours_source_idx].similarity >= opts->rename_threshold)
1372 0           ours_source->type = GIT_MERGE_DIFF_BOTH_RENAMED_1_TO_2;
1373              
1374 0 0         else if (GIT_MERGE_INDEX_ENTRY_EXISTS(target->their_entry)) {
1375 0           ours_source->type = GIT_MERGE_DIFF_RENAMED_ADDED;
1376 0           target->type = GIT_MERGE_DIFF_RENAMED_ADDED;
1377             }
1378              
1379 0 0         else if (!GIT_MERGE_INDEX_ENTRY_EXISTS(ours_source->their_entry))
1380 0           ours_source->type = GIT_MERGE_DIFF_RENAMED_DELETED;
1381              
1382 0 0         else if (ours_source->type == GIT_MERGE_DIFF_MODIFIED_DELETED)
1383 0           ours_source->type = GIT_MERGE_DIFF_RENAMED_MODIFIED;
1384 22 50         } else if (theirs_renamed) {
1385             /* If their source was also renamed in ours, this is a 1->2 */
1386 0 0         if (similarity_ours[theirs_source_idx].similarity >= opts->rename_threshold)
1387 0           theirs_source->type = GIT_MERGE_DIFF_BOTH_RENAMED_1_TO_2;
1388              
1389 0 0         else if (GIT_MERGE_INDEX_ENTRY_EXISTS(target->our_entry)) {
1390 0           theirs_source->type = GIT_MERGE_DIFF_RENAMED_ADDED;
1391 0           target->type = GIT_MERGE_DIFF_RENAMED_ADDED;
1392             }
1393              
1394 0 0         else if (!GIT_MERGE_INDEX_ENTRY_EXISTS(theirs_source->our_entry))
1395 0           theirs_source->type = GIT_MERGE_DIFF_RENAMED_DELETED;
1396              
1397 0 0         else if (theirs_source->type == GIT_MERGE_DIFF_MODIFIED_DELETED)
1398 0           theirs_source->type = GIT_MERGE_DIFF_RENAMED_MODIFIED;
1399             }
1400 22           }
1401              
1402 0           GIT_INLINE(void) merge_diff_coalesce_rename(
1403             git_index_entry *source_entry,
1404             git_delta_t *source_status,
1405             git_index_entry *target_entry,
1406             git_delta_t *target_status)
1407             {
1408             /* Coalesce the rename target into the rename source. */
1409 0           memcpy(source_entry, target_entry, sizeof(git_index_entry));
1410 0           *source_status = GIT_DELTA_RENAMED;
1411              
1412 0           memset(target_entry, 0x0, sizeof(git_index_entry));
1413 0           *target_status = GIT_DELTA_UNMODIFIED;
1414 0           }
1415              
1416 22           static void merge_diff_list_coalesce_renames(
1417             git_merge_diff_list *diff_list,
1418             struct merge_diff_similarity *similarity_ours,
1419             struct merge_diff_similarity *similarity_theirs,
1420             const git_merge_options *opts)
1421             {
1422             size_t i;
1423 22           bool ours_renamed = 0, theirs_renamed = 0;
1424 22           size_t ours_source_idx = 0, theirs_source_idx = 0;
1425             git_merge_diff *ours_source, *theirs_source, *target;
1426              
1427 44 100         for (i = 0; i < diff_list->conflicts.length; i++) {
1428 22           target = diff_list->conflicts.contents[i];
1429              
1430 22           ours_renamed = 0;
1431 22           theirs_renamed = 0;
1432              
1433 22 100         if (GIT_MERGE_INDEX_ENTRY_EXISTS(target->our_entry) &&
    50          
1434 18           similarity_ours[i].similarity >= opts->rename_threshold) {
1435 0           ours_source_idx = similarity_ours[i].other_idx;
1436              
1437 0           ours_source = diff_list->conflicts.contents[ours_source_idx];
1438              
1439 0           merge_diff_coalesce_rename(
1440             &ours_source->our_entry,
1441             &ours_source->our_status,
1442             &target->our_entry,
1443             &target->our_status);
1444              
1445 0           similarity_ours[ours_source_idx].similarity = 0;
1446 0           similarity_ours[i].similarity = 0;
1447              
1448 0           ours_renamed = 1;
1449             }
1450              
1451             /* insufficient to determine direction */
1452 22 50         if (GIT_MERGE_INDEX_ENTRY_EXISTS(target->their_entry) &&
    50          
1453 22           similarity_theirs[i].similarity >= opts->rename_threshold) {
1454 0           theirs_source_idx = similarity_theirs[i].other_idx;
1455              
1456 0           theirs_source = diff_list->conflicts.contents[theirs_source_idx];
1457              
1458 0           merge_diff_coalesce_rename(
1459             &theirs_source->their_entry,
1460             &theirs_source->their_status,
1461             &target->their_entry,
1462             &target->their_status);
1463              
1464 0           similarity_theirs[theirs_source_idx].similarity = 0;
1465 0           similarity_theirs[i].similarity = 0;
1466              
1467 0           theirs_renamed = 1;
1468             }
1469              
1470 22           merge_diff_mark_rename_conflict(diff_list,
1471             similarity_ours, ours_renamed, ours_source_idx,
1472             similarity_theirs, theirs_renamed, theirs_source_idx,
1473             target, opts);
1474             }
1475 22           }
1476              
1477 22           static int merge_diff_empty(const git_vector *conflicts, size_t idx, void *p)
1478             {
1479 22           git_merge_diff *conflict = conflicts->contents[idx];
1480              
1481             GIT_UNUSED(p);
1482              
1483 25 50         return (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) &&
1484 25 100         !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) &&
    50          
1485 3           !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry));
1486             }
1487              
1488 22           static void merge_diff_list_count_candidates(
1489             git_merge_diff_list *diff_list,
1490             size_t *src_count,
1491             size_t *tgt_count)
1492             {
1493             git_merge_diff *entry;
1494             size_t i;
1495              
1496 22           *src_count = 0;
1497 22           *tgt_count = 0;
1498              
1499 44 100         git_vector_foreach(&diff_list->conflicts, i, entry) {
1500 22 100         if (GIT_MERGE_INDEX_ENTRY_EXISTS(entry->ancestor_entry) &&
    100          
1501 18 50         (!GIT_MERGE_INDEX_ENTRY_EXISTS(entry->our_entry) ||
1502 18           !GIT_MERGE_INDEX_ENTRY_EXISTS(entry->their_entry)))
1503 1           (*src_count)++;
1504 21 100         else if (!GIT_MERGE_INDEX_ENTRY_EXISTS(entry->ancestor_entry))
1505 3           (*tgt_count)++;
1506             }
1507 22           }
1508              
1509 22           int git_merge_diff_list__find_renames(
1510             git_repository *repo,
1511             git_merge_diff_list *diff_list,
1512             const git_merge_options *opts)
1513             {
1514             struct merge_diff_similarity *similarity_ours, *similarity_theirs;
1515 22           void **cache = NULL;
1516 22           size_t cache_size = 0;
1517             size_t src_count, tgt_count, i;
1518 22           int error = 0;
1519              
1520 22 50         assert(diff_list && opts);
    50          
1521              
1522 22 50         if ((opts->flags & GIT_MERGE_FIND_RENAMES) == 0)
1523 0           return 0;
1524              
1525 22           similarity_ours = git__calloc(diff_list->conflicts.length,
1526             sizeof(struct merge_diff_similarity));
1527 22 50         GIT_ERROR_CHECK_ALLOC(similarity_ours);
1528              
1529 22           similarity_theirs = git__calloc(diff_list->conflicts.length,
1530             sizeof(struct merge_diff_similarity));
1531 22 50         GIT_ERROR_CHECK_ALLOC(similarity_theirs);
1532              
1533             /* Calculate similarity between items that were deleted from the ancestor
1534             * and added in the other branch.
1535             */
1536 22 50         if ((error = merge_diff_mark_similarity_exact(diff_list, similarity_ours, similarity_theirs)) < 0)
1537 0           goto done;
1538              
1539 22 50         if (opts->rename_threshold < 100 && diff_list->conflicts.length <= opts->target_limit) {
    50          
1540 22 50         GIT_ERROR_CHECK_ALLOC_MULTIPLY(&cache_size, diff_list->conflicts.length, 3);
    50          
1541 22           cache = git__calloc(cache_size, sizeof(void *));
1542 22 50         GIT_ERROR_CHECK_ALLOC(cache);
1543              
1544 22           merge_diff_list_count_candidates(diff_list, &src_count, &tgt_count);
1545              
1546 22 50         if (src_count > opts->target_limit || tgt_count > opts->target_limit) {
    50          
1547             /* TODO: report! */
1548             } else {
1549 22 50         if ((error = merge_diff_mark_similarity_inexact(
1550             repo, diff_list, similarity_ours, similarity_theirs, cache, opts)) < 0)
1551 0           goto done;
1552             }
1553             }
1554              
1555             /* For entries that are appropriately similar, merge the new name's entry
1556             * into the old name.
1557             */
1558 22           merge_diff_list_coalesce_renames(diff_list, similarity_ours, similarity_theirs, opts);
1559              
1560             /* And remove any entries that were merged and are now empty. */
1561 22           git_vector_remove_matching(&diff_list->conflicts, merge_diff_empty, NULL);
1562              
1563             done:
1564 22 50         if (cache != NULL) {
1565 88 100         for (i = 0; i < cache_size; ++i) {
1566 66 50         if (cache[i] != NULL && cache[i] != &cache_invalid_marker)
    0          
1567 0           opts->metric->free_signature(cache[i], opts->metric->payload);
1568             }
1569              
1570 22           git__free(cache);
1571             }
1572              
1573 22           git__free(similarity_ours);
1574 22           git__free(similarity_theirs);
1575              
1576 22           return error;
1577             }
1578              
1579             /* Directory/file conflict handling */
1580              
1581 22           GIT_INLINE(const char *) merge_diff_path(
1582             const git_merge_diff *conflict)
1583             {
1584 22 100         if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry))
1585 19           return conflict->ancestor_entry.path;
1586 3 50         else if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry))
1587 0           return conflict->our_entry.path;
1588 3 50         else if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry))
1589 3           return conflict->their_entry.path;
1590              
1591 0           return NULL;
1592             }
1593              
1594 0           GIT_INLINE(bool) merge_diff_any_side_added_or_modified(
1595             const git_merge_diff *conflict)
1596             {
1597 0 0         if (conflict->our_status == GIT_DELTA_ADDED ||
    0          
1598 0 0         conflict->our_status == GIT_DELTA_MODIFIED ||
1599 0 0         conflict->their_status == GIT_DELTA_ADDED ||
1600 0           conflict->their_status == GIT_DELTA_MODIFIED)
1601 0           return true;
1602              
1603 0           return false;
1604             }
1605              
1606 0           GIT_INLINE(bool) path_is_prefixed(const char *parent, const char *child)
1607             {
1608 0           size_t child_len = strlen(child);
1609 0           size_t parent_len = strlen(parent);
1610              
1611 0 0         if (child_len < parent_len ||
    0          
1612 0           strncmp(parent, child, parent_len) != 0)
1613 0           return 0;
1614              
1615 0           return (child[parent_len] == '/');
1616             }
1617              
1618 22           GIT_INLINE(int) merge_diff_detect_df_conflict(
1619             struct merge_diff_df_data *df_data,
1620             git_merge_diff *conflict)
1621             {
1622 22           const char *cur_path = merge_diff_path(conflict);
1623              
1624             /* Determine if this is a D/F conflict or the child of one */
1625 22           if (df_data->df_path &&
1626 0           path_is_prefixed(df_data->df_path, cur_path))
1627 0           conflict->type = GIT_MERGE_DIFF_DF_CHILD;
1628 22 50         else if(df_data->df_path)
1629 0           df_data->df_path = NULL;
1630 22           else if (df_data->prev_path &&
1631 0 0         merge_diff_any_side_added_or_modified(df_data->prev_conflict) &&
1632 0 0         merge_diff_any_side_added_or_modified(conflict) &&
1633 0           path_is_prefixed(df_data->prev_path, cur_path)) {
1634 0           conflict->type = GIT_MERGE_DIFF_DF_CHILD;
1635              
1636 0           df_data->prev_conflict->type = GIT_MERGE_DIFF_DIRECTORY_FILE;
1637 0           df_data->df_path = df_data->prev_path;
1638             }
1639              
1640 22           df_data->prev_path = cur_path;
1641 22           df_data->prev_conflict = conflict;
1642              
1643 22           return 0;
1644             }
1645              
1646             /* Conflict handling */
1647              
1648 22           GIT_INLINE(int) merge_diff_detect_type(
1649             git_merge_diff *conflict)
1650             {
1651 22 50         if (conflict->our_status == GIT_DELTA_ADDED &&
    0          
1652 0           conflict->their_status == GIT_DELTA_ADDED)
1653 0           conflict->type = GIT_MERGE_DIFF_BOTH_ADDED;
1654 22 100         else if (conflict->our_status == GIT_DELTA_MODIFIED &&
    50          
1655 7           conflict->their_status == GIT_DELTA_MODIFIED)
1656 7           conflict->type = GIT_MERGE_DIFF_BOTH_MODIFIED;
1657 15 100         else if (conflict->our_status == GIT_DELTA_DELETED &&
    50          
1658 1           conflict->their_status == GIT_DELTA_DELETED)
1659 0           conflict->type = GIT_MERGE_DIFF_BOTH_DELETED;
1660 15 50         else if (conflict->our_status == GIT_DELTA_MODIFIED &&
    0          
1661 0           conflict->their_status == GIT_DELTA_DELETED)
1662 0           conflict->type = GIT_MERGE_DIFF_MODIFIED_DELETED;
1663 15 100         else if (conflict->our_status == GIT_DELTA_DELETED &&
    50          
1664 1           conflict->their_status == GIT_DELTA_MODIFIED)
1665 1           conflict->type = GIT_MERGE_DIFF_MODIFIED_DELETED;
1666             else
1667 14           conflict->type = GIT_MERGE_DIFF_NONE;
1668              
1669 22           return 0;
1670             }
1671              
1672 92           GIT_INLINE(int) index_entry_dup_pool(
1673             git_index_entry *out,
1674             git_pool *pool,
1675             const git_index_entry *src)
1676             {
1677 92 100         if (src != NULL) {
1678 85           memcpy(out, src, sizeof(git_index_entry));
1679 85 50         if ((out->path = git_pool_strdup(pool, src->path)) == NULL)
1680 0           return -1;
1681             }
1682              
1683 92           return 0;
1684             }
1685              
1686 44           GIT_INLINE(int) merge_delta_type_from_index_entries(
1687             const git_index_entry *ancestor,
1688             const git_index_entry *other)
1689             {
1690 44 100         if (ancestor == NULL && other == NULL)
    100          
1691 3           return GIT_DELTA_UNMODIFIED;
1692 41 100         else if (ancestor == NULL && other != NULL)
    50          
1693 3           return GIT_DELTA_ADDED;
1694 38 50         else if (ancestor != NULL && other == NULL)
    100          
1695 1           return GIT_DELTA_DELETED;
1696 37 50         else if (S_ISDIR(ancestor->mode) ^ S_ISDIR(other->mode))
1697 0           return GIT_DELTA_TYPECHANGE;
1698 37 50         else if(S_ISLNK(ancestor->mode) ^ S_ISLNK(other->mode))
1699 0           return GIT_DELTA_TYPECHANGE;
1700 37 100         else if (git_oid__cmp(&ancestor->id, &other->id) ||
    50          
1701 11           ancestor->mode != other->mode)
1702 26           return GIT_DELTA_MODIFIED;
1703              
1704 11           return GIT_DELTA_UNMODIFIED;
1705             }
1706              
1707 22           static git_merge_diff *merge_diff_from_index_entries(
1708             git_merge_diff_list *diff_list,
1709             const git_index_entry **entries)
1710             {
1711             git_merge_diff *conflict;
1712 22           git_pool *pool = &diff_list->pool;
1713              
1714 22 50         if ((conflict = git_pool_mallocz(pool, sizeof(git_merge_diff))) == NULL)
1715 0           return NULL;
1716              
1717 44           if (index_entry_dup_pool(&conflict->ancestor_entry, pool, entries[TREE_IDX_ANCESTOR]) < 0 ||
1718 44 50         index_entry_dup_pool(&conflict->our_entry, pool, entries[TREE_IDX_OURS]) < 0 ||
1719 22           index_entry_dup_pool(&conflict->their_entry, pool, entries[TREE_IDX_THEIRS]) < 0)
1720 0           return NULL;
1721              
1722 22           conflict->our_status = merge_delta_type_from_index_entries(
1723 22           entries[TREE_IDX_ANCESTOR], entries[TREE_IDX_OURS]);
1724 22           conflict->their_status = merge_delta_type_from_index_entries(
1725 22           entries[TREE_IDX_ANCESTOR], entries[TREE_IDX_THEIRS]);
1726              
1727 22           return conflict;
1728             }
1729              
1730             /* Merge trees */
1731              
1732 22           static int merge_diff_list_insert_conflict(
1733             git_merge_diff_list *diff_list,
1734             struct merge_diff_df_data *merge_df_data,
1735             const git_index_entry *tree_items[3])
1736             {
1737             git_merge_diff *conflict;
1738              
1739 44           if ((conflict = merge_diff_from_index_entries(diff_list, tree_items)) == NULL ||
1740 44 50         merge_diff_detect_type(conflict) < 0 ||
1741 44 50         merge_diff_detect_df_conflict(merge_df_data, conflict) < 0 ||
1742 22           git_vector_insert(&diff_list->conflicts, conflict) < 0)
1743 0           return -1;
1744              
1745 22           return 0;
1746             }
1747              
1748 26           static int merge_diff_list_insert_unmodified(
1749             git_merge_diff_list *diff_list,
1750             const git_index_entry *tree_items[3])
1751             {
1752 26           int error = 0;
1753             git_index_entry *entry;
1754              
1755 26           entry = git_pool_malloc(&diff_list->pool, sizeof(git_index_entry));
1756 26 50         GIT_ERROR_CHECK_ALLOC(entry);
1757              
1758 26 50         if ((error = index_entry_dup_pool(entry, &diff_list->pool, tree_items[0])) >= 0)
1759 26           error = git_vector_insert(&diff_list->staged, entry);
1760              
1761 26           return error;
1762             }
1763              
1764             struct merge_diff_find_data {
1765             git_merge_diff_list *diff_list;
1766             struct merge_diff_df_data df_data;
1767             };
1768              
1769 48           static int queue_difference(const git_index_entry **entries, void *data)
1770             {
1771 48           struct merge_diff_find_data *find_data = data;
1772 48           bool item_modified = false;
1773             size_t i;
1774              
1775 48 100         if (!entries[0] || !entries[1] || !entries[2]) {
    100          
    50          
1776 4           item_modified = true;
1777             } else {
1778 107 100         for (i = 1; i < 3; i++) {
1779 81 100         if (index_entry_cmp(entries[0], entries[i]) != 0) {
1780 18           item_modified = true;
1781 18           break;
1782             }
1783             }
1784             }
1785              
1786 48           return item_modified ?
1787 22           merge_diff_list_insert_conflict(
1788 48 100         find_data->diff_list, &find_data->df_data, entries) :
1789 26           merge_diff_list_insert_unmodified(find_data->diff_list, entries);
1790             }
1791              
1792 22           int git_merge_diff_list__find_differences(
1793             git_merge_diff_list *diff_list,
1794             git_iterator *ancestor_iter,
1795             git_iterator *our_iter,
1796             git_iterator *their_iter)
1797             {
1798 22           git_iterator *iterators[3] = { ancestor_iter, our_iter, their_iter };
1799 22           struct merge_diff_find_data find_data = { diff_list };
1800              
1801 22           return git_iterator_walk(iterators, 3, queue_difference, &find_data);
1802             }
1803              
1804 22           git_merge_diff_list *git_merge_diff_list__alloc(git_repository *repo)
1805             {
1806 22           git_merge_diff_list *diff_list = git__calloc(1, sizeof(git_merge_diff_list));
1807              
1808 22 50         if (diff_list == NULL)
1809 0           return NULL;
1810              
1811 22           diff_list->repo = repo;
1812              
1813 22           git_pool_init(&diff_list->pool, 1);
1814              
1815 44           if (git_vector_init(&diff_list->staged, 0, NULL) < 0 ||
1816 44 50         git_vector_init(&diff_list->conflicts, 0, NULL) < 0 ||
1817 22           git_vector_init(&diff_list->resolved, 0, NULL) < 0) {
1818 0           git_merge_diff_list__free(diff_list);
1819 0           return NULL;
1820             }
1821              
1822 22           return diff_list;
1823             }
1824              
1825 22           void git_merge_diff_list__free(git_merge_diff_list *diff_list)
1826             {
1827 22 50         if (!diff_list)
1828 0           return;
1829              
1830 22           git_vector_free(&diff_list->staged);
1831 22           git_vector_free(&diff_list->conflicts);
1832 22           git_vector_free(&diff_list->resolved);
1833 22           git_pool_clear(&diff_list->pool);
1834 22           git__free(diff_list);
1835             }
1836              
1837 22           static int merge_normalize_opts(
1838             git_repository *repo,
1839             git_merge_options *opts,
1840             const git_merge_options *given)
1841             {
1842 22           git_config *cfg = NULL;
1843 22           git_config_entry *entry = NULL;
1844 22           int error = 0;
1845              
1846 22 50         assert(repo && opts);
    50          
1847              
1848 22 50         if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
1849 0           return error;
1850              
1851 22 100         if (given != NULL) {
1852 18           memcpy(opts, given, sizeof(git_merge_options));
1853             } else {
1854 4           git_merge_options init = GIT_MERGE_OPTIONS_INIT;
1855 4           memcpy(opts, &init, sizeof(init));
1856             }
1857              
1858 22 50         if ((opts->flags & GIT_MERGE_FIND_RENAMES) && !opts->rename_threshold)
    100          
1859 21           opts->rename_threshold = GIT_MERGE_DEFAULT_RENAME_THRESHOLD;
1860              
1861 22 100         if (given && given->default_driver) {
    50          
1862 0           opts->default_driver = git__strdup(given->default_driver);
1863 0 0         GIT_ERROR_CHECK_ALLOC(opts->default_driver);
1864             } else {
1865 22           error = git_config_get_entry(&entry, cfg, "merge.default");
1866              
1867 22 50         if (error == 0) {
1868 0           opts->default_driver = git__strdup(entry->value);
1869 0 0         GIT_ERROR_CHECK_ALLOC(opts->default_driver);
1870 22 50         } else if (error == GIT_ENOTFOUND) {
1871 22           error = 0;
1872             } else {
1873 0           goto done;
1874             }
1875             }
1876              
1877 22 100         if (!opts->target_limit) {
1878 21           int limit = git_config__get_int_force(cfg, "merge.renamelimit", 0);
1879              
1880 21 50         if (!limit)
1881 21           limit = git_config__get_int_force(cfg, "diff.renamelimit", 0);
1882              
1883 21           opts->target_limit = (limit <= 0) ?
1884 21 50         GIT_MERGE_DEFAULT_TARGET_LIMIT : (unsigned int)limit;
1885             }
1886              
1887             /* assign the internal metric with whitespace flag as payload */
1888 22 50         if (!opts->metric) {
1889 22           opts->metric = git__malloc(sizeof(git_diff_similarity_metric));
1890 22 50         GIT_ERROR_CHECK_ALLOC(opts->metric);
1891              
1892 22           opts->metric->file_signature = git_diff_find_similar__hashsig_for_file;
1893 22           opts->metric->buffer_signature = git_diff_find_similar__hashsig_for_buf;
1894 22           opts->metric->free_signature = git_diff_find_similar__hashsig_free;
1895 22           opts->metric->similarity = git_diff_find_similar__calc_similarity;
1896 22           opts->metric->payload = (void *)GIT_HASHSIG_SMART_WHITESPACE;
1897             }
1898              
1899             done:
1900 22           git_config_entry_free(entry);
1901 22           return error;
1902             }
1903              
1904              
1905 6           static int merge_index_insert_reuc(
1906             git_index *index,
1907             size_t idx,
1908             const git_index_entry *entry)
1909             {
1910             const git_index_reuc_entry *reuc;
1911 6           int mode[3] = { 0, 0, 0 };
1912 6           git_oid const *oid[3] = { NULL, NULL, NULL };
1913             size_t i;
1914              
1915 6 50         if (!GIT_MERGE_INDEX_ENTRY_EXISTS(*entry))
1916 0           return 0;
1917              
1918 6 100         if ((reuc = git_index_reuc_get_bypath(index, entry->path)) != NULL) {
1919 16 100         for (i = 0; i < 3; i++) {
1920 12           mode[i] = reuc->mode[i];
1921 12           oid[i] = &reuc->oid[i];
1922             }
1923             }
1924              
1925 6           mode[idx] = entry->mode;
1926 6           oid[idx] = &entry->id;
1927              
1928 6           return git_index_reuc_add(index, entry->path,
1929             mode[0], oid[0], mode[1], oid[1], mode[2], oid[2]);
1930             }
1931              
1932 22           static int index_update_reuc(git_index *index, git_merge_diff_list *diff_list)
1933             {
1934             int error;
1935             size_t i;
1936             git_merge_diff *conflict;
1937              
1938             /* Add each entry in the resolved conflict to the REUC independently, since
1939             * the paths may differ due to renames. */
1940 24 100         git_vector_foreach(&diff_list->resolved, i, conflict) {
1941 2           const git_index_entry *ancestor =
1942 2           GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
1943 2 50         &conflict->ancestor_entry : NULL;
1944              
1945 2           const git_index_entry *ours =
1946 2           GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
1947 2 50         &conflict->our_entry : NULL;
1948              
1949 2           const git_index_entry *theirs =
1950 2           GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
1951 2 50         &conflict->their_entry : NULL;
1952              
1953 2 50         if (ancestor != NULL &&
    50          
1954             (error = merge_index_insert_reuc(index, TREE_IDX_ANCESTOR, ancestor)) < 0)
1955 0           return error;
1956              
1957 2 50         if (ours != NULL &&
    50          
1958             (error = merge_index_insert_reuc(index, TREE_IDX_OURS, ours)) < 0)
1959 0           return error;
1960              
1961 2 50         if (theirs != NULL &&
    50          
1962             (error = merge_index_insert_reuc(index, TREE_IDX_THEIRS, theirs)) < 0)
1963 0           return error;
1964             }
1965              
1966 22           return 0;
1967             }
1968              
1969 22           static int index_from_diff_list(git_index **out,
1970             git_merge_diff_list *diff_list, bool skip_reuc)
1971             {
1972             git_index *index;
1973             size_t i;
1974             git_merge_diff *conflict;
1975 22           int error = 0;
1976              
1977 22           *out = NULL;
1978              
1979 22 50         if ((error = git_index_new(&index)) < 0)
1980 0           return error;
1981              
1982 22 50         if ((error = git_index__fill(index, &diff_list->staged)) < 0)
1983 0           goto on_error;
1984              
1985 27 100         git_vector_foreach(&diff_list->conflicts, i, conflict) {
1986 5           const git_index_entry *ancestor =
1987 5           GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
1988 5 50         &conflict->ancestor_entry : NULL;
1989              
1990 5           const git_index_entry *ours =
1991 5           GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
1992 5 100         &conflict->our_entry : NULL;
1993              
1994 5           const git_index_entry *theirs =
1995 5           GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
1996 5 50         &conflict->their_entry : NULL;
1997              
1998 5 50         if ((error = git_index_conflict_add(index, ancestor, ours, theirs)) < 0)
1999 0           goto on_error;
2000             }
2001              
2002             /* Add each rename entry to the rename portion of the index. */
2003 27 100         git_vector_foreach(&diff_list->conflicts, i, conflict) {
2004             const char *ancestor_path, *our_path, *their_path;
2005              
2006 5 50         if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry))
2007 0           continue;
2008              
2009 5           ancestor_path = conflict->ancestor_entry.path;
2010              
2011 5           our_path =
2012 5           GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
2013 5 100         conflict->our_entry.path : NULL;
2014              
2015 5           their_path =
2016 5           GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
2017 5 50         conflict->their_entry.path : NULL;
2018              
2019 5 100         if ((our_path && strcmp(ancestor_path, our_path) != 0) ||
    50          
    50          
2020 5 50         (their_path && strcmp(ancestor_path, their_path) != 0)) {
2021 0 0         if ((error = git_index_name_add(index, ancestor_path, our_path, their_path)) < 0)
2022 0           goto on_error;
2023             }
2024             }
2025              
2026 22 50         if (!skip_reuc) {
2027 22 50         if ((error = index_update_reuc(index, diff_list)) < 0)
2028 0           goto on_error;
2029             }
2030              
2031 22           *out = index;
2032 22           return 0;
2033              
2034             on_error:
2035 0           git_index_free(index);
2036 22           return error;
2037             }
2038              
2039 66           static git_iterator *iterator_given_or_empty(git_iterator **empty, git_iterator *given)
2040             {
2041 66           git_iterator_options opts = GIT_ITERATOR_OPTIONS_INIT;
2042              
2043 66 50         if (given)
2044 66           return given;
2045              
2046 0           opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
2047              
2048 0 0         if (git_iterator_for_nothing(empty, &opts) < 0)
2049 0           return NULL;
2050              
2051 66           return *empty;
2052             }
2053              
2054 22           int git_merge__iterators(
2055             git_index **out,
2056             git_repository *repo,
2057             git_iterator *ancestor_iter,
2058             git_iterator *our_iter,
2059             git_iterator *theirs_iter,
2060             const git_merge_options *given_opts)
2061             {
2062 22           git_iterator *empty_ancestor = NULL,
2063 22           *empty_ours = NULL,
2064 22           *empty_theirs = NULL;
2065             git_merge_diff_list *diff_list;
2066             git_merge_options opts;
2067 22           git_merge_file_options file_opts = GIT_MERGE_FILE_OPTIONS_INIT;
2068             git_merge_diff *conflict;
2069             git_vector changes;
2070             size_t i;
2071 22           int error = 0;
2072              
2073 22 50         assert(out && repo);
    50          
2074              
2075 22           *out = NULL;
2076              
2077 22 50         GIT_ERROR_CHECK_VERSION(
2078             given_opts, GIT_MERGE_OPTIONS_VERSION, "git_merge_options");
2079              
2080 22 50         if ((error = merge_normalize_opts(repo, &opts, given_opts)) < 0)
2081 0           return error;
2082              
2083 22           file_opts.favor = opts.file_favor;
2084 22           file_opts.flags = opts.file_flags;
2085              
2086             /* use the git-inspired labels when virtual base building */
2087 22 50         if (opts.flags & GIT_MERGE__VIRTUAL_BASE) {
2088 0           file_opts.ancestor_label = "merged common ancestors";
2089 0           file_opts.our_label = "Temporary merge branch 1";
2090 0           file_opts.their_label = "Temporary merge branch 2";
2091 0           file_opts.flags |= GIT_MERGE_FILE_FAVOR__CONFLICTED;
2092 0           file_opts.marker_size = GIT_MERGE_CONFLICT_MARKER_SIZE + 2;
2093             }
2094              
2095 22           diff_list = git_merge_diff_list__alloc(repo);
2096 22 50         GIT_ERROR_CHECK_ALLOC(diff_list);
2097              
2098 22           ancestor_iter = iterator_given_or_empty(&empty_ancestor, ancestor_iter);
2099 22           our_iter = iterator_given_or_empty(&empty_ours, our_iter);
2100 22           theirs_iter = iterator_given_or_empty(&empty_theirs, theirs_iter);
2101              
2102 22 50         if ((error = git_merge_diff_list__find_differences(
2103 22 50         diff_list, ancestor_iter, our_iter, theirs_iter)) < 0 ||
2104             (error = git_merge_diff_list__find_renames(repo, diff_list, &opts)) < 0)
2105             goto done;
2106              
2107 22           memcpy(&changes, &diff_list->conflicts, sizeof(git_vector));
2108 22           git_vector_clear(&diff_list->conflicts);
2109              
2110 44 100         git_vector_foreach(&changes, i, conflict) {
2111 22           int resolved = 0;
2112              
2113 22 50         if ((error = merge_conflict_resolve(
2114             &resolved, diff_list, conflict, &opts, &file_opts)) < 0)
2115 0           goto done;
2116              
2117 22 100         if (!resolved) {
2118 5 50         if ((opts.flags & GIT_MERGE_FAIL_ON_CONFLICT)) {
2119 0           git_error_set(GIT_ERROR_MERGE, "merge conflicts exist");
2120 0           error = GIT_EMERGECONFLICT;
2121 0           goto done;
2122             }
2123              
2124 5           git_vector_insert(&diff_list->conflicts, conflict);
2125             }
2126             }
2127              
2128 22           error = index_from_diff_list(out, diff_list,
2129 22           (opts.flags & GIT_MERGE_SKIP_REUC));
2130              
2131             done:
2132 22 100         if (!given_opts || !given_opts->metric)
    50          
2133 22           git__free(opts.metric);
2134              
2135 22           git__free((char *)opts.default_driver);
2136              
2137 22           git_merge_diff_list__free(diff_list);
2138 22           git_iterator_free(empty_ancestor);
2139 22           git_iterator_free(empty_ours);
2140 22           git_iterator_free(empty_theirs);
2141              
2142 22           return error;
2143             }
2144              
2145 12           int git_merge_trees(
2146             git_index **out,
2147             git_repository *repo,
2148             const git_tree *ancestor_tree,
2149             const git_tree *our_tree,
2150             const git_tree *their_tree,
2151             const git_merge_options *merge_opts)
2152             {
2153 12           git_iterator *ancestor_iter = NULL, *our_iter = NULL, *their_iter = NULL;
2154 12           git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
2155             int error;
2156              
2157 12 50         assert(out && repo);
    50          
2158              
2159             /* if one side is treesame to the ancestor, take the other side */
2160 12 50         if (ancestor_tree && merge_opts && (merge_opts->flags & GIT_MERGE_SKIP_REUC)) {
    50          
    50          
2161 0           const git_tree *result = NULL;
2162 0           const git_oid *ancestor_tree_id = git_tree_id(ancestor_tree);
2163              
2164 0 0         if (our_tree && !git_oid_cmp(ancestor_tree_id, git_tree_id(our_tree)))
    0          
2165 0           result = their_tree;
2166 0 0         else if (their_tree && !git_oid_cmp(ancestor_tree_id, git_tree_id(their_tree)))
    0          
2167 0           result = our_tree;
2168              
2169 0 0         if (result) {
2170 0 0         if ((error = git_index_new(out)) == 0)
2171 0           error = git_index_read_tree(*out, result);
2172              
2173 0           return error;
2174             }
2175             }
2176              
2177 12           iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
2178              
2179 12 50         if ((error = git_iterator_for_tree(
2180 12 50         &ancestor_iter, (git_tree *)ancestor_tree, &iter_opts)) < 0 ||
2181             (error = git_iterator_for_tree(
2182 12 50         &our_iter, (git_tree *)our_tree, &iter_opts)) < 0 ||
2183             (error = git_iterator_for_tree(
2184             &their_iter, (git_tree *)their_tree, &iter_opts)) < 0)
2185             goto done;
2186              
2187 12           error = git_merge__iterators(
2188             out, repo, ancestor_iter, our_iter, their_iter, merge_opts);
2189              
2190             done:
2191 12           git_iterator_free(ancestor_iter);
2192 12           git_iterator_free(our_iter);
2193 12           git_iterator_free(their_iter);
2194              
2195 12           return error;
2196             }
2197              
2198             static int merge_annotated_commits(
2199             git_index **index_out,
2200             git_annotated_commit **base_out,
2201             git_repository *repo,
2202             git_annotated_commit *our_commit,
2203             git_annotated_commit *their_commit,
2204             size_t recursion_level,
2205             const git_merge_options *opts);
2206              
2207 12           GIT_INLINE(int) insert_head_ids(
2208             git_array_oid_t *ids,
2209             const git_annotated_commit *annotated_commit)
2210             {
2211             git_oid *id;
2212             size_t i;
2213              
2214 12 50         if (annotated_commit->type == GIT_ANNOTATED_COMMIT_REAL) {
2215 12 100         id = git_array_alloc(*ids);
    50          
2216 12 50         GIT_ERROR_CHECK_ALLOC(id);
2217              
2218 12           git_oid_cpy(id, git_commit_id(annotated_commit->commit));
2219             } else {
2220 0 0         for (i = 0; i < annotated_commit->parents.size; i++) {
2221 0 0         id = git_array_alloc(*ids);
    0          
2222 0 0         GIT_ERROR_CHECK_ALLOC(id);
2223              
2224 0           git_oid_cpy(id, &annotated_commit->parents.ptr[i]);
2225             }
2226             }
2227              
2228 12           return 0;
2229             }
2230              
2231 0           static int create_virtual_base(
2232             git_annotated_commit **out,
2233             git_repository *repo,
2234             git_annotated_commit *one,
2235             git_annotated_commit *two,
2236             const git_merge_options *opts,
2237             size_t recursion_level)
2238             {
2239 0           git_annotated_commit *result = NULL;
2240 0           git_index *index = NULL;
2241 0           git_merge_options virtual_opts = GIT_MERGE_OPTIONS_INIT;
2242              
2243             /* Conflicts in the merge base creation do not propagate to conflicts
2244             * in the result; the conflicted base will act as the common ancestor.
2245             */
2246 0 0         if (opts)
2247 0           memcpy(&virtual_opts, opts, sizeof(git_merge_options));
2248              
2249 0           virtual_opts.flags &= ~GIT_MERGE_FAIL_ON_CONFLICT;
2250 0           virtual_opts.flags |= GIT_MERGE__VIRTUAL_BASE;
2251              
2252 0 0         if ((merge_annotated_commits(&index, NULL, repo, one, two,
2253             recursion_level + 1, &virtual_opts)) < 0)
2254 0           return -1;
2255              
2256 0           result = git__calloc(1, sizeof(git_annotated_commit));
2257 0 0         GIT_ERROR_CHECK_ALLOC(result);
2258 0           result->type = GIT_ANNOTATED_COMMIT_VIRTUAL;
2259 0           result->index = index;
2260              
2261 0           insert_head_ids(&result->parents, one);
2262 0           insert_head_ids(&result->parents, two);
2263              
2264 0           *out = result;
2265 0           return 0;
2266             }
2267              
2268 6           static int compute_base(
2269             git_annotated_commit **out,
2270             git_repository *repo,
2271             const git_annotated_commit *one,
2272             const git_annotated_commit *two,
2273             const git_merge_options *given_opts,
2274             size_t recursion_level)
2275             {
2276 6           git_array_oid_t head_ids = GIT_ARRAY_INIT;
2277 6           git_oidarray bases = {0};
2278 6           git_annotated_commit *base = NULL, *other = NULL, *new_base = NULL;
2279 6           git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
2280             size_t i, base_count;
2281             int error;
2282              
2283 6           *out = NULL;
2284              
2285 6 50         if (given_opts)
2286 6           memcpy(&opts, given_opts, sizeof(git_merge_options));
2287              
2288             /* With more than two commits, merge_bases_many finds the base of
2289             * the first commit and a hypothetical merge of the others. Since
2290             * "one" may itself be a virtual commit, which insert_head_ids
2291             * substitutes multiple ancestors for, it needs to be added
2292             * after "two" which is always a single real commit.
2293             */
2294 6 50         if ((error = insert_head_ids(&head_ids, two)) < 0 ||
    50          
2295 6 50         (error = insert_head_ids(&head_ids, one)) < 0 ||
2296 6           (error = git_merge_bases_many(&bases, repo,
2297 6           head_ids.size, head_ids.ptr)) < 0)
2298             goto done;
2299              
2300 6 50         base_count = (opts.flags & GIT_MERGE_NO_RECURSIVE) ? 0 : bases.count;
2301              
2302 6 50         if (base_count)
2303 6           git_oidarray__reverse(&bases);
2304              
2305 6 50         if ((error = git_annotated_commit_lookup(&base, repo, &bases.ids[0])) < 0)
2306 0           goto done;
2307              
2308 6 50         for (i = 1; i < base_count; i++) {
2309 0           recursion_level++;
2310              
2311 0 0         if (opts.recursion_limit && recursion_level > opts.recursion_limit)
    0          
2312 0           break;
2313              
2314 0 0         if ((error = git_annotated_commit_lookup(&other, repo,
2315 0 0         &bases.ids[i])) < 0 ||
2316 0           (error = create_virtual_base(&new_base, repo, base, other, &opts,
2317             recursion_level)) < 0)
2318             goto done;
2319              
2320 0           git_annotated_commit_free(base);
2321 0           git_annotated_commit_free(other);
2322              
2323 0           base = new_base;
2324 0           new_base = NULL;
2325 0           other = NULL;
2326             }
2327              
2328             done:
2329 6 50         if (error == 0)
2330 6           *out = base;
2331             else
2332 0           git_annotated_commit_free(base);
2333              
2334 6           git_annotated_commit_free(other);
2335 6           git_annotated_commit_free(new_base);
2336 6           git_oidarray_free(&bases);
2337 6           git_array_clear(head_ids);
2338 6           return error;
2339             }
2340              
2341 18           static int iterator_for_annotated_commit(
2342             git_iterator **out,
2343             git_annotated_commit *commit)
2344             {
2345 18           git_iterator_options opts = GIT_ITERATOR_OPTIONS_INIT;
2346             int error;
2347              
2348 18           opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
2349              
2350 18 50         if (commit == NULL) {
2351 0           error = git_iterator_for_nothing(out, &opts);
2352 18 50         } else if (commit->type == GIT_ANNOTATED_COMMIT_VIRTUAL) {
2353 0           error = git_iterator_for_index(out, git_index_owner(commit->index), commit->index, &opts);
2354             } else {
2355 18 50         if (!commit->tree &&
    50          
2356 18           (error = git_commit_tree(&commit->tree, commit->commit)) < 0)
2357 0           goto done;
2358              
2359 18           error = git_iterator_for_tree(out, commit->tree, &opts);
2360             }
2361              
2362             done:
2363 18           return error;
2364             }
2365              
2366 6           static int merge_annotated_commits(
2367             git_index **index_out,
2368             git_annotated_commit **base_out,
2369             git_repository *repo,
2370             git_annotated_commit *ours,
2371             git_annotated_commit *theirs,
2372             size_t recursion_level,
2373             const git_merge_options *opts)
2374             {
2375 6           git_annotated_commit *base = NULL;
2376 6           git_iterator *base_iter = NULL, *our_iter = NULL, *their_iter = NULL;
2377             int error;
2378              
2379 6 50         if ((error = compute_base(&base, repo, ours, theirs, opts,
2380             recursion_level)) < 0) {
2381              
2382 0 0         if (error != GIT_ENOTFOUND)
2383 0           goto done;
2384              
2385 0           git_error_clear();
2386             }
2387              
2388 6 50         if ((error = iterator_for_annotated_commit(&base_iter, base)) < 0 ||
    50          
2389 6 50         (error = iterator_for_annotated_commit(&our_iter, ours)) < 0 ||
2390 6 50         (error = iterator_for_annotated_commit(&their_iter, theirs)) < 0 ||
2391 6           (error = git_merge__iterators(index_out, repo, base_iter, our_iter,
2392             their_iter, opts)) < 0)
2393             goto done;
2394              
2395 6 50         if (base_out) {
2396 6           *base_out = base;
2397 6           base = NULL;
2398             }
2399              
2400             done:
2401 6           git_annotated_commit_free(base);
2402 6           git_iterator_free(base_iter);
2403 6           git_iterator_free(our_iter);
2404 6           git_iterator_free(their_iter);
2405 6           return error;
2406             }
2407              
2408              
2409 1           int git_merge_commits(
2410             git_index **out,
2411             git_repository *repo,
2412             const git_commit *our_commit,
2413             const git_commit *their_commit,
2414             const git_merge_options *opts)
2415             {
2416 1           git_annotated_commit *ours = NULL, *theirs = NULL, *base = NULL;
2417 1           int error = 0;
2418              
2419 1 50         if ((error = git_annotated_commit_from_commit(&ours, (git_commit *)our_commit)) < 0 ||
    50          
2420             (error = git_annotated_commit_from_commit(&theirs, (git_commit *)their_commit)) < 0)
2421             goto done;
2422              
2423 1           error = merge_annotated_commits(out, &base, repo, ours, theirs, 0, opts);
2424              
2425             done:
2426 1           git_annotated_commit_free(ours);
2427 1           git_annotated_commit_free(theirs);
2428 1           git_annotated_commit_free(base);
2429 1           return error;
2430             }
2431              
2432             /* Merge setup / cleanup */
2433              
2434 5           static int write_merge_head(
2435             git_repository *repo,
2436             const git_annotated_commit *heads[],
2437             size_t heads_len)
2438             {
2439 5           git_filebuf file = GIT_FILEBUF_INIT;
2440 5           git_buf file_path = GIT_BUF_INIT;
2441             size_t i;
2442 5           int error = 0;
2443              
2444 5 50         assert(repo && heads);
    50          
2445              
2446 5 50         if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_HEAD_FILE)) < 0 ||
    50          
2447 5           (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_MERGE_FILE_MODE)) < 0)
2448             goto cleanup;
2449              
2450 10 100         for (i = 0; i < heads_len; i++) {
2451 5 50         if ((error = git_filebuf_printf(&file, "%s\n", heads[i]->id_str)) < 0)
2452 0           goto cleanup;
2453             }
2454              
2455 5           error = git_filebuf_commit(&file);
2456              
2457             cleanup:
2458 5 50         if (error < 0)
2459 0           git_filebuf_cleanup(&file);
2460              
2461 5           git_buf_dispose(&file_path);
2462              
2463 5           return error;
2464             }
2465              
2466 5           static int write_merge_mode(git_repository *repo)
2467             {
2468 5           git_filebuf file = GIT_FILEBUF_INIT;
2469 5           git_buf file_path = GIT_BUF_INIT;
2470 5           int error = 0;
2471              
2472 5 50         assert(repo);
2473              
2474 5 50         if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MODE_FILE)) < 0 ||
    50          
2475 5           (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_MERGE_FILE_MODE)) < 0)
2476             goto cleanup;
2477              
2478 5 50         if ((error = git_filebuf_write(&file, "no-ff", 5)) < 0)
2479 0           goto cleanup;
2480              
2481 5           error = git_filebuf_commit(&file);
2482              
2483             cleanup:
2484 5 50         if (error < 0)
2485 0           git_filebuf_cleanup(&file);
2486              
2487 5           git_buf_dispose(&file_path);
2488              
2489 5           return error;
2490             }
2491              
2492             struct merge_msg_entry {
2493             const git_annotated_commit *merge_head;
2494             bool written;
2495             };
2496              
2497 5           static int msg_entry_is_branch(
2498             const struct merge_msg_entry *entry,
2499             git_vector *entries)
2500             {
2501             GIT_UNUSED(entries);
2502              
2503 10 50         return (entry->written == 0 &&
2504 5 50         entry->merge_head->remote_url == NULL &&
2505 10 50         entry->merge_head->ref_name != NULL &&
    50          
2506 5           git__strncmp(GIT_REFS_HEADS_DIR, entry->merge_head->ref_name, strlen(GIT_REFS_HEADS_DIR)) == 0);
2507             }
2508              
2509 5           static int msg_entry_is_tracking(
2510             const struct merge_msg_entry *entry,
2511             git_vector *entries)
2512             {
2513             GIT_UNUSED(entries);
2514              
2515 5 0         return (entry->written == 0 &&
2516 0 0         entry->merge_head->remote_url == NULL &&
2517 5 50         entry->merge_head->ref_name != NULL &&
    0          
2518 0           git__strncmp(GIT_REFS_REMOTES_DIR, entry->merge_head->ref_name, strlen(GIT_REFS_REMOTES_DIR)) == 0);
2519             }
2520              
2521 5           static int msg_entry_is_tag(
2522             const struct merge_msg_entry *entry,
2523             git_vector *entries)
2524             {
2525             GIT_UNUSED(entries);
2526              
2527 5 0         return (entry->written == 0 &&
2528 0 0         entry->merge_head->remote_url == NULL &&
2529 5 50         entry->merge_head->ref_name != NULL &&
    0          
2530 0           git__strncmp(GIT_REFS_TAGS_DIR, entry->merge_head->ref_name, strlen(GIT_REFS_TAGS_DIR)) == 0);
2531             }
2532              
2533 5           static int msg_entry_is_remote(
2534             const struct merge_msg_entry *entry,
2535             git_vector *entries)
2536             {
2537 5 50         if (entry->written == 0 &&
    0          
2538 0 0         entry->merge_head->remote_url != NULL &&
2539 0 0         entry->merge_head->ref_name != NULL &&
2540 0           git__strncmp(GIT_REFS_HEADS_DIR, entry->merge_head->ref_name, strlen(GIT_REFS_HEADS_DIR)) == 0)
2541             {
2542             struct merge_msg_entry *existing;
2543              
2544             /* Match only branches from the same remote */
2545 0 0         if (entries->length == 0)
2546 0           return 1;
2547              
2548 0           existing = git_vector_get(entries, 0);
2549              
2550 0           return (git__strcmp(existing->merge_head->remote_url,
2551 0           entry->merge_head->remote_url) == 0);
2552             }
2553              
2554 5           return 0;
2555             }
2556              
2557 5           static int msg_entry_is_oid(
2558             const struct merge_msg_entry *merge_msg_entry)
2559             {
2560 10 50         return (merge_msg_entry->written == 0 &&
2561 10 50         merge_msg_entry->merge_head->ref_name == NULL &&
    0          
2562 0           merge_msg_entry->merge_head->remote_url == NULL);
2563             }
2564              
2565 5           static int merge_msg_entry_written(
2566             const struct merge_msg_entry *merge_msg_entry)
2567             {
2568 5           return (merge_msg_entry->written == 1);
2569             }
2570              
2571 20           static int merge_msg_entries(
2572             git_vector *v,
2573             const struct merge_msg_entry *entries,
2574             size_t len,
2575             int (*match)(const struct merge_msg_entry *entry, git_vector *entries))
2576             {
2577             size_t i;
2578 20           int matches, total = 0;
2579              
2580 20           git_vector_clear(v);
2581              
2582 40 100         for (i = 0; i < len; i++) {
2583 20 50         if ((matches = match(&entries[i], v)) < 0)
2584 0           return matches;
2585 20 100         else if (!matches)
2586 15           continue;
2587              
2588 5           git_vector_insert(v, (struct merge_msg_entry *)&entries[i]);
2589 5           total++;
2590             }
2591              
2592 20           return total;
2593             }
2594              
2595 15           static int merge_msg_write_entries(
2596             git_filebuf *file,
2597             git_vector *entries,
2598             const char *item_name,
2599             const char *item_plural_name,
2600             size_t ref_name_skip,
2601             const char *source,
2602             char sep)
2603             {
2604             struct merge_msg_entry *entry;
2605             size_t i;
2606 15           int error = 0;
2607              
2608 15 100         if (entries->length == 0)
2609 10           return 0;
2610              
2611 5 50         if (sep && (error = git_filebuf_printf(file, "%c ", sep)) < 0)
    0          
2612 0           goto done;
2613              
2614 5 50         if ((error = git_filebuf_printf(file, "%s ",
    50          
2615 5           (entries->length == 1) ? item_name : item_plural_name)) < 0)
2616 0           goto done;
2617              
2618 10 100         git_vector_foreach(entries, i, entry) {
2619 5 50         if (i > 0 &&
    0          
2620 0 0         (error = git_filebuf_printf(file, "%s", (i == entries->length - 1) ? " and " : ", ")) < 0)
2621 0           goto done;
2622              
2623 5 50         if ((error = git_filebuf_printf(file, "'%s'", entry->merge_head->ref_name + ref_name_skip)) < 0)
2624 0           goto done;
2625              
2626 5           entry->written = 1;
2627             }
2628              
2629 5 50         if (source)
2630 0           error = git_filebuf_printf(file, " of %s", source);
2631              
2632             done:
2633 5           return error;
2634             }
2635              
2636 5           static int merge_msg_write_branches(
2637             git_filebuf *file,
2638             git_vector *entries,
2639             char sep)
2640             {
2641 5           return merge_msg_write_entries(file, entries,
2642             "branch", "branches", strlen(GIT_REFS_HEADS_DIR), NULL, sep);
2643             }
2644              
2645 5           static int merge_msg_write_tracking(
2646             git_filebuf *file,
2647             git_vector *entries,
2648             char sep)
2649             {
2650 5           return merge_msg_write_entries(file, entries,
2651             "remote-tracking branch", "remote-tracking branches", 0, NULL, sep);
2652             }
2653              
2654 5           static int merge_msg_write_tags(
2655             git_filebuf *file,
2656             git_vector *entries,
2657             char sep)
2658             {
2659 5           return merge_msg_write_entries(file, entries,
2660             "tag", "tags", strlen(GIT_REFS_TAGS_DIR), NULL, sep);
2661             }
2662              
2663 0           static int merge_msg_write_remotes(
2664             git_filebuf *file,
2665             git_vector *entries,
2666             char sep)
2667             {
2668             const char *source;
2669              
2670 0 0         if (entries->length == 0)
2671 0           return 0;
2672              
2673 0           source = ((struct merge_msg_entry *)entries->contents[0])->merge_head->remote_url;
2674              
2675 0           return merge_msg_write_entries(file, entries,
2676             "branch", "branches", strlen(GIT_REFS_HEADS_DIR), source, sep);
2677             }
2678              
2679 5           static int write_merge_msg(
2680             git_repository *repo,
2681             const git_annotated_commit *heads[],
2682             size_t heads_len)
2683             {
2684 5           git_filebuf file = GIT_FILEBUF_INIT;
2685 5           git_buf file_path = GIT_BUF_INIT;
2686             struct merge_msg_entry *entries;
2687 5           git_vector matching = GIT_VECTOR_INIT;
2688             size_t i;
2689 5           char sep = 0;
2690 5           int error = 0;
2691              
2692 5 50         assert(repo && heads);
    50          
2693              
2694 5           entries = git__calloc(heads_len, sizeof(struct merge_msg_entry));
2695 5 50         GIT_ERROR_CHECK_ALLOC(entries);
2696              
2697 5 50         if (git_vector_init(&matching, heads_len, NULL) < 0) {
2698 0           git__free(entries);
2699 0           return -1;
2700             }
2701              
2702 10 100         for (i = 0; i < heads_len; i++)
2703 5           entries[i].merge_head = heads[i];
2704              
2705 5 50         if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
    50          
2706 5 50         (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_MERGE_FILE_MODE)) < 0 ||
2707             (error = git_filebuf_write(&file, "Merge ", 6)) < 0)
2708             goto cleanup;
2709              
2710             /*
2711             * This is to emulate the format of MERGE_MSG by core git.
2712             *
2713             * Core git will write all the commits specified by OID, in the order
2714             * provided, until the first named branch or tag is reached, at which
2715             * point all branches will be written in the order provided, then all
2716             * tags, then all remote tracking branches and finally all commits that
2717             * were specified by OID that were not already written.
2718             *
2719             * Yes. Really.
2720             */
2721 5 50         for (i = 0; i < heads_len; i++) {
2722 5 50         if (!msg_entry_is_oid(&entries[i]))
2723 5           break;
2724              
2725 0 0         if ((error = git_filebuf_printf(&file,
    0          
2726             "%scommit '%s'", (i > 0) ? "; " : "",
2727 0           entries[i].merge_head->id_str)) < 0)
2728 0           goto cleanup;
2729              
2730 0           entries[i].written = 1;
2731             }
2732              
2733 5 50         if (i)
2734 0           sep = ';';
2735              
2736 5 50         if ((error = merge_msg_entries(&matching, entries, heads_len, msg_entry_is_branch)) < 0 ||
    50          
2737 5           (error = merge_msg_write_branches(&file, &matching, sep)) < 0)
2738             goto cleanup;
2739              
2740 5 50         if (matching.length)
2741 5           sep =',';
2742              
2743 5 50         if ((error = merge_msg_entries(&matching, entries, heads_len, msg_entry_is_tracking)) < 0 ||
    50          
2744 5           (error = merge_msg_write_tracking(&file, &matching, sep)) < 0)
2745             goto cleanup;
2746              
2747 5 50         if (matching.length)
2748 0           sep =',';
2749              
2750 5 50         if ((error = merge_msg_entries(&matching, entries, heads_len, msg_entry_is_tag)) < 0 ||
    50          
2751 5           (error = merge_msg_write_tags(&file, &matching, sep)) < 0)
2752             goto cleanup;
2753              
2754 5 50         if (matching.length)
2755 0           sep =',';
2756              
2757             /* We should never be called with multiple remote branches, but handle
2758             * it in case we are... */
2759 5 50         while ((error = merge_msg_entries(&matching, entries, heads_len, msg_entry_is_remote)) > 0) {
2760 0 0         if ((error = merge_msg_write_remotes(&file, &matching, sep)) < 0)
2761 0           goto cleanup;
2762              
2763 0 0         if (matching.length)
2764 0           sep =',';
2765             }
2766              
2767 5 50         if (error < 0)
2768 0           goto cleanup;
2769              
2770 10 100         for (i = 0; i < heads_len; i++) {
2771 5 50         if (merge_msg_entry_written(&entries[i]))
2772 5           continue;
2773              
2774 0 0         if ((error = git_filebuf_printf(&file, "; commit '%s'",
2775 0           entries[i].merge_head->id_str)) < 0)
2776 0           goto cleanup;
2777             }
2778              
2779 5 50         if ((error = git_filebuf_printf(&file, "\n")) < 0 ||
2780             (error = git_filebuf_commit(&file)) < 0)
2781             goto cleanup;
2782              
2783             cleanup:
2784 5 50         if (error < 0)
2785 0           git_filebuf_cleanup(&file);
2786              
2787 5           git_buf_dispose(&file_path);
2788              
2789 5           git_vector_free(&matching);
2790 5           git__free(entries);
2791              
2792 5           return error;
2793             }
2794              
2795 5           int git_merge__setup(
2796             git_repository *repo,
2797             const git_annotated_commit *our_head,
2798             const git_annotated_commit *heads[],
2799             size_t heads_len)
2800             {
2801 5           int error = 0;
2802              
2803 5 50         assert (repo && our_head && heads);
    50          
    50          
2804              
2805 5 50         if ((error = git_repository__set_orig_head(repo, git_annotated_commit_id(our_head))) == 0 &&
    50          
2806 5 50         (error = write_merge_head(repo, heads, heads_len)) == 0 &&
2807             (error = write_merge_mode(repo)) == 0) {
2808 5           error = write_merge_msg(repo, heads, heads_len);
2809             }
2810              
2811 5           return error;
2812             }
2813              
2814             /* Merge branches */
2815              
2816 5           static int merge_ancestor_head(
2817             git_annotated_commit **ancestor_head,
2818             git_repository *repo,
2819             const git_annotated_commit *our_head,
2820             const git_annotated_commit **their_heads,
2821             size_t their_heads_len)
2822             {
2823             git_oid *oids, ancestor_oid;
2824             size_t i, alloc_len;
2825 5           int error = 0;
2826              
2827 5 50         assert(repo && our_head && their_heads);
    50          
    50          
2828              
2829 5 50         GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, their_heads_len, 1);
    50          
2830 5           oids = git__calloc(alloc_len, sizeof(git_oid));
2831 5 50         GIT_ERROR_CHECK_ALLOC(oids);
2832              
2833 5           git_oid_cpy(&oids[0], git_commit_id(our_head->commit));
2834              
2835 10 100         for (i = 0; i < their_heads_len; i++)
2836 5           git_oid_cpy(&oids[i + 1], git_annotated_commit_id(their_heads[i]));
2837              
2838 5 50         if ((error = git_merge_base_many(&ancestor_oid, repo, their_heads_len + 1, oids)) < 0)
2839 0           goto on_error;
2840              
2841 5           error = git_annotated_commit_lookup(ancestor_head, repo, &ancestor_oid);
2842              
2843             on_error:
2844 5           git__free(oids);
2845 5           return error;
2846             }
2847              
2848 5           const char *merge_their_label(const char *branchname)
2849             {
2850             const char *slash;
2851              
2852 5 50         if ((slash = strrchr(branchname, '/')) == NULL)
2853 0           return branchname;
2854              
2855 5 50         if (*(slash+1) == '\0')
2856 0           return "theirs";
2857              
2858 5           return slash+1;
2859             }
2860              
2861 5           static int merge_normalize_checkout_opts(
2862             git_checkout_options *out,
2863             git_repository *repo,
2864             const git_checkout_options *given_checkout_opts,
2865             unsigned int checkout_strategy,
2866             git_annotated_commit *ancestor,
2867             const git_annotated_commit *our_head,
2868             const git_annotated_commit **their_heads,
2869             size_t their_heads_len)
2870             {
2871 5           git_checkout_options default_checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
2872 5           int error = 0;
2873              
2874             GIT_UNUSED(repo);
2875              
2876 5 50         if (given_checkout_opts != NULL)
2877 5           memcpy(out, given_checkout_opts, sizeof(git_checkout_options));
2878             else
2879 0           memcpy(out, &default_checkout_opts, sizeof(git_checkout_options));
2880              
2881 5           out->checkout_strategy = checkout_strategy;
2882              
2883 5 50         if (!out->ancestor_label) {
2884 5 50         if (ancestor && ancestor->type == GIT_ANNOTATED_COMMIT_REAL)
    50          
2885 5           out->ancestor_label = git_commit_summary(ancestor->commit);
2886 0 0         else if (ancestor)
2887 0           out->ancestor_label = "merged common ancestors";
2888             else
2889 0           out->ancestor_label = "empty base";
2890             }
2891              
2892 5 50         if (!out->our_label) {
2893 5 50         if (our_head && our_head->ref_name)
    50          
2894 5           out->our_label = our_head->ref_name;
2895             else
2896 0           out->our_label = "ours";
2897             }
2898              
2899 5 50         if (!out->their_label) {
2900 5 50         if (their_heads_len == 1 && their_heads[0]->ref_name)
    50          
2901 5           out->their_label = merge_their_label(their_heads[0]->ref_name);
2902 0 0         else if (their_heads_len == 1)
2903 0           out->their_label = their_heads[0]->id_str;
2904             else
2905 0           out->their_label = "theirs";
2906             }
2907              
2908 5           return error;
2909             }
2910              
2911 15           static int merge_check_index(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths)
2912             {
2913 15           git_tree *head_tree = NULL;
2914 15           git_index *index_repo = NULL;
2915 15           git_iterator *iter_repo = NULL, *iter_new = NULL;
2916 15           git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
2917 15           git_diff *staged_diff_list = NULL, *index_diff_list = NULL;
2918             git_diff_delta *delta;
2919 15           git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
2920 15           git_vector staged_paths = GIT_VECTOR_INIT;
2921             size_t i;
2922 15           int error = 0;
2923              
2924             GIT_UNUSED(merged_paths);
2925              
2926 15           *conflicts = 0;
2927              
2928             /* No staged changes may exist unless the change staged is identical to
2929             * the result of the merge. This allows one to apply to merge manually,
2930             * then run merge. Any other staged change would be overwritten by
2931             * a reset merge.
2932             */
2933 15 50         if ((error = git_repository_head_tree(&head_tree, repo)) < 0 ||
    50          
2934 15 50         (error = git_repository_index(&index_repo, repo)) < 0 ||
2935 15           (error = git_diff_tree_to_index(&staged_diff_list, repo, head_tree, index_repo, &opts)) < 0)
2936             goto done;
2937              
2938 15 100         if (staged_diff_list->deltas.length == 0)
2939 12           goto done;
2940              
2941 6 100         git_vector_foreach(&staged_diff_list->deltas, i, delta) {
2942 3 50         if ((error = git_vector_insert(&staged_paths, (char *)delta->new_file.path)) < 0)
2943 0           goto done;
2944             }
2945              
2946 3           iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
2947 3           iter_opts.pathlist.strings = (char **)staged_paths.contents;
2948 3           iter_opts.pathlist.count = staged_paths.length;
2949              
2950 3 50         if ((error = git_iterator_for_index(&iter_repo, repo, index_repo, &iter_opts)) < 0 ||
    50          
2951 3 50         (error = git_iterator_for_index(&iter_new, repo, index_new, &iter_opts)) < 0 ||
2952 3           (error = git_diff__from_iterators(&index_diff_list, repo, iter_repo, iter_new, &opts)) < 0)
2953             goto done;
2954              
2955 3           *conflicts = index_diff_list->deltas.length;
2956              
2957             done:
2958 15           git_tree_free(head_tree);
2959 15           git_index_free(index_repo);
2960 15           git_iterator_free(iter_repo);
2961 15           git_iterator_free(iter_new);
2962 15           git_diff_free(staged_diff_list);
2963 15           git_diff_free(index_diff_list);
2964 15           git_vector_free(&staged_paths);
2965              
2966 15           return error;
2967             }
2968              
2969 15           static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths)
2970             {
2971 15           git_diff *wd_diff_list = NULL;
2972 15           git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
2973 15           int error = 0;
2974              
2975             GIT_UNUSED(index_new);
2976              
2977 15           *conflicts = 0;
2978              
2979             /* We need to have merged at least 1 file for the possibility to exist to
2980             * have conflicts with the workdir. Passing 0 as the pathspec count paramter
2981             * will consider all files in the working directory, that is, we may detect
2982             * a conflict if there were untracked files in the workdir prior to starting
2983             * the merge. This typically happens when cherry-picking a commmit whose
2984             * changes have already been applied.
2985             */
2986 15 100         if (merged_paths->length == 0)
2987 2           return 0;
2988              
2989 13           opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
2990              
2991             /* Workdir changes may exist iff they do not conflict with changes that
2992             * will be applied by the merge (including conflicts). Ensure that there
2993             * are no changes in the workdir to these paths.
2994             */
2995 13           opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
2996 13           opts.pathspec.count = merged_paths->length;
2997 13           opts.pathspec.strings = (char **)merged_paths->contents;
2998 13           opts.ignore_submodules = GIT_SUBMODULE_IGNORE_ALL;
2999              
3000 13 50         if ((error = git_diff_index_to_workdir(&wd_diff_list, repo, NULL, &opts)) < 0)
3001 0           goto done;
3002              
3003 13           *conflicts = wd_diff_list->deltas.length;
3004              
3005             done:
3006 13           git_diff_free(wd_diff_list);
3007              
3008 15           return error;
3009             }
3010              
3011 15           int git_merge__check_result(git_repository *repo, git_index *index_new)
3012             {
3013 15           git_tree *head_tree = NULL;
3014 15           git_iterator *iter_head = NULL, *iter_new = NULL;
3015 15           git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
3016 15           git_diff *merged_list = NULL;
3017 15           git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
3018             git_diff_delta *delta;
3019 15           git_vector paths = GIT_VECTOR_INIT;
3020 15           size_t i, index_conflicts = 0, wd_conflicts = 0, conflicts;
3021             const git_index_entry *e;
3022 15           int error = 0;
3023              
3024 15           iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
3025              
3026 15 50         if ((error = git_repository_head_tree(&head_tree, repo)) < 0 ||
    50          
3027 15 50         (error = git_iterator_for_tree(&iter_head, head_tree, &iter_opts)) < 0 ||
3028 15 50         (error = git_iterator_for_index(&iter_new, repo, index_new, &iter_opts)) < 0 ||
3029 15           (error = git_diff__from_iterators(&merged_list, repo, iter_head, iter_new, &opts)) < 0)
3030             goto done;
3031              
3032 27 100         git_vector_foreach(&merged_list->deltas, i, delta) {
3033 12 50         if ((error = git_vector_insert(&paths, (char *)delta->new_file.path)) < 0)
3034 0           goto done;
3035             }
3036              
3037 54 100         for (i = 0; i < git_index_entrycount(index_new); i++) {
3038 39           e = git_index_get_byindex(index_new, i);
3039              
3040 50           if (git_index_entry_is_conflict(e) &&
3041 21 50         (git_vector_last(&paths) == NULL ||
3042 10           strcmp(git_vector_last(&paths), e->path) != 0)) {
3043              
3044 1 50         if ((error = git_vector_insert(&paths, (char *)e->path)) < 0)
3045 0           goto done;
3046             }
3047             }
3048              
3049             /* Make sure the index and workdir state do not prevent merging */
3050 15 50         if ((error = merge_check_index(&index_conflicts, repo, index_new, &paths)) < 0 ||
    50          
3051             (error = merge_check_workdir(&wd_conflicts, repo, index_new, &paths)) < 0)
3052             goto done;
3053              
3054 15 100         if ((conflicts = index_conflicts + wd_conflicts) > 0) {
3055 1 50         git_error_set(GIT_ERROR_MERGE, "%" PRIuZ " uncommitted change%s would be overwritten by merge",
3056             conflicts, (conflicts != 1) ? "s" : "");
3057 1           error = GIT_ECONFLICT;
3058             }
3059              
3060             done:
3061 15           git_vector_free(&paths);
3062 15           git_tree_free(head_tree);
3063 15           git_iterator_free(iter_head);
3064 15           git_iterator_free(iter_new);
3065 15           git_diff_free(merged_list);
3066              
3067 15           return error;
3068             }
3069              
3070 11           int git_merge__append_conflicts_to_merge_msg(
3071             git_repository *repo,
3072             git_index *index)
3073             {
3074 11           git_filebuf file = GIT_FILEBUF_INIT;
3075 11           git_buf file_path = GIT_BUF_INIT;
3076 11           const char *last = NULL;
3077             size_t i;
3078             int error;
3079              
3080 11 100         if (!git_index_has_conflicts(index))
3081 8           return 0;
3082              
3083 3 50         if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
    50          
3084 3           (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_APPEND, GIT_MERGE_FILE_MODE)) < 0)
3085             goto cleanup;
3086              
3087 3           git_filebuf_printf(&file, "\nConflicts:\n");
3088              
3089 14 100         for (i = 0; i < git_index_entrycount(index); i++) {
3090 11           const git_index_entry *e = git_index_get_byindex(index, i);
3091              
3092 11 100         if (!git_index_entry_is_conflict(e))
3093 2           continue;
3094              
3095 9 100         if (last == NULL || strcmp(e->path, last) != 0)
    50          
3096 3           git_filebuf_printf(&file, "\t%s\n", e->path);
3097              
3098 9           last = e->path;
3099             }
3100              
3101 3           error = git_filebuf_commit(&file);
3102              
3103             cleanup:
3104 3 50         if (error < 0)
3105 0           git_filebuf_cleanup(&file);
3106              
3107 3           git_buf_dispose(&file_path);
3108              
3109 11           return error;
3110             }
3111              
3112 0           static int merge_state_cleanup(git_repository *repo)
3113             {
3114 0           const char *state_files[] = {
3115             GIT_MERGE_HEAD_FILE,
3116             GIT_MERGE_MODE_FILE,
3117             GIT_MERGE_MSG_FILE,
3118             };
3119              
3120 0           return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files));
3121             }
3122              
3123 5           static int merge_heads(
3124             git_annotated_commit **ancestor_head_out,
3125             git_annotated_commit **our_head_out,
3126             git_repository *repo,
3127             git_reference *our_ref,
3128             const git_annotated_commit **their_heads,
3129             size_t their_heads_len)
3130             {
3131 5           git_annotated_commit *ancestor_head = NULL, *our_head = NULL;
3132 5           int error = 0;
3133              
3134 5           *ancestor_head_out = NULL;
3135 5           *our_head_out = NULL;
3136              
3137 5 50         if ((error = git_annotated_commit_from_ref(&our_head, repo, our_ref)) < 0)
3138 0           goto done;
3139              
3140 5 50         if ((error = merge_ancestor_head(&ancestor_head, repo, our_head, their_heads, their_heads_len)) < 0) {
3141 0 0         if (error != GIT_ENOTFOUND)
3142 0           goto done;
3143              
3144 0           git_error_clear();
3145 0           error = 0;
3146             }
3147              
3148 5           *ancestor_head_out = ancestor_head;
3149 5           *our_head_out = our_head;
3150              
3151             done:
3152 5 50         if (error < 0) {
3153 0           git_annotated_commit_free(ancestor_head);
3154 0           git_annotated_commit_free(our_head);
3155             }
3156              
3157 5           return error;
3158             }
3159              
3160 5           static int merge_preference(git_merge_preference_t *out, git_repository *repo)
3161             {
3162             git_config *config;
3163             const char *value;
3164 5           int bool_value, error = 0;
3165              
3166 5           *out = GIT_MERGE_PREFERENCE_NONE;
3167              
3168 5 50         if ((error = git_repository_config_snapshot(&config, repo)) < 0)
3169 0           goto done;
3170              
3171 5 50         if ((error = git_config_get_string(&value, config, "merge.ff")) < 0) {
3172 5 50         if (error == GIT_ENOTFOUND) {
3173 5           git_error_clear();
3174 5           error = 0;
3175             }
3176              
3177 5           goto done;
3178             }
3179              
3180 0 0         if (git_config_parse_bool(&bool_value, value) == 0) {
3181 0 0         if (!bool_value)
3182 0           *out |= GIT_MERGE_PREFERENCE_NO_FASTFORWARD;
3183             } else {
3184 0 0         if (strcasecmp(value, "only") == 0)
3185 0           *out |= GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY;
3186             }
3187              
3188             done:
3189 5           git_config_free(config);
3190 5           return error;
3191             }
3192              
3193 5           int git_merge_analysis_for_ref(
3194             git_merge_analysis_t *analysis_out,
3195             git_merge_preference_t *preference_out,
3196             git_repository *repo,
3197             git_reference *our_ref,
3198             const git_annotated_commit **their_heads,
3199             size_t their_heads_len)
3200             {
3201 5           git_annotated_commit *ancestor_head = NULL, *our_head = NULL;
3202 5           int error = 0;
3203             bool unborn;
3204              
3205 5 50         assert(analysis_out && preference_out && repo && their_heads && their_heads_len > 0);
    50          
    50          
    50          
    50          
3206              
3207 5 50         if (their_heads_len != 1) {
3208 0           git_error_set(GIT_ERROR_MERGE, "can only merge a single branch");
3209 0           error = -1;
3210 0           goto done;
3211             }
3212              
3213 5           *analysis_out = GIT_MERGE_ANALYSIS_NONE;
3214              
3215 5 50         if ((error = merge_preference(preference_out, repo)) < 0)
3216 0           goto done;
3217              
3218 5 50         if ((error = git_reference__is_unborn_head(&unborn, our_ref, repo)) < 0)
3219 0           goto done;
3220              
3221 5 50         if (unborn) {
3222 0           *analysis_out |= GIT_MERGE_ANALYSIS_FASTFORWARD | GIT_MERGE_ANALYSIS_UNBORN;
3223 0           error = 0;
3224 0           goto done;
3225             }
3226              
3227 5 50         if ((error = merge_heads(&ancestor_head, &our_head, repo, our_ref, their_heads, their_heads_len)) < 0)
3228 0           goto done;
3229              
3230             /* We're up-to-date if we're trying to merge our own common ancestor. */
3231 5 50         if (ancestor_head && git_oid_equal(
    100          
3232             git_annotated_commit_id(ancestor_head), git_annotated_commit_id(their_heads[0])))
3233 1           *analysis_out |= GIT_MERGE_ANALYSIS_UP_TO_DATE;
3234              
3235             /* We're fastforwardable if we're our own common ancestor. */
3236 4 50         else if (ancestor_head && git_oid_equal(
    100          
3237             git_annotated_commit_id(ancestor_head), git_annotated_commit_id(our_head)))
3238 1           *analysis_out |= GIT_MERGE_ANALYSIS_FASTFORWARD | GIT_MERGE_ANALYSIS_NORMAL;
3239              
3240             /* Otherwise, just a normal merge is possible. */
3241             else
3242 3           *analysis_out |= GIT_MERGE_ANALYSIS_NORMAL;
3243              
3244             done:
3245 5           git_annotated_commit_free(ancestor_head);
3246 5           git_annotated_commit_free(our_head);
3247 5           return error;
3248             }
3249              
3250 5           int git_merge_analysis(
3251             git_merge_analysis_t *analysis_out,
3252             git_merge_preference_t *preference_out,
3253             git_repository *repo,
3254             const git_annotated_commit **their_heads,
3255             size_t their_heads_len)
3256             {
3257 5           git_reference *head_ref = NULL;
3258 5           int error = 0;
3259              
3260 5 50         if ((error = git_reference_lookup(&head_ref, repo, GIT_HEAD_FILE)) < 0) {
3261 0           git_error_set(GIT_ERROR_MERGE, "failed to lookup HEAD reference");
3262 0           return error;
3263             }
3264              
3265 5           error = git_merge_analysis_for_ref(analysis_out, preference_out, repo, head_ref, their_heads, their_heads_len);
3266              
3267 5           git_reference_free(head_ref);
3268              
3269 5           return error;
3270             }
3271              
3272 5           int git_merge(
3273             git_repository *repo,
3274             const git_annotated_commit **their_heads,
3275             size_t their_heads_len,
3276             const git_merge_options *merge_opts,
3277             const git_checkout_options *given_checkout_opts)
3278             {
3279 5           git_reference *our_ref = NULL;
3280             git_checkout_options checkout_opts;
3281 5           git_annotated_commit *our_head = NULL, *base = NULL;
3282 5           git_index *repo_index = NULL, *index = NULL;
3283 5           git_indexwriter indexwriter = GIT_INDEXWRITER_INIT;
3284             unsigned int checkout_strategy;
3285 5           int error = 0;
3286              
3287 5 50         assert(repo && their_heads && their_heads_len > 0);
    50          
    50          
3288              
3289 5 50         if (their_heads_len != 1) {
3290 0           git_error_set(GIT_ERROR_MERGE, "can only merge a single branch");
3291 0           return -1;
3292             }
3293              
3294 5 50         if ((error = git_repository__ensure_not_bare(repo, "merge")) < 0)
3295 0           goto done;
3296              
3297 5           checkout_strategy = given_checkout_opts ?
3298 5 50         given_checkout_opts->checkout_strategy :
3299             GIT_CHECKOUT_SAFE;
3300              
3301 5 50         if ((error = git_indexwriter_init_for_operation(&indexwriter, repo,
3302             &checkout_strategy)) < 0)
3303 0           goto done;
3304              
3305 10           if ((error = git_repository_index(&repo_index, repo) < 0) ||
3306 5           (error = git_index_read(repo_index, 0) < 0))
3307             goto done;
3308              
3309             /* Write the merge setup files to the repository. */
3310 5 50         if ((error = git_annotated_commit_from_head(&our_head, repo)) < 0 ||
    50          
3311 5           (error = git_merge__setup(repo, our_head, their_heads,
3312             their_heads_len)) < 0)
3313             goto done;
3314              
3315             /* TODO: octopus */
3316              
3317 5 50         if ((error = merge_annotated_commits(&index, &base, repo, our_head,
3318 5 50         (git_annotated_commit *)their_heads[0], 0, merge_opts)) < 0 ||
3319 5 50         (error = git_merge__check_result(repo, index)) < 0 ||
3320 5           (error = git_merge__append_conflicts_to_merge_msg(repo, index)) < 0)
3321             goto done;
3322              
3323             /* check out the merge results */
3324              
3325 5 50         if ((error = merge_normalize_checkout_opts(&checkout_opts, repo,
3326             given_checkout_opts, checkout_strategy,
3327 5 50         base, our_head, their_heads, their_heads_len)) < 0 ||
3328 5           (error = git_checkout_index(repo, index, &checkout_opts)) < 0)
3329             goto done;
3330              
3331 5           error = git_indexwriter_commit(&indexwriter);
3332              
3333             done:
3334 5 50         if (error < 0)
3335 0           merge_state_cleanup(repo);
3336              
3337 5           git_indexwriter_cleanup(&indexwriter);
3338 5           git_index_free(index);
3339 5           git_annotated_commit_free(our_head);
3340 5           git_annotated_commit_free(base);
3341 5           git_reference_free(our_ref);
3342 5           git_index_free(repo_index);
3343              
3344 5           return error;
3345             }
3346              
3347 0           int git_merge_options_init(git_merge_options *opts, unsigned int version)
3348             {
3349 0 0         GIT_INIT_STRUCTURE_FROM_TEMPLATE(
3350             opts, version, git_merge_options, GIT_MERGE_OPTIONS_INIT);
3351 0           return 0;
3352             }
3353              
3354 0           int git_merge_init_options(git_merge_options *opts, unsigned int version)
3355             {
3356 0           return git_merge_options_init(opts, version);
3357             }
3358              
3359 0           int git_merge_file_input_init(git_merge_file_input *input, unsigned int version)
3360             {
3361 0 0         GIT_INIT_STRUCTURE_FROM_TEMPLATE(
3362             input, version, git_merge_file_input, GIT_MERGE_FILE_INPUT_INIT);
3363 0           return 0;
3364             }
3365              
3366 0           int git_merge_file_init_input(git_merge_file_input *input, unsigned int version)
3367             {
3368 0           return git_merge_file_input_init(input, version);
3369             }
3370              
3371 0           int git_merge_file_options_init(
3372             git_merge_file_options *opts, unsigned int version)
3373             {
3374 0 0         GIT_INIT_STRUCTURE_FROM_TEMPLATE(
3375             opts, version, git_merge_file_options, GIT_MERGE_FILE_OPTIONS_INIT);
3376 0           return 0;
3377             }
3378              
3379 0           int git_merge_file_init_options(
3380             git_merge_file_options *opts, unsigned int version)
3381             {
3382 0           return git_merge_file_options_init(opts, version);
3383             }