merge.c 81.3 KB
Newer Older
Edward Thomson committed
1
/*
Edward Thomson committed
2
 * Copyright (C) the libgit2 contributors. All rights reserved.
Edward Thomson committed
3 4 5 6 7
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */

Edward Thomson committed
8 9 10
#include "common.h"
#include "posix.h"
#include "buffer.h"
Edward Thomson committed
11
#include "repository.h"
12
#include "revwalk.h"
Edward Thomson committed
13
#include "commit_list.h"
Edward Thomson committed
14
#include "merge.h"
Edward Thomson committed
15
#include "path.h"
Edward Thomson committed
16
#include "refs.h"
Edward Thomson committed
17 18 19 20
#include "object.h"
#include "iterator.h"
#include "refs.h"
#include "diff.h"
21 22
#include "diff_generate.h"
#include "diff_tform.h"
Edward Thomson committed
23 24 25
#include "checkout.h"
#include "tree.h"
#include "blob.h"
Edward Thomson committed
26
#include "oid.h"
27 28
#include "index.h"
#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"
Edward Thomson committed
35 36

#include "git2/types.h"
Edward Thomson committed
37
#include "git2/repository.h"
Edward Thomson committed
38 39
#include "git2/object.h"
#include "git2/commit.h"
Edward Thomson committed
40
#include "git2/merge.h"
Edward Thomson committed
41
#include "git2/refs.h"
Edward Thomson committed
42
#include "git2/reset.h"
Edward Thomson committed
43 44 45 46
#include "git2/checkout.h"
#include "git2/signature.h"
#include "git2/config.h"
#include "git2/tree.h"
47
#include "git2/oidarray.h"
48
#include "git2/annotated_commit.h"
49
#include "git2/sys/index.h"
50
#include "git2/sys/hashsig.h"
Edward Thomson committed
51 52

#define GIT_MERGE_INDEX_ENTRY_EXISTS(X)	((X).mode != 0)
Edward Thomson committed
53
#define GIT_MERGE_INDEX_ENTRY_ISFILE(X) S_ISREG((X).mode)
Edward Thomson committed
54

55

Edward Thomson committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
typedef enum {
	TREE_IDX_ANCESTOR = 0,
	TREE_IDX_OURS = 1,
	TREE_IDX_THEIRS = 2
} merge_tree_index_t;

/* Tracks D/F conflicts */
struct merge_diff_df_data {
	const char *df_path;
	const char *prev_path;
	git_merge_diff *prev_conflict;
};

/* Merge base computation */

71
int merge_bases_many(git_commit_list **out, git_revwalk **walk_out, git_repository *repo, size_t length, const git_oid input_array[])
72
{
73
	git_revwalk *walk = NULL;
74 75
	git_vector list;
	git_commit_list *result = NULL;
76
	git_commit_list_node *commit;
77 78 79 80
	int error = -1;
	unsigned int i;

	if (length < 2) {
81
		giterr_set(GITERR_INVALID, "at least two commits are required to find an ancestor");
82 83 84 85 86 87 88
		return -1;
	}

	if (git_vector_init(&list, length - 1, NULL) < 0)
		return -1;

	if (git_revwalk_new(&walk, repo) < 0)
89
		goto on_error;
90 91

	for (i = 1; i < length; i++) {
92
		commit = git_revwalk__commit_lookup(walk, &input_array[i]);
93
		if (commit == NULL)
94
			goto on_error;
95 96 97 98

		git_vector_insert(&list, commit);
	}

99
	commit = git_revwalk__commit_lookup(walk, &input_array[0]);
100
	if (commit == NULL)
101
		goto on_error;
102 103

	if (git_merge__bases_many(&result, walk, commit, &list) < 0)
104
		goto on_error;
105 106

	if (!result) {
107
		giterr_set(GITERR_MERGE, "no merge base found");
108
		error = GIT_ENOTFOUND;
109
		goto on_error;
110 111
	}

112 113
	*out = result;
	*walk_out = walk;
114

115 116
	git_vector_free(&list);
	return 0;
117

118
on_error:
119
	git_vector_free(&list);
120
	git_revwalk_free(walk);
121 122 123
	return error;
}

124
int git_merge_base_many(git_oid *out, git_repository *repo, size_t length, const git_oid input_array[])
125 126
{
	git_revwalk *walk;
127 128
	git_commit_list *result = NULL;
	int error = 0;
129 130 131

	assert(out && repo && input_array);

132 133
	if ((error = merge_bases_many(&result, &walk, repo, length, input_array)) < 0)
		return error;
134

135
	git_oid_cpy(out, &result->item->oid);
136

137 138
	git_commit_list_free(&result);
	git_revwalk_free(walk);
139

140 141
	return 0;
}
142

143 144 145 146 147 148
int git_merge_bases_many(git_oidarray *out, git_repository *repo, size_t length, const git_oid input_array[])
{
	git_revwalk *walk;
	git_commit_list *list, *result = NULL;
	int error = 0;
	git_array_oid_t array;
149

150
	assert(out && repo && input_array);
151

152 153
	if ((error = merge_bases_many(&result, &walk, repo, length, input_array)) < 0)
		return error;
154 155 156

	git_array_init(array);

157 158
	list = result;
	while (list) {
159
		git_oid *id = git_array_alloc(array);
160 161
		if (id == NULL) {
			error = -1;
162
			goto cleanup;
163
		}
164

165 166
		git_oid_cpy(id, &list->item->oid);
		list = list->next;
167 168 169 170 171 172 173
	}

	git_oidarray__from_array(out, &array);

cleanup:
	git_commit_list_free(&result);
	git_revwalk_free(walk);
174

175 176 177
	return error;
}

178 179 180 181 182 183 184 185 186
int git_merge_base_octopus(git_oid *out, git_repository *repo, size_t length, const git_oid input_array[])
{
	git_oid result;
	unsigned int i;
	int error = -1;

	assert(out && repo && input_array);

	if (length < 2) {
187
		giterr_set(GITERR_INVALID, "at least two commits are required to find an ancestor");
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
		return -1;
	}

	result = input_array[0];
	for (i = 1; i < length; i++) {
		error = git_merge_base(&result, repo, &result, &input_array[i]);
		if (error < 0)
			return error;
	}

	*out = result;

	return 0;
}

203
static int merge_bases(git_commit_list **out, git_revwalk **walk_out, git_repository *repo, const git_oid *one, const git_oid *two)
204 205 206 207 208 209 210 211 212 213
{
	git_revwalk *walk;
	git_vector list;
	git_commit_list *result = NULL;
	git_commit_list_node *commit;
	void *contents[1];

	if (git_revwalk_new(&walk, repo) < 0)
		return -1;

214
	commit = git_revwalk__commit_lookup(walk, two);
215 216 217 218 219 220 221 222 223
	if (commit == NULL)
		goto on_error;

	/* This is just one value, so we can do it on the stack */
	memset(&list, 0x0, sizeof(git_vector));
	contents[0] = commit;
	list.length = 1;
	list.contents = contents;

224
	commit = git_revwalk__commit_lookup(walk, one);
225 226 227 228 229 230 231 232
	if (commit == NULL)
		goto on_error;

	if (git_merge__bases_many(&result, walk, commit, &list) < 0)
		goto on_error;

	if (!result) {
		git_revwalk_free(walk);
233
		giterr_set(GITERR_MERGE, "no merge base found");
234 235 236
		return GIT_ENOTFOUND;
	}

237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
	*out = result;
	*walk_out = walk;

	return 0;

on_error:
	git_revwalk_free(walk);
	return -1;

}

int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const git_oid *two)
{
	int error;
	git_revwalk *walk;
	git_commit_list *result;

	if ((error = merge_bases(&result, &walk, repo, one, two)) < 0)
		return error;

257 258 259 260 261
	git_oid_cpy(out, &result->item->oid);
	git_commit_list_free(&result);
	git_revwalk_free(walk);

	return 0;
262 263 264 265 266
}

int git_merge_bases(git_oidarray *out, git_repository *repo, const git_oid *one, const git_oid *two)
{
	int error;
267
	git_revwalk *walk;
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
	git_commit_list *result, *list;
	git_array_oid_t array;

	git_array_init(array);

	if ((error = merge_bases(&result, &walk, repo, one, two)) < 0)
		return error;

	list = result;
	while (list) {
		git_oid *id = git_array_alloc(array);
		if (id == NULL)
			goto on_error;

		git_oid_cpy(id, &list->item->oid);
		list = list->next;
	}

	git_oidarray__from_array(out, &array);
	git_commit_list_free(&result);
	git_revwalk_free(walk);

	return 0;
291 292

on_error:
293
	git_commit_list_free(&result);
294 295 296 297 298 299
	git_revwalk_free(walk);
	return -1;
}

static int interesting(git_pqueue *list)
{
300 301 302 303
	size_t i;

	for (i = 0; i < git_pqueue_size(list); i++) {
		git_commit_list_node *commit = git_pqueue_get(list, i);
304 305 306 307 308 309 310
		if ((commit->flags & STALE) == 0)
			return 1;
	}

	return 0;
}

311 312
static void clear_commit_marks_1(git_commit_list **plist,
		git_commit_list_node *commit, unsigned int mark)
313
{
314 315
	while (commit) {
		unsigned int i;
316

317 318 319 320 321 322 323 324 325 326
		if (!(mark & commit->flags))
			return;

		commit->flags &= ~mark;

		for (i = 1; i < commit->out_degree; i++) {
			git_commit_list_node *p = commit->parents[i];
			git_commit_list_insert(p, plist);
		}

327
		commit = commit->out_degree ? commit->parents[0] : NULL;
328
	}
329
}
330

331 332 333 334 335 336 337 338
static void clear_commit_marks_many(git_vector *commits, unsigned int mark)
{
	git_commit_list *list = NULL;
	git_commit_list_node *c;
	unsigned int i;

	git_vector_foreach(commits, i, c) {
		git_commit_list_insert(c, &list);
339 340
	}

341 342 343
	while (list)
		clear_commit_marks_1(&list, git_commit_list_pop(&list), mark);
}
344

345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
static void clear_commit_marks(git_commit_list_node *commit, unsigned int mark)
{
	git_commit_list *list = NULL;
	git_commit_list_insert(commit, &list);
	while (list)
		clear_commit_marks_1(&list, git_commit_list_pop(&list), mark);
}

static int paint_down_to_common(
	git_commit_list **out, git_revwalk *walk, git_commit_list_node *one, git_vector *twos)
{
	git_pqueue list;
	git_commit_list *result = NULL;
	git_commit_list_node *two;

	int error;
	unsigned int i;

	if (git_pqueue_init(&list, 0, twos->length * 2, git_commit_list_time_cmp) < 0)
Edward Thomson committed
364
		return -1;
365 366 367 368 369 370

	one->flags |= PARENT1;
	if (git_pqueue_insert(&list, one) < 0)
		return -1;

	git_vector_foreach(twos, i, two) {
371 372 373
		if (git_commit_list_parse(walk, two) < 0)
			return -1;

374
		two->flags |= PARENT2;
375

376 377 378 379 380 381
		if (git_pqueue_insert(&list, two) < 0)
			return -1;
	}

	/* as long as there are non-STALE commits */
	while (interesting(&list)) {
382
		git_commit_list_node *commit = git_pqueue_pop(&list);
383 384
		int flags;

385 386
		if (commit == NULL)
			break;
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413

		flags = commit->flags & (PARENT1 | PARENT2 | STALE);
		if (flags == (PARENT1 | PARENT2)) {
			if (!(commit->flags & RESULT)) {
				commit->flags |= RESULT;
				if (git_commit_list_insert(commit, &result) == NULL)
					return -1;
			}
			/* we mark the parents of a merge stale */
			flags |= STALE;
		}

		for (i = 0; i < commit->out_degree; i++) {
			git_commit_list_node *p = commit->parents[i];
			if ((p->flags & flags) == flags)
				continue;

			if ((error = git_commit_list_parse(walk, p)) < 0)
				return error;

			p->flags |= flags;
			if (git_pqueue_insert(&list, p) < 0)
				return -1;
		}
	}

	git_pqueue_free(&list);
414 415 416 417 418 419 420 421 422 423 424 425 426
	*out = result;
	return 0;
}

static int remove_redundant(git_revwalk *walk, git_vector *commits)
{
	git_vector work = GIT_VECTOR_INIT;
	unsigned char *redundant;
	unsigned int *filled_index;
	unsigned int i, j;
	int error = 0;

	redundant = git__calloc(commits->length, 1);
Vicent Marti committed
427
	GITERR_CHECK_ALLOC(redundant);
428
	filled_index = git__calloc((commits->length - 1), sizeof(unsigned int));
Vicent Marti committed
429
	GITERR_CHECK_ALLOC(filled_index);
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509

	for (i = 0; i < commits->length; ++i) {
		if ((error = git_commit_list_parse(walk, commits->contents[i])) < 0)
			goto done;
	}

	for (i = 0; i < commits->length; ++i) {
		git_commit_list *common = NULL;
		git_commit_list_node *commit = commits->contents[i];

		if (redundant[i])
			continue;

		git_vector_clear(&work);

		for (j = 0; j < commits->length; j++) {
			if (i == j || redundant[j])
				continue;

			filled_index[work.length] = j;
			if ((error = git_vector_insert(&work, commits->contents[j])) < 0)
				goto done;
		}

		error = paint_down_to_common(&common, walk, commit, &work);
		if (error < 0)
			goto done;

		if (commit->flags & PARENT2)
			redundant[i] = 1;

		for (j = 0; j < work.length; j++) {
			git_commit_list_node *w = work.contents[j];
			if (w->flags & PARENT1)
				redundant[filled_index[j]] = 1;
		}

		clear_commit_marks(commit, ALL_FLAGS);
		clear_commit_marks_many(&work, ALL_FLAGS);

		git_commit_list_free(&common);
	}

	for (i = 0; i < commits->length; ++i) {
		if (redundant[i])
			commits->contents[i] = NULL;
	}

done:
	git__free(redundant);
	git__free(filled_index);
	git_vector_free(&work);
	return error;
}

int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_list_node *one, git_vector *twos)
{
	int error;
	unsigned int i;
	git_commit_list_node *two;
	git_commit_list *result = NULL, *tmp = NULL;

	/* If there's only the one commit, there can be no merge bases */
	if (twos->length == 0) {
		*out = NULL;
		return 0;
	}

	/* if the commit is repeated, we have a our merge base already */
	git_vector_foreach(twos, i, two) {
		if (one == two)
			return git_commit_list_insert(one, out) ? 0 : -1;
	}

	if (git_commit_list_parse(walk, one) < 0)
		return -1;

	error = paint_down_to_common(&result, walk, one, twos);
	if (error < 0)
		return error;
510 511 512 513 514 515

	/* filter out any stale commits in the results */
	tmp = result;
	result = NULL;

	while (tmp) {
516 517 518
		git_commit_list_node *c = git_commit_list_pop(&tmp);
		if (!(c->flags & STALE))
			if (git_commit_list_insert_by_date(c, &result) == NULL)
519
				return -1;
520 521
	}

Vicent Marti committed
522 523 524 525
	/*
	 * more than one merge base -- see if there are redundant merge
	 * bases and remove them
	 */
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
	if (result && result->next) {
		git_vector redundant = GIT_VECTOR_INIT;

		while (result)
			git_vector_insert(&redundant, git_commit_list_pop(&result));

		clear_commit_marks(one, ALL_FLAGS);
		clear_commit_marks_many(twos, ALL_FLAGS);

		if ((error = remove_redundant(walk, &redundant)) < 0) {
			git_vector_free(&redundant);
			return error;
		}

		git_vector_foreach(&redundant, i, two) {
			if (two != NULL)
				git_commit_list_insert_by_date(two, &result);
		}
544

545
		git_vector_free(&redundant);
546 547 548 549 550
	}

	*out = result;
	return 0;
}
551

552 553
int git_repository_mergehead_foreach(
	git_repository *repo,
554 555 556 557 558 559 560 561 562 563 564
	git_repository_mergehead_foreach_cb cb,
	void *payload)
{
	git_buf merge_head_path = GIT_BUF_INIT, merge_head_file = GIT_BUF_INIT;
	char *buffer, *line;
	size_t line_num = 1;
	git_oid oid;
	int error = 0;

	assert(repo && cb);

565
	if ((error = git_buf_joinpath(&merge_head_path, repo->gitdir,
566 567 568 569 570 571 572 573 574 575 576
		GIT_MERGE_HEAD_FILE)) < 0)
		return error;

	if ((error = git_futils_readbuffer(&merge_head_file,
		git_buf_cstr(&merge_head_path))) < 0)
		goto cleanup;

	buffer = merge_head_file.ptr;

	while ((line = git__strsep(&buffer, "\n")) != NULL) {
		if (strlen(line) != GIT_OID_HEXSZ) {
577
			giterr_set(GITERR_INVALID, "unable to parse OID - invalid length");
578 579 580 581 582 583 584
			error = -1;
			goto cleanup;
		}

		if ((error = git_oid_fromstr(&oid, line)) < 0)
			goto cleanup;

585
		if ((error = cb(&oid, payload)) != 0) {
586
			giterr_set_after_callback(error);
587 588 589 590 591 592 593
			goto cleanup;
		}

		++line_num;
	}

	if (*buffer) {
594
		giterr_set(GITERR_MERGE, "no EOL at line %"PRIuZ, line_num);
595 596 597 598 599 600 601 602 603 604
		error = -1;
		goto cleanup;
	}

cleanup:
	git_buf_free(&merge_head_path);
	git_buf_free(&merge_head_file);

	return error;
}
Edward Thomson committed
605 606 607 608 609 610 611 612 613

GIT_INLINE(int) index_entry_cmp(const git_index_entry *a, const git_index_entry *b)
{
	int value = 0;

	if (a->path == NULL)
		return (b->path == NULL) ? 0 : 1;

	if ((value = a->mode - b->mode) == 0 &&
614
		(value = git_oid__cmp(&a->id, &b->id)) == 0)
Edward Thomson committed
615 616 617 618 619 620 621 622 623 624 625 626
		value = strcmp(a->path, b->path);

	return value;
}

/* Conflict resolution */

static int merge_conflict_resolve_trivial(
	int *resolved,
	git_merge_diff_list *diff_list,
	const git_merge_diff *conflict)
{
627
	int ours_empty, theirs_empty;
Edward Thomson committed
628 629 630 631 632 633 634 635 636 637 638
	int ours_changed, theirs_changed, ours_theirs_differ;
	git_index_entry const *result = NULL;
	int error = 0;

	assert(resolved && diff_list && conflict);

	*resolved = 0;

	if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE ||
		conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
		return 0;
nulltoken committed
639

Edward Thomson committed
640 641 642 643 644 645
	if (conflict->our_status == GIT_DELTA_RENAMED ||
		conflict->their_status == GIT_DELTA_RENAMED)
		return 0;

	ours_empty = !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry);
	theirs_empty = !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry);
nulltoken committed
646

Edward Thomson committed
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701
	ours_changed = (conflict->our_status != GIT_DELTA_UNMODIFIED);
	theirs_changed = (conflict->their_status != GIT_DELTA_UNMODIFIED);
	ours_theirs_differ = ours_changed && theirs_changed &&
		index_entry_cmp(&conflict->our_entry, &conflict->their_entry);

	/*
	 * Note: with only one ancestor, some cases are not distinct:
	 *
	 * 16: ancest:anc1/anc2, head:anc1, remote:anc2 = result:no merge
	 * 3: ancest:(empty)^, head:head, remote:(empty) = result:no merge
	 * 2: ancest:(empty)^, head:(empty), remote:remote = result:no merge
	 *
	 * Note that the two cases that take D/F conflicts into account
	 * specifically do not need to be explicitly tested, as D/F conflicts
	 * would fail the *empty* test:
	 *
	 * 3ALT: ancest:(empty)+, head:head, remote:*empty* = result:head
	 * 2ALT: ancest:(empty)+, head:*empty*, remote:remote = result:remote
	 *
	 * Note that many of these cases need not be explicitly tested, as
	 * they simply degrade to "all different" cases (eg, 11):
	 *
	 * 4: ancest:(empty)^, head:head, remote:remote = result:no merge
	 * 7: ancest:ancest+, head:(empty), remote:remote = result:no merge
	 * 9: ancest:ancest+, head:head, remote:(empty) = result:no merge
	 * 11: ancest:ancest+, head:head, remote:remote = result:no merge
	 */

	/* 5ALT: ancest:*, head:head, remote:head = result:head */
	if (ours_changed && !ours_empty && !ours_theirs_differ)
		result = &conflict->our_entry;
	/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */
	else if (ours_changed && ours_empty && theirs_empty)
		*resolved = 0;
	/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */
	else if (ours_empty && !theirs_changed)
		*resolved = 0;
	/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */
	else if (!ours_changed && theirs_empty)
		*resolved = 0;
	/* 13: ancest:ancest+, head:head, remote:ancest = result:head */
	else if (ours_changed && !theirs_changed)
		result = &conflict->our_entry;
	/* 14: ancest:ancest+, head:ancest, remote:remote = result:remote */
	else if (!ours_changed && theirs_changed)
		result = &conflict->their_entry;
	else
		*resolved = 0;

	if (result != NULL &&
		GIT_MERGE_INDEX_ENTRY_EXISTS(*result) &&
		(error = git_vector_insert(&diff_list->staged, (void *)result)) >= 0)
		*resolved = 1;

	/* Note: trivial resolution does not update the REUC. */
nulltoken committed
702

Edward Thomson committed
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
	return error;
}

static int merge_conflict_resolve_one_removed(
	int *resolved,
	git_merge_diff_list *diff_list,
	const git_merge_diff *conflict)
{
	int ours_empty, theirs_empty;
	int ours_changed, theirs_changed;
	int error = 0;

	assert(resolved && diff_list && conflict);

	*resolved = 0;

	if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE ||
		conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
		return 0;

	ours_empty = !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry);
	theirs_empty = !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry);

	ours_changed = (conflict->our_status != GIT_DELTA_UNMODIFIED);
	theirs_changed = (conflict->their_status != GIT_DELTA_UNMODIFIED);

	/* Removed in both */
	if (ours_changed && ours_empty && theirs_empty)
		*resolved = 1;
	/* Removed in ours */
	else if (ours_empty && !theirs_changed)
		*resolved = 1;
	/* Removed in theirs */
	else if (!ours_changed && theirs_empty)
		*resolved = 1;

	if (*resolved)
		git_vector_insert(&diff_list->resolved, (git_merge_diff *)conflict);

	return error;
}

static int merge_conflict_resolve_one_renamed(
	int *resolved,
	git_merge_diff_list *diff_list,
	const git_merge_diff *conflict)
{
	int ours_renamed, theirs_renamed;
	int ours_changed, theirs_changed;
	git_index_entry *merged;
	int error = 0;
nulltoken committed
754

Edward Thomson committed
755
	assert(resolved && diff_list && conflict);
nulltoken committed
756

Edward Thomson committed
757 758 759 760 761 762 763 764
	*resolved = 0;

	if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ||
		!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry))
		return 0;

	ours_renamed = (conflict->our_status == GIT_DELTA_RENAMED);
	theirs_renamed = (conflict->their_status == GIT_DELTA_RENAMED);
nulltoken committed
765

Edward Thomson committed
766 767 768 769 770 771 772 773 774
	if (!ours_renamed && !theirs_renamed)
		return 0;

	/* Reject one file in a 2->1 conflict */
	if (conflict->type == GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1 ||
		conflict->type == GIT_MERGE_DIFF_BOTH_RENAMED_1_TO_2 ||
		conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
		return 0;

775 776
	ours_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->our_entry.id) != 0);
	theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->their_entry.id) != 0);
nulltoken committed
777

Edward Thomson committed
778 779
	/* if both are modified (and not to a common target) require a merge */
	if (ours_changed && theirs_changed &&
780
		git_oid__cmp(&conflict->our_entry.id, &conflict->their_entry.id) != 0)
Edward Thomson committed
781 782
		return 0;

783
	if ((merged = git_pool_malloc(&diff_list->pool, sizeof(git_index_entry))) == NULL)
Edward Thomson committed
784
		return -1;
nulltoken committed
785

Edward Thomson committed
786 787 788 789 790 791 792 793 794
	if (ours_changed)
		memcpy(merged, &conflict->our_entry, sizeof(git_index_entry));
	else
		memcpy(merged, &conflict->their_entry, sizeof(git_index_entry));

	if (ours_renamed)
		merged->path = conflict->our_entry.path;
	else
		merged->path = conflict->their_entry.path;
nulltoken committed
795

Edward Thomson committed
796
	*resolved = 1;
nulltoken committed
797

Edward Thomson committed
798 799
	git_vector_insert(&diff_list->staged, merged);
	git_vector_insert(&diff_list->resolved, (git_merge_diff *)conflict);
nulltoken committed
800

Edward Thomson committed
801 802 803
	return error;
}

804 805
static bool merge_conflict_can_resolve_contents(
	const git_merge_diff *conflict)
Edward Thomson committed
806
{
807 808
	if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ||
		!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry))
809
		return false;
810

Edward Thomson committed
811 812
	/* Reject D/F conflicts */
	if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE)
813
		return false;
Edward Thomson committed
814

Edward Thomson committed
815 816 817 818
	/* Reject submodules. */
	if (S_ISGITLINK(conflict->ancestor_entry.mode) ||
		S_ISGITLINK(conflict->our_entry.mode) ||
		S_ISGITLINK(conflict->their_entry.mode))
819
		return false;
Edward Thomson committed
820

Edward Thomson committed
821
	/* Reject link/file conflicts. */
822 823 824 825 826
	if ((S_ISLNK(conflict->ancestor_entry.mode) ^
			S_ISLNK(conflict->our_entry.mode)) ||
		(S_ISLNK(conflict->ancestor_entry.mode) ^
			S_ISLNK(conflict->their_entry.mode)))
		return false;
Edward Thomson committed
827 828 829 830

	/* Reject name conflicts */
	if (conflict->type == GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1 ||
		conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
831
		return false;
Edward Thomson committed
832 833 834 835

	if ((conflict->our_status & GIT_DELTA_RENAMED) == GIT_DELTA_RENAMED &&
		(conflict->their_status & GIT_DELTA_RENAMED) == GIT_DELTA_RENAMED &&
		strcmp(conflict->ancestor_entry.path, conflict->their_entry.path) != 0)
836 837 838 839 840 841 842
		return false;

	return true;
}

static int merge_conflict_invoke_driver(
	git_index_entry **out,
843
	const char *name,
844 845
	git_merge_driver *driver,
	git_merge_diff_list *diff_list,
846
	git_merge_driver_source *src)
847 848 849 850 851 852 853 854 855 856 857
{
	git_index_entry *result;
	git_buf buf = GIT_BUF_INIT;
	const char *path;
	uint32_t mode;
	git_odb *odb = NULL;
	git_oid oid;
	int error;

	*out = NULL;

858 859
	if ((error = driver->apply(driver, &path, &mode, &buf, name, src)) < 0 ||
		(error = git_repository_odb(&odb, src->repo)) < 0 ||
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885
		(error = git_odb_write(&oid, odb, buf.ptr, buf.size, GIT_OBJ_BLOB)) < 0)
		goto done;

	result = git_pool_mallocz(&diff_list->pool, sizeof(git_index_entry));
	GITERR_CHECK_ALLOC(result);

	git_oid_cpy(&result->id, &oid);
	result->mode = mode;
	result->file_size = buf.size;

	result->path = git_pool_strdup(&diff_list->pool, path);
	GITERR_CHECK_ALLOC(result->path);

	*out = result;

done:
	git_buf_free(&buf);
	git_odb_free(odb);

	return error;
}

static int merge_conflict_resolve_contents(
	int *resolved,
	git_merge_diff_list *diff_list,
	const git_merge_diff *conflict,
886
	const git_merge_options *merge_opts,
887 888 889 890 891
	const git_merge_file_options *file_opts)
{
	git_merge_driver_source source = {0};
	git_merge_file_result result = {0};
	git_merge_driver *driver;
892
	git_merge_driver__builtin builtin = {{0}};
893 894
	git_index_entry *merge_result;
	git_odb *odb = NULL;
895
	const char *name;
896 897
	bool fallback = false;
	int error;
898 899 900 901 902 903

	assert(resolved && diff_list && conflict);

	*resolved = 0;

	if (!merge_conflict_can_resolve_contents(conflict))
Edward Thomson committed
904 905
		return 0;

906
	source.repo = diff_list->repo;
907
	source.default_driver = merge_opts->default_driver;
908 909
	source.file_opts = file_opts;
	source.ancestor = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
910
		&conflict->ancestor_entry : NULL;
911
	source.ours = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
912
		&conflict->our_entry : NULL;
913
	source.theirs = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
914 915
		&conflict->their_entry : NULL;

916 917
	if (file_opts->favor != GIT_MERGE_FILE_FAVOR_NORMAL) {
		/* if the user requested a particular type of resolution (via the
918 919
		 * favor flag) then let that override the gitattributes and use
		 * the builtin driver.
920
		 */
921 922 923 924 925
		name = "text";
		builtin.base.apply = git_merge_driver__builtin_apply;
		builtin.favor = file_opts->favor;

		driver = &builtin.base;
926 927
	} else {
		/* find the merge driver for this file */
928
		if ((error = git_merge_driver_for_source(&name, &driver, &source)) < 0)
929
			goto done;
930 931 932

		if (driver == NULL)
			fallback = true;
933 934
	}

935 936 937 938 939 940 941
	if (driver) {
		error = merge_conflict_invoke_driver(&merge_result, name, driver,
			diff_list, &source);

		if (error == GIT_PASSTHROUGH)
			fallback = true;
	}
nulltoken committed
942

943
	if (fallback) {
944 945
		error = merge_conflict_invoke_driver(&merge_result, "text",
			&git_merge_driver__text.base, diff_list, &source);
946
	}
Edward Thomson committed
947

948 949 950
	if (error < 0) {
		if (error == GIT_EMERGECONFLICT)
			error = 0;
Edward Thomson committed
951

952 953
		goto done;
	}
nulltoken committed
954

955
	git_vector_insert(&diff_list->staged, merge_result);
Edward Thomson committed
956 957 958 959 960 961 962
	git_vector_insert(&diff_list->resolved, (git_merge_diff *)conflict);

	*resolved = 1;

done:
	git_merge_file_result_free(&result);
	git_odb_free(odb);
nulltoken committed
963

Edward Thomson committed
964 965 966 967 968 969 970
	return error;
}

static int merge_conflict_resolve(
	int *out,
	git_merge_diff_list *diff_list,
	const git_merge_diff *conflict,
971
	const git_merge_options *merge_opts,
972
	const git_merge_file_options *file_opts)
Edward Thomson committed
973 974 975
{
	int resolved = 0;
	int error = 0;
nulltoken committed
976

Edward Thomson committed
977
	*out = 0;
nulltoken committed
978

979 980
	if ((error = merge_conflict_resolve_trivial(
			&resolved, diff_list, conflict)) < 0)
Edward Thomson committed
981 982
		goto done;

983 984
	if (!resolved && (error = merge_conflict_resolve_one_removed(
			&resolved, diff_list, conflict)) < 0)
985
		goto done;
nulltoken committed
986

987 988
	if (!resolved && (error = merge_conflict_resolve_one_renamed(
			&resolved, diff_list, conflict)) < 0)
989
		goto done;
Edward Thomson committed
990

991 992
	if (!resolved && (error = merge_conflict_resolve_contents(
			&resolved, diff_list, conflict, merge_opts, file_opts)) < 0)
993
		goto done;
Edward Thomson committed
994 995

	*out = resolved;
nulltoken committed
996

Edward Thomson committed
997 998 999 1000
done:
	return error;
}

Edward Thomson committed
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
/* Rename detection and coalescing */

struct merge_diff_similarity {
	unsigned char similarity;
	size_t other_idx;
};

static int index_entry_similarity_exact(
	git_repository *repo,
	git_index_entry *a,
	size_t a_idx,
	git_index_entry *b,
	size_t b_idx,
	void **cache,
1015
	const git_merge_options *opts)
Edward Thomson committed
1016 1017 1018 1019 1020 1021 1022
{
	GIT_UNUSED(repo);
	GIT_UNUSED(a_idx);
	GIT_UNUSED(b_idx);
	GIT_UNUSED(cache);
	GIT_UNUSED(opts);

1023
	if (git_oid__cmp(&a->id, &b->id) == 0)
Edward Thomson committed
1024
		return 100;
nulltoken committed
1025

Edward Thomson committed
1026 1027 1028 1029 1030 1031 1032
	return 0;
}

static int index_entry_similarity_calc(
	void **out,
	git_repository *repo,
	git_index_entry *entry,
1033
	const git_merge_options *opts)
Edward Thomson committed
1034 1035 1036
{
	git_blob *blob;
	git_diff_file diff_file = {{{0}}};
1037
	git_off_t blobsize;
Edward Thomson committed
1038
	int error;
nulltoken committed
1039

Edward Thomson committed
1040 1041
	*out = NULL;

1042
	if ((error = git_blob_lookup(&blob, repo, &entry->id)) < 0)
Edward Thomson committed
1043
		return error;
nulltoken committed
1044

1045
	git_oid_cpy(&diff_file.id, &entry->id);
Edward Thomson committed
1046 1047 1048 1049
	diff_file.path = entry->path;
	diff_file.size = entry->file_size;
	diff_file.mode = entry->mode;
	diff_file.flags = 0;
nulltoken committed
1050

1051 1052 1053 1054 1055
	blobsize = git_blob_rawsize(blob);

	/* file too big for rename processing */
	if (!git__is_sizet(blobsize))
		return 0;
nulltoken committed
1056

Edward Thomson committed
1057
	error = opts->metric->buffer_signature(out, &diff_file,
1058
		git_blob_rawcontent(blob), (size_t)blobsize,
Edward Thomson committed
1059
		opts->metric->payload);
nulltoken committed
1060

Edward Thomson committed
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072
	git_blob_free(blob);

	return error;
}

static int index_entry_similarity_inexact(
	git_repository *repo,
	git_index_entry *a,
	size_t a_idx,
	git_index_entry *b,
	size_t b_idx,
	void **cache,
1073
	const git_merge_options *opts)
Edward Thomson committed
1074 1075 1076
{
	int score = 0;
	int error = 0;
nulltoken committed
1077

1078
	if (!GIT_MODE_ISBLOB(a->mode) || !GIT_MODE_ISBLOB(b->mode))
Edward Thomson committed
1079
		return 0;
nulltoken committed
1080

Edward Thomson committed
1081 1082 1083 1084 1085
	/* update signature cache if needed */
	if (!cache[a_idx] && (error = index_entry_similarity_calc(&cache[a_idx], repo, a, opts)) < 0)
		return error;
	if (!cache[b_idx] && (error = index_entry_similarity_calc(&cache[b_idx], repo, b, opts)) < 0)
		return error;
nulltoken committed
1086

Edward Thomson committed
1087 1088 1089 1090 1091 1092 1093 1094
	/* some metrics may not wish to process this file (too big / too small) */
	if (!cache[a_idx] || !cache[b_idx])
		return 0;

	/* compare signatures */
	if (opts->metric->similarity(
		&score, cache[a_idx], cache[b_idx], opts->metric->payload) < 0)
		return -1;
nulltoken committed
1095

Edward Thomson committed
1096 1097 1098 1099 1100
	/* clip score */
	if (score < 0)
		score = 0;
	else if (score > 100)
		score = 100;
nulltoken committed
1101

Edward Thomson committed
1102 1103 1104 1105 1106 1107 1108 1109
	return score;
}

static int merge_diff_mark_similarity(
	git_repository *repo,
	git_merge_diff_list *diff_list,
	struct merge_diff_similarity *similarity_ours,
	struct merge_diff_similarity *similarity_theirs,
1110
	int (*similarity_fn)(git_repository *, git_index_entry *, size_t, git_index_entry *, size_t, void **, const git_merge_options *),
Edward Thomson committed
1111
	void **cache,
1112
	const git_merge_options *opts)
Edward Thomson committed
1113 1114 1115 1116
{
	size_t i, j;
	git_merge_diff *conflict_src, *conflict_tgt;
	int similarity;
nulltoken committed
1117

Edward Thomson committed
1118 1119 1120 1121 1122 1123 1124
	git_vector_foreach(&diff_list->conflicts, i, conflict_src) {
		/* Items can be the source of a rename iff they have an item in the
		 * ancestor slot and lack an item in the ours or theirs slot. */
		if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->ancestor_entry) ||
			(GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->our_entry) &&
			 GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->their_entry)))
			continue;
nulltoken committed
1125

Edward Thomson committed
1126 1127 1128
		git_vector_foreach(&diff_list->conflicts, j, conflict_tgt) {
			size_t our_idx = diff_list->conflicts.length + j;
			size_t their_idx = (diff_list->conflicts.length * 2) + j;
nulltoken committed
1129

Edward Thomson committed
1130 1131
			if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->ancestor_entry))
				continue;
nulltoken committed
1132

Edward Thomson committed
1133 1134 1135
			if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->our_entry) &&
				!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->our_entry)) {
				similarity = similarity_fn(repo, &conflict_src->ancestor_entry, i, &conflict_tgt->our_entry, our_idx, cache, opts);
nulltoken committed
1136

Edward Thomson committed
1137
				if (similarity == GIT_EBUFS)
nulltoken committed
1138
					continue;
Edward Thomson committed
1139 1140
				else if (similarity < 0)
					return similarity;
nulltoken committed
1141

Edward Thomson committed
1142 1143 1144 1145 1146
				if (similarity > similarity_ours[i].similarity &&
					similarity > similarity_ours[j].similarity) {
					/* Clear previous best similarity */
					if (similarity_ours[i].similarity > 0)
						similarity_ours[similarity_ours[i].other_idx].similarity = 0;
nulltoken committed
1147

Edward Thomson committed
1148 1149
					if (similarity_ours[j].similarity > 0)
						similarity_ours[similarity_ours[j].other_idx].similarity = 0;
nulltoken committed
1150

Edward Thomson committed
1151 1152
					similarity_ours[i].similarity = similarity;
					similarity_ours[i].other_idx = j;
nulltoken committed
1153

Edward Thomson committed
1154 1155 1156 1157
					similarity_ours[j].similarity = similarity;
					similarity_ours[j].other_idx = i;
				}
			}
nulltoken committed
1158

Edward Thomson committed
1159 1160 1161
			if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->their_entry) &&
				!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->their_entry)) {
				similarity = similarity_fn(repo, &conflict_src->ancestor_entry, i, &conflict_tgt->their_entry, their_idx, cache, opts);
nulltoken committed
1162

Edward Thomson committed
1163 1164 1165 1166 1167
				if (similarity > similarity_theirs[i].similarity &&
					similarity > similarity_theirs[j].similarity) {
					/* Clear previous best similarity */
					if (similarity_theirs[i].similarity > 0)
						similarity_theirs[similarity_theirs[i].other_idx].similarity = 0;
nulltoken committed
1168

Edward Thomson committed
1169 1170
					if (similarity_theirs[j].similarity > 0)
						similarity_theirs[similarity_theirs[j].other_idx].similarity = 0;
nulltoken committed
1171

Edward Thomson committed
1172 1173
					similarity_theirs[i].similarity = similarity;
					similarity_theirs[i].other_idx = j;
nulltoken committed
1174

Edward Thomson committed
1175 1176 1177 1178 1179 1180
					similarity_theirs[j].similarity = similarity;
					similarity_theirs[j].other_idx = i;
				}
			}
		}
	}
nulltoken committed
1181

Edward Thomson committed
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212
	return 0;
}

/*
 * Rename conflicts:
 *
 *      Ancestor   Ours   Theirs
 *
 * 0a   A          A      A        No rename
 *  b   A          A*     A        No rename (ours was rewritten)
 *  c   A          A      A*       No rename (theirs rewritten)
 * 1a   A          A      B[A]     Rename or rename/edit
 *  b   A          B[A]   A        (automergeable)
 * 2    A          B[A]   B[A]     Both renamed (automergeable)
 * 3a   A          B[A]            Rename/delete
 *  b   A                 B[A]      (same)
 * 4a   A          B[A]   B        Rename/add [B~ours B~theirs]
 *  b   A          B      B[A]      (same)
 * 5    A          B[A]   C[A]     Both renamed ("1 -> 2")
 * 6    A          C[A]            Both renamed ("2 -> 1")
 *      B                 C[B]     [C~ours C~theirs]    (automergeable)
 */
static void merge_diff_mark_rename_conflict(
	git_merge_diff_list *diff_list,
	struct merge_diff_similarity *similarity_ours,
	bool ours_renamed,
	size_t ours_source_idx,
	struct merge_diff_similarity *similarity_theirs,
	bool theirs_renamed,
	size_t theirs_source_idx,
	git_merge_diff *target,
1213
	const git_merge_options *opts)
Edward Thomson committed
1214 1215
{
	git_merge_diff *ours_source = NULL, *theirs_source = NULL;
nulltoken committed
1216

Edward Thomson committed
1217 1218
	if (ours_renamed)
		ours_source = diff_list->conflicts.contents[ours_source_idx];
nulltoken committed
1219

Edward Thomson committed
1220 1221
	if (theirs_renamed)
		theirs_source = diff_list->conflicts.contents[theirs_source_idx];
nulltoken committed
1222

Edward Thomson committed
1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
	/* Detect 2->1 conflicts */
	if (ours_renamed && theirs_renamed) {
		/* Both renamed to the same target name. */
		if (ours_source_idx == theirs_source_idx)
			ours_source->type = GIT_MERGE_DIFF_BOTH_RENAMED;
		else {
			ours_source->type = GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1;
			theirs_source->type = GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1;
		}
	} else if (ours_renamed) {
		/* If our source was also renamed in theirs, this is a 1->2 */
		if (similarity_theirs[ours_source_idx].similarity >= opts->rename_threshold)
			ours_source->type = GIT_MERGE_DIFF_BOTH_RENAMED_1_TO_2;
nulltoken committed
1236

Edward Thomson committed
1237 1238 1239 1240
		else if (GIT_MERGE_INDEX_ENTRY_EXISTS(target->their_entry)) {
			ours_source->type = GIT_MERGE_DIFF_RENAMED_ADDED;
			target->type = GIT_MERGE_DIFF_RENAMED_ADDED;
		}
nulltoken committed
1241

Edward Thomson committed
1242 1243
		else if (!GIT_MERGE_INDEX_ENTRY_EXISTS(ours_source->their_entry))
			ours_source->type = GIT_MERGE_DIFF_RENAMED_DELETED;
nulltoken committed
1244

Edward Thomson committed
1245 1246 1247 1248 1249 1250
		else if (ours_source->type == GIT_MERGE_DIFF_MODIFIED_DELETED)
			ours_source->type = GIT_MERGE_DIFF_RENAMED_MODIFIED;
	} else if (theirs_renamed) {
		/* If their source was also renamed in ours, this is a 1->2 */
		if (similarity_ours[theirs_source_idx].similarity >= opts->rename_threshold)
			theirs_source->type = GIT_MERGE_DIFF_BOTH_RENAMED_1_TO_2;
nulltoken committed
1251

Edward Thomson committed
1252 1253 1254 1255
		else if (GIT_MERGE_INDEX_ENTRY_EXISTS(target->our_entry)) {
			theirs_source->type = GIT_MERGE_DIFF_RENAMED_ADDED;
			target->type = GIT_MERGE_DIFF_RENAMED_ADDED;
		}
nulltoken committed
1256

Edward Thomson committed
1257 1258
		else if (!GIT_MERGE_INDEX_ENTRY_EXISTS(theirs_source->our_entry))
			theirs_source->type = GIT_MERGE_DIFF_RENAMED_DELETED;
nulltoken committed
1259

Edward Thomson committed
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
		else if (theirs_source->type == GIT_MERGE_DIFF_MODIFIED_DELETED)
			theirs_source->type = GIT_MERGE_DIFF_RENAMED_MODIFIED;
	}
}

GIT_INLINE(void) merge_diff_coalesce_rename(
	git_index_entry *source_entry,
	git_delta_t *source_status,
	git_index_entry *target_entry,
	git_delta_t *target_status)
{
	/* Coalesce the rename target into the rename source. */
	memcpy(source_entry, target_entry, sizeof(git_index_entry));
	*source_status = GIT_DELTA_RENAMED;
nulltoken committed
1274

Edward Thomson committed
1275 1276 1277 1278 1279 1280 1281 1282
	memset(target_entry, 0x0, sizeof(git_index_entry));
	*target_status = GIT_DELTA_UNMODIFIED;
}

static void merge_diff_list_coalesce_renames(
	git_merge_diff_list *diff_list,
	struct merge_diff_similarity *similarity_ours,
	struct merge_diff_similarity *similarity_theirs,
1283
	const git_merge_options *opts)
Edward Thomson committed
1284 1285 1286 1287 1288
{
	size_t i;
	bool ours_renamed = 0, theirs_renamed = 0;
	size_t ours_source_idx = 0, theirs_source_idx = 0;
	git_merge_diff *ours_source, *theirs_source, *target;
nulltoken committed
1289

Edward Thomson committed
1290 1291
	for (i = 0; i < diff_list->conflicts.length; i++) {
		target = diff_list->conflicts.contents[i];
nulltoken committed
1292

Edward Thomson committed
1293 1294
		ours_renamed = 0;
		theirs_renamed = 0;
nulltoken committed
1295

Edward Thomson committed
1296 1297 1298
		if (GIT_MERGE_INDEX_ENTRY_EXISTS(target->our_entry) &&
			similarity_ours[i].similarity >= opts->rename_threshold) {
			ours_source_idx = similarity_ours[i].other_idx;
nulltoken committed
1299

Edward Thomson committed
1300
			ours_source = diff_list->conflicts.contents[ours_source_idx];
nulltoken committed
1301

Edward Thomson committed
1302 1303 1304 1305 1306
			merge_diff_coalesce_rename(
				&ours_source->our_entry,
				&ours_source->our_status,
				&target->our_entry,
				&target->our_status);
nulltoken committed
1307

Edward Thomson committed
1308 1309
			similarity_ours[ours_source_idx].similarity = 0;
			similarity_ours[i].similarity = 0;
nulltoken committed
1310

Edward Thomson committed
1311 1312
			ours_renamed = 1;
		}
nulltoken committed
1313

Edward Thomson committed
1314 1315 1316 1317
		/* insufficient to determine direction */
		if (GIT_MERGE_INDEX_ENTRY_EXISTS(target->their_entry) &&
			similarity_theirs[i].similarity >= opts->rename_threshold) {
			theirs_source_idx = similarity_theirs[i].other_idx;
nulltoken committed
1318

Edward Thomson committed
1319
			theirs_source = diff_list->conflicts.contents[theirs_source_idx];
nulltoken committed
1320

Edward Thomson committed
1321 1322 1323 1324 1325
			merge_diff_coalesce_rename(
				&theirs_source->their_entry,
				&theirs_source->their_status,
				&target->their_entry,
				&target->their_status);
nulltoken committed
1326

Edward Thomson committed
1327 1328
			similarity_theirs[theirs_source_idx].similarity = 0;
			similarity_theirs[i].similarity = 0;
nulltoken committed
1329

Edward Thomson committed
1330 1331
			theirs_renamed = 1;
		}
nulltoken committed
1332

Edward Thomson committed
1333 1334 1335 1336 1337 1338 1339
		merge_diff_mark_rename_conflict(diff_list,
			similarity_ours, ours_renamed, ours_source_idx,
			similarity_theirs, theirs_renamed, theirs_source_idx,
			target, opts);
	}
}

1340
static int merge_diff_empty(const git_vector *conflicts, size_t idx, void *p)
Edward Thomson committed
1341 1342
{
	git_merge_diff *conflict = conflicts->contents[idx];
nulltoken committed
1343

1344 1345
	GIT_UNUSED(p);

Edward Thomson committed
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360
	return (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) &&
		!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) &&
		!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry));
}

static void merge_diff_list_count_candidates(
	git_merge_diff_list *diff_list,
	size_t *src_count,
	size_t *tgt_count)
{
	git_merge_diff *entry;
	size_t i;

	*src_count = 0;
	*tgt_count = 0;
nulltoken committed
1361

Edward Thomson committed
1362 1363 1364 1365
	git_vector_foreach(&diff_list->conflicts, i, entry) {
		if (GIT_MERGE_INDEX_ENTRY_EXISTS(entry->ancestor_entry) &&
			(!GIT_MERGE_INDEX_ENTRY_EXISTS(entry->our_entry) ||
			!GIT_MERGE_INDEX_ENTRY_EXISTS(entry->their_entry)))
1366
			(*src_count)++;
Edward Thomson committed
1367
		else if (!GIT_MERGE_INDEX_ENTRY_EXISTS(entry->ancestor_entry))
1368
			(*tgt_count)++;
Edward Thomson committed
1369 1370 1371 1372 1373 1374
	}
}

int git_merge_diff_list__find_renames(
	git_repository *repo,
	git_merge_diff_list *diff_list,
1375
	const git_merge_options *opts)
Edward Thomson committed
1376 1377 1378 1379 1380 1381
{
	struct merge_diff_similarity *similarity_ours, *similarity_theirs;
	void **cache = NULL;
	size_t cache_size = 0;
	size_t src_count, tgt_count, i;
	int error = 0;
nulltoken committed
1382

Edward Thomson committed
1383
	assert(diff_list && opts);
nulltoken committed
1384

1385
	if ((opts->flags & GIT_MERGE_FIND_RENAMES) == 0)
Edward Thomson committed
1386
		return 0;
nulltoken committed
1387

Edward Thomson committed
1388 1389 1390
	similarity_ours = git__calloc(diff_list->conflicts.length,
		sizeof(struct merge_diff_similarity));
	GITERR_CHECK_ALLOC(similarity_ours);
nulltoken committed
1391

Edward Thomson committed
1392 1393 1394
	similarity_theirs = git__calloc(diff_list->conflicts.length,
		sizeof(struct merge_diff_similarity));
	GITERR_CHECK_ALLOC(similarity_theirs);
nulltoken committed
1395

Edward Thomson committed
1396 1397 1398 1399 1400 1401 1402 1403
	/* Calculate similarity between items that were deleted from the ancestor
	 * and added in the other branch.
	 */
	if ((error = merge_diff_mark_similarity(repo, diff_list, similarity_ours,
		similarity_theirs, index_entry_similarity_exact, NULL, opts)) < 0)
		goto done;

	if (diff_list->conflicts.length <= opts->target_limit) {
1404
		GITERR_CHECK_ALLOC_MULTIPLY(&cache_size, diff_list->conflicts.length, 3);
Edward Thomson committed
1405 1406 1407 1408
		cache = git__calloc(cache_size, sizeof(void *));
		GITERR_CHECK_ALLOC(cache);

		merge_diff_list_count_candidates(diff_list, &src_count, &tgt_count);
nulltoken committed
1409

Edward Thomson committed
1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423
		if (src_count > opts->target_limit || tgt_count > opts->target_limit) {
			/* TODO: report! */
		} else {
			if ((error = merge_diff_mark_similarity(
				repo, diff_list, similarity_ours, similarity_theirs,
				index_entry_similarity_inexact, cache, opts)) < 0)
				goto done;
		}
	}

	/* For entries that are appropriately similar, merge the new name's entry
	 * into the old name.
	 */
	merge_diff_list_coalesce_renames(diff_list, similarity_ours, similarity_theirs, opts);
nulltoken committed
1424

Edward Thomson committed
1425
	/* And remove any entries that were merged and are now empty. */
1426
	git_vector_remove_matching(&diff_list->conflicts, merge_diff_empty, NULL);
Edward Thomson committed
1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443

done:
	if (cache != NULL) {
		for (i = 0; i < cache_size; ++i) {
			if (cache[i] != NULL)
				opts->metric->free_signature(cache[i], opts->metric->payload);
		}

		git__free(cache);
	}

	git__free(similarity_ours);
	git__free(similarity_theirs);

	return error;
}

Edward Thomson committed
1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454
/* Directory/file conflict handling */

GIT_INLINE(const char *) merge_diff_path(
	const git_merge_diff *conflict)
{
	if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry))
		return conflict->ancestor_entry.path;
	else if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry))
		return conflict->our_entry.path;
	else if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry))
		return conflict->their_entry.path;
nulltoken committed
1455

Edward Thomson committed
1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466
	return NULL;
}

GIT_INLINE(bool) merge_diff_any_side_added_or_modified(
	const git_merge_diff *conflict)
{
	if (conflict->our_status == GIT_DELTA_ADDED ||
		conflict->our_status == GIT_DELTA_MODIFIED ||
		conflict->their_status == GIT_DELTA_ADDED ||
		conflict->their_status == GIT_DELTA_MODIFIED)
		return true;
nulltoken committed
1467

Edward Thomson committed
1468 1469 1470 1471 1472 1473 1474
	return false;
}

GIT_INLINE(bool) path_is_prefixed(const char *parent, const char *child)
{
	size_t child_len = strlen(child);
	size_t parent_len = strlen(parent);
nulltoken committed
1475

Edward Thomson committed
1476 1477 1478
	if (child_len < parent_len ||
		strncmp(parent, child, parent_len) != 0)
		return 0;
nulltoken committed
1479

Edward Thomson committed
1480 1481 1482 1483 1484 1485 1486 1487
	return (child[parent_len] == '/');
}

GIT_INLINE(int) merge_diff_detect_df_conflict(
	struct merge_diff_df_data *df_data,
	git_merge_diff *conflict)
{
	const char *cur_path = merge_diff_path(conflict);
nulltoken committed
1488

Edward Thomson committed
1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499
	/* Determine if this is a D/F conflict or the child of one */
	if (df_data->df_path &&
		path_is_prefixed(df_data->df_path, cur_path))
		conflict->type = GIT_MERGE_DIFF_DF_CHILD;
	else if(df_data->df_path)
		df_data->df_path = NULL;
	else if (df_data->prev_path &&
		merge_diff_any_side_added_or_modified(df_data->prev_conflict) &&
		merge_diff_any_side_added_or_modified(conflict) &&
		path_is_prefixed(df_data->prev_path, cur_path)) {
		conflict->type = GIT_MERGE_DIFF_DF_CHILD;
nulltoken committed
1500

Edward Thomson committed
1501 1502 1503
		df_data->prev_conflict->type = GIT_MERGE_DIFF_DIRECTORY_FILE;
		df_data->df_path = df_data->prev_path;
	}
nulltoken committed
1504

Edward Thomson committed
1505 1506
	df_data->prev_path = cur_path;
	df_data->prev_conflict = conflict;
nulltoken committed
1507

Edward Thomson committed
1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532
	return 0;
}

/* Conflict handling */

GIT_INLINE(int) merge_diff_detect_type(
	git_merge_diff *conflict)
{
	if (conflict->our_status == GIT_DELTA_ADDED &&
		conflict->their_status == GIT_DELTA_ADDED)
		conflict->type = GIT_MERGE_DIFF_BOTH_ADDED;
	else if (conflict->our_status == GIT_DELTA_MODIFIED &&
			 conflict->their_status == GIT_DELTA_MODIFIED)
		conflict->type = GIT_MERGE_DIFF_BOTH_MODIFIED;
	else if (conflict->our_status == GIT_DELTA_DELETED &&
			 conflict->their_status == GIT_DELTA_DELETED)
		conflict->type = GIT_MERGE_DIFF_BOTH_DELETED;
	else if (conflict->our_status == GIT_DELTA_MODIFIED &&
			 conflict->their_status == GIT_DELTA_DELETED)
		conflict->type = GIT_MERGE_DIFF_MODIFIED_DELETED;
	else if (conflict->our_status == GIT_DELTA_DELETED &&
			 conflict->their_status == GIT_DELTA_MODIFIED)
		conflict->type = GIT_MERGE_DIFF_MODIFIED_DELETED;
	else
		conflict->type = GIT_MERGE_DIFF_NONE;
nulltoken committed
1533

Edward Thomson committed
1534 1535 1536
	return 0;
}

1537
GIT_INLINE(int) index_entry_dup_pool(
Edward Thomson committed
1538 1539 1540 1541 1542 1543 1544 1545 1546
	git_index_entry *out,
	git_pool *pool,
	const git_index_entry *src)
{
	if (src != NULL) {
		memcpy(out, src, sizeof(git_index_entry));
		if ((out->path = git_pool_strdup(pool, src->path)) == NULL)
			return -1;
	}
nulltoken committed
1547

Edward Thomson committed
1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564
	return 0;
}

GIT_INLINE(int) merge_delta_type_from_index_entries(
	const git_index_entry *ancestor,
	const git_index_entry *other)
{
	if (ancestor == NULL && other == NULL)
		return GIT_DELTA_UNMODIFIED;
	else if (ancestor == NULL && other != NULL)
		return GIT_DELTA_ADDED;
	else if (ancestor != NULL && other == NULL)
		return GIT_DELTA_DELETED;
	else if (S_ISDIR(ancestor->mode) ^ S_ISDIR(other->mode))
		return GIT_DELTA_TYPECHANGE;
	else if(S_ISLNK(ancestor->mode) ^ S_ISLNK(other->mode))
		return GIT_DELTA_TYPECHANGE;
1565
	else if (git_oid__cmp(&ancestor->id, &other->id) ||
Edward Thomson committed
1566 1567
			 ancestor->mode != other->mode)
		return GIT_DELTA_MODIFIED;
nulltoken committed
1568

Edward Thomson committed
1569 1570 1571 1572 1573 1574 1575 1576 1577
	return GIT_DELTA_UNMODIFIED;
}

static git_merge_diff *merge_diff_from_index_entries(
	git_merge_diff_list *diff_list,
	const git_index_entry **entries)
{
	git_merge_diff *conflict;
	git_pool *pool = &diff_list->pool;
nulltoken committed
1578

1579
	if ((conflict = git_pool_mallocz(pool, sizeof(git_merge_diff))) == NULL)
Edward Thomson committed
1580
		return NULL;
nulltoken committed
1581

1582 1583 1584
	if (index_entry_dup_pool(&conflict->ancestor_entry, pool, entries[TREE_IDX_ANCESTOR]) < 0 ||
		index_entry_dup_pool(&conflict->our_entry, pool, entries[TREE_IDX_OURS]) < 0 ||
		index_entry_dup_pool(&conflict->their_entry, pool, entries[TREE_IDX_THEIRS]) < 0)
Edward Thomson committed
1585
		return NULL;
nulltoken committed
1586

Edward Thomson committed
1587 1588 1589 1590
	conflict->our_status = merge_delta_type_from_index_entries(
		entries[TREE_IDX_ANCESTOR], entries[TREE_IDX_OURS]);
	conflict->their_status = merge_delta_type_from_index_entries(
		entries[TREE_IDX_ANCESTOR], entries[TREE_IDX_THEIRS]);
nulltoken committed
1591

Edward Thomson committed
1592 1593 1594 1595 1596
	return conflict;
}

/* Merge trees */

1597
static int merge_diff_list_insert_conflict(
Edward Thomson committed
1598 1599 1600 1601 1602
	git_merge_diff_list *diff_list,
	struct merge_diff_df_data *merge_df_data,
	const git_index_entry *tree_items[3])
{
	git_merge_diff *conflict;
nulltoken committed
1603

Edward Thomson committed
1604 1605 1606 1607 1608
	if ((conflict = merge_diff_from_index_entries(diff_list, tree_items)) == NULL ||
		merge_diff_detect_type(conflict) < 0 ||
		merge_diff_detect_df_conflict(merge_df_data, conflict) < 0 ||
		git_vector_insert(&diff_list->conflicts, conflict) < 0)
		return -1;
nulltoken committed
1609

Edward Thomson committed
1610 1611 1612
	return 0;
}

1613
static int merge_diff_list_insert_unmodified(
Edward Thomson committed
1614 1615 1616 1617 1618
	git_merge_diff_list *diff_list,
	const git_index_entry *tree_items[3])
{
	int error = 0;
	git_index_entry *entry;
nulltoken committed
1619

1620
	entry = git_pool_malloc(&diff_list->pool, sizeof(git_index_entry));
Edward Thomson committed
1621
	GITERR_CHECK_ALLOC(entry);
nulltoken committed
1622

1623
	if ((error = index_entry_dup_pool(entry, &diff_list->pool, tree_items[0])) >= 0)
Edward Thomson committed
1624
		error = git_vector_insert(&diff_list->staged, entry);
nulltoken committed
1625

Edward Thomson committed
1626 1627 1628
	return error;
}

1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656
struct merge_diff_find_data {
	git_merge_diff_list *diff_list;
	struct merge_diff_df_data df_data;
};

static int queue_difference(const git_index_entry **entries, void *data)
{
	struct merge_diff_find_data *find_data = data;
	bool item_modified = false;
	size_t i;

	if (!entries[0] || !entries[1] || !entries[2]) {
		item_modified = true;
	} else {
		for (i = 1; i < 3; i++) {
			if (index_entry_cmp(entries[0], entries[i]) != 0) {
				item_modified = true;
				break;
			}
		}
	}

	return item_modified ?
		merge_diff_list_insert_conflict(
			find_data->diff_list, &find_data->df_data, entries) :
		merge_diff_list_insert_unmodified(find_data->diff_list, entries);
}

Edward Thomson committed
1657 1658
int git_merge_diff_list__find_differences(
	git_merge_diff_list *diff_list,
1659 1660 1661
	git_iterator *ancestor_iter,
	git_iterator *our_iter,
	git_iterator *their_iter)
Edward Thomson committed
1662
{
1663
	git_iterator *iterators[3] = { ancestor_iter, our_iter, their_iter };
1664
	struct merge_diff_find_data find_data = { diff_list };
nulltoken committed
1665

1666
	return git_iterator_walk(iterators, 3, queue_difference, &find_data);
Edward Thomson committed
1667 1668 1669 1670 1671
}

git_merge_diff_list *git_merge_diff_list__alloc(git_repository *repo)
{
	git_merge_diff_list *diff_list = git__calloc(1, sizeof(git_merge_diff_list));
nulltoken committed
1672

Edward Thomson committed
1673 1674
	if (diff_list == NULL)
		return NULL;
nulltoken committed
1675

Edward Thomson committed
1676
	diff_list->repo = repo;
nulltoken committed
1677

1678 1679
	git_pool_init(&diff_list->pool, 1);

Edward Thomson committed
1680 1681
	if (git_vector_init(&diff_list->staged, 0, NULL) < 0 ||
		git_vector_init(&diff_list->conflicts, 0, NULL) < 0 ||
1682
		git_vector_init(&diff_list->resolved, 0, NULL) < 0) {
Jacques Germishuys committed
1683
		git_merge_diff_list__free(diff_list);
Edward Thomson committed
1684
		return NULL;
Jacques Germishuys committed
1685
	}
nulltoken committed
1686

Edward Thomson committed
1687 1688 1689
	return diff_list;
}

Edward Thomson committed
1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701
void git_merge_diff_list__free(git_merge_diff_list *diff_list)
{
	if (!diff_list)
		return;

	git_vector_free(&diff_list->staged);
	git_vector_free(&diff_list->conflicts);
	git_vector_free(&diff_list->resolved);
	git_pool_clear(&diff_list->pool);
	git__free(diff_list);
}

1702
static int merge_normalize_opts(
Edward Thomson committed
1703
	git_repository *repo,
1704 1705
	git_merge_options *opts,
	const git_merge_options *given)
Edward Thomson committed
1706 1707
{
	git_config *cfg = NULL;
1708
	git_config_entry *entry = NULL;
Edward Thomson committed
1709
	int error = 0;
nulltoken committed
1710

Edward Thomson committed
1711
	assert(repo && opts);
nulltoken committed
1712

Edward Thomson committed
1713 1714
	if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
		return error;
nulltoken committed
1715

1716
	if (given != NULL) {
1717
		memcpy(opts, given, sizeof(git_merge_options));
1718
	} else {
1719
		git_merge_options init = GIT_MERGE_OPTIONS_INIT;
Edward Thomson committed
1720
		memcpy(opts, &init, sizeof(init));
1721
	}
nulltoken committed
1722

1723
	if ((opts->flags & GIT_MERGE_FIND_RENAMES) && !opts->rename_threshold)
1724
		opts->rename_threshold = GIT_MERGE_DEFAULT_RENAME_THRESHOLD;
nulltoken committed
1725

1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741
	if (given && given->default_driver) {
		opts->default_driver = git__strdup(given->default_driver);
		GITERR_CHECK_ALLOC(opts->default_driver);
	} else {
		error = git_config_get_entry(&entry, cfg, "merge.default");

		if (error == 0) {
			opts->default_driver = git__strdup(entry->value);
			GITERR_CHECK_ALLOC(opts->default_driver);
		} else if (error == GIT_ENOTFOUND) {
			error = 0;
		} else {
			goto done;
		}
	}

Edward Thomson committed
1742
	if (!opts->target_limit) {
1743
		int limit = git_config__get_int_force(cfg, "merge.renamelimit", 0);
nulltoken committed
1744

1745 1746
		if (!limit)
			limit = git_config__get_int_force(cfg, "diff.renamelimit", 0);
nulltoken committed
1747

1748
		opts->target_limit = (limit <= 0) ?
1749
			GIT_MERGE_DEFAULT_TARGET_LIMIT : (unsigned int)limit;
Edward Thomson committed
1750
	}
nulltoken committed
1751

Edward Thomson committed
1752 1753 1754 1755
	/* assign the internal metric with whitespace flag as payload */
	if (!opts->metric) {
		opts->metric = git__malloc(sizeof(git_diff_similarity_metric));
		GITERR_CHECK_ALLOC(opts->metric);
nulltoken committed
1756

Edward Thomson committed
1757 1758 1759 1760
		opts->metric->file_signature = git_diff_find_similar__hashsig_for_file;
		opts->metric->buffer_signature = git_diff_find_similar__hashsig_for_buf;
		opts->metric->free_signature = git_diff_find_similar__hashsig_free;
		opts->metric->similarity = git_diff_find_similar__calc_similarity;
1761
		opts->metric->payload = (void *)GIT_HASHSIG_SMART_WHITESPACE;
Edward Thomson committed
1762
	}
nulltoken committed
1763

1764 1765 1766
done:
	git_config_entry_free(entry);
	return error;
Edward Thomson committed
1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778
}


static int merge_index_insert_reuc(
	git_index *index,
	size_t idx,
	const git_index_entry *entry)
{
	const git_index_reuc_entry *reuc;
	int mode[3] = { 0, 0, 0 };
	git_oid const *oid[3] = { NULL, NULL, NULL };
	size_t i;
nulltoken committed
1779

Edward Thomson committed
1780 1781
	if (!GIT_MERGE_INDEX_ENTRY_EXISTS(*entry))
		return 0;
nulltoken committed
1782

Edward Thomson committed
1783 1784 1785 1786 1787 1788
	if ((reuc = git_index_reuc_get_bypath(index, entry->path)) != NULL) {
		for (i = 0; i < 3; i++) {
			mode[i] = reuc->mode[i];
			oid[i] = &reuc->oid[i];
		}
	}
nulltoken committed
1789

Edward Thomson committed
1790
	mode[idx] = entry->mode;
1791
	oid[idx] = &entry->id;
nulltoken committed
1792

Edward Thomson committed
1793 1794 1795 1796
	return git_index_reuc_add(index, entry->path,
		mode[0], oid[0], mode[1], oid[1], mode[2], oid[2]);
}

1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835
static int index_update_reuc(git_index *index, git_merge_diff_list *diff_list)
{
	int error;
	size_t i;
	git_merge_diff *conflict;

	/* Add each entry in the resolved conflict to the REUC independently, since
	 * the paths may differ due to renames. */
	git_vector_foreach(&diff_list->resolved, i, conflict) {
		const git_index_entry *ancestor =
			GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
			&conflict->ancestor_entry : NULL;

		const git_index_entry *ours =
			GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
			&conflict->our_entry : NULL;

		const git_index_entry *theirs =
			GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
			&conflict->their_entry : NULL;

		if (ancestor != NULL &&
			(error = merge_index_insert_reuc(index, TREE_IDX_ANCESTOR, ancestor)) < 0)
			return error;

		if (ours != NULL &&
			(error = merge_index_insert_reuc(index, TREE_IDX_OURS, ours)) < 0)
			return error;

		if (theirs != NULL &&
			(error = merge_index_insert_reuc(index, TREE_IDX_THEIRS, theirs)) < 0)
			return error;
	}

	return 0;
}

static int index_from_diff_list(git_index **out,
	git_merge_diff_list *diff_list, bool skip_reuc)
Edward Thomson committed
1836 1837 1838 1839 1840
{
	git_index *index;
	size_t i;
	git_merge_diff *conflict;
	int error = 0;
nulltoken committed
1841

Edward Thomson committed
1842
	*out = NULL;
nulltoken committed
1843

Edward Thomson committed
1844 1845
	if ((error = git_index_new(&index)) < 0)
		return error;
nulltoken committed
1846

1847 1848
	if ((error = git_index__fill(index, &diff_list->staged)) < 0)
		goto on_error;
nulltoken committed
1849

Edward Thomson committed
1850 1851 1852 1853
	git_vector_foreach(&diff_list->conflicts, i, conflict) {
		const git_index_entry *ancestor =
			GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
			&conflict->ancestor_entry : NULL;
nulltoken committed
1854

Edward Thomson committed
1855 1856 1857
		const git_index_entry *ours =
			GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
			&conflict->our_entry : NULL;
nulltoken committed
1858

Edward Thomson committed
1859 1860 1861
		const git_index_entry *theirs =
			GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
			&conflict->their_entry : NULL;
nulltoken committed
1862

Edward Thomson committed
1863 1864 1865
		if ((error = git_index_conflict_add(index, ancestor, ours, theirs)) < 0)
			goto on_error;
	}
nulltoken committed
1866

Edward Thomson committed
1867 1868 1869
	/* Add each rename entry to the rename portion of the index. */
	git_vector_foreach(&diff_list->conflicts, i, conflict) {
		const char *ancestor_path, *our_path, *their_path;
nulltoken committed
1870

Edward Thomson committed
1871 1872
		if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry))
			continue;
nulltoken committed
1873

Edward Thomson committed
1874
		ancestor_path = conflict->ancestor_entry.path;
nulltoken committed
1875

Edward Thomson committed
1876 1877 1878
		our_path =
			GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
			conflict->our_entry.path : NULL;
nulltoken committed
1879

Edward Thomson committed
1880 1881 1882
		their_path =
			GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
			conflict->their_entry.path : NULL;
nulltoken committed
1883

Edward Thomson committed
1884 1885 1886 1887 1888
		if ((our_path && strcmp(ancestor_path, our_path) != 0) ||
			(their_path && strcmp(ancestor_path, their_path) != 0)) {
			if ((error = git_index_name_add(index, ancestor_path, our_path, their_path)) < 0)
				goto on_error;
		}
Edward Thomson committed
1889
	}
nulltoken committed
1890

1891 1892
	if (!skip_reuc) {
		if ((error = index_update_reuc(index, diff_list)) < 0)
Edward Thomson committed
1893 1894
			goto on_error;
	}
nulltoken committed
1895

Edward Thomson committed
1896 1897
	*out = index;
	return 0;
nulltoken committed
1898

Edward Thomson committed
1899 1900 1901 1902 1903
on_error:
	git_index_free(index);
	return error;
}

1904 1905
static git_iterator *iterator_given_or_empty(git_iterator **empty, git_iterator *given)
{
1906 1907
	git_iterator_options opts = GIT_ITERATOR_OPTIONS_INIT;

1908 1909 1910
	if (given)
		return given;

1911 1912 1913
	opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;

	if (git_iterator_for_nothing(empty, &opts) < 0)
1914 1915 1916 1917 1918 1919
		return NULL;

	return *empty;
}

int git_merge__iterators(
Edward Thomson committed
1920 1921
	git_index **out,
	git_repository *repo,
1922 1923 1924
	git_iterator *ancestor_iter,
	git_iterator *our_iter,
	git_iterator *theirs_iter,
1925
	const git_merge_options *given_opts)
Edward Thomson committed
1926
{
1927 1928 1929
	git_iterator *empty_ancestor = NULL,
		*empty_ours = NULL,
		*empty_theirs = NULL;
Edward Thomson committed
1930
	git_merge_diff_list *diff_list;
1931
	git_merge_options opts;
1932
	git_merge_file_options file_opts = GIT_MERGE_FILE_OPTIONS_INIT;
Edward Thomson committed
1933 1934 1935 1936 1937
	git_merge_diff *conflict;
	git_vector changes;
	size_t i;
	int error = 0;

1938
	assert(out && repo);
Edward Thomson committed
1939 1940

	*out = NULL;
nulltoken committed
1941

1942 1943
	GITERR_CHECK_VERSION(
		given_opts, GIT_MERGE_OPTIONS_VERSION, "git_merge_options");
1944

1945
	if ((error = merge_normalize_opts(repo, &opts, given_opts)) < 0)
Edward Thomson committed
1946 1947
		return error;

1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958
	file_opts.favor = opts.file_favor;
	file_opts.flags = opts.file_flags;

	/* use the git-inspired labels when virtual base building */
	if (opts.flags & GIT_MERGE__VIRTUAL_BASE) {
		file_opts.ancestor_label = "merged common ancestors";
		file_opts.our_label = "Temporary merge branch 1";
		file_opts.their_label = "Temporary merge branch 2";
		file_opts.flags |= GIT_MERGE_FILE_FAVOR__CONFLICTED;
	}

Edward Thomson committed
1959 1960
	diff_list = git_merge_diff_list__alloc(repo);
	GITERR_CHECK_ALLOC(diff_list);
nulltoken committed
1961

1962 1963 1964 1965 1966 1967
	ancestor_iter = iterator_given_or_empty(&empty_ancestor, ancestor_iter);
	our_iter = iterator_given_or_empty(&empty_ours, our_iter);
	theirs_iter = iterator_given_or_empty(&empty_theirs, theirs_iter);

	if ((error = git_merge_diff_list__find_differences(
			diff_list, ancestor_iter, our_iter, theirs_iter)) < 0 ||
Edward Thomson committed
1968
		(error = git_merge_diff_list__find_renames(repo, diff_list, &opts)) < 0)
Edward Thomson committed
1969
		goto done;
nulltoken committed
1970

Edward Thomson committed
1971 1972
	memcpy(&changes, &diff_list->conflicts, sizeof(git_vector));
	git_vector_clear(&diff_list->conflicts);
nulltoken committed
1973

Edward Thomson committed
1974 1975
	git_vector_foreach(&changes, i, conflict) {
		int resolved = 0;
nulltoken committed
1976

1977
		if ((error = merge_conflict_resolve(
1978
			&resolved, diff_list, conflict, &opts, &file_opts)) < 0)
Edward Thomson committed
1979
			goto done;
nulltoken committed
1980

1981
		if (!resolved) {
1982
			if ((opts.flags & GIT_MERGE_FAIL_ON_CONFLICT)) {
1983 1984 1985 1986 1987
				giterr_set(GITERR_MERGE, "merge conflicts exist");
				error = GIT_EMERGECONFLICT;
				goto done;
			}

Edward Thomson committed
1988
			git_vector_insert(&diff_list->conflicts, conflict);
1989
		}
Edward Thomson committed
1990
	}
nulltoken committed
1991

1992
	error = index_from_diff_list(out, diff_list,
1993
		(opts.flags & GIT_MERGE_SKIP_REUC));
Edward Thomson committed
1994 1995

done:
Vicent Marti committed
1996 1997 1998
	if (!given_opts || !given_opts->metric)
		git__free(opts.metric);

1999 2000
	git__free((char *)opts.default_driver);

Edward Thomson committed
2001
	git_merge_diff_list__free(diff_list);
2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017
	git_iterator_free(empty_ancestor);
	git_iterator_free(empty_ours);
	git_iterator_free(empty_theirs);

	return error;
}

int git_merge_trees(
	git_index **out,
	git_repository *repo,
	const git_tree *ancestor_tree,
	const git_tree *our_tree,
	const git_tree *their_tree,
	const git_merge_options *merge_opts)
{
	git_iterator *ancestor_iter = NULL, *our_iter = NULL, *their_iter = NULL;
2018
	git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
2019 2020
	int error;

2021 2022 2023 2024 2025 2026 2027 2028
	iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;

	if ((error = git_iterator_for_tree(
			&ancestor_iter, (git_tree *)ancestor_tree, &iter_opts)) < 0 ||
		(error = git_iterator_for_tree(
			&our_iter, (git_tree *)our_tree, &iter_opts)) < 0 ||
		(error = git_iterator_for_tree(
			&their_iter, (git_tree *)their_tree, &iter_opts)) < 0)
2029 2030 2031 2032 2033 2034 2035 2036 2037
		goto done;

	error = git_merge__iterators(
		out, repo, ancestor_iter, our_iter, their_iter, merge_opts);

done:
	git_iterator_free(ancestor_iter);
	git_iterator_free(our_iter);
	git_iterator_free(their_iter);
Edward Thomson committed
2038 2039 2040 2041

	return error;
}

2042 2043 2044
static int merge_annotated_commits(
	git_index **index_out,
	git_annotated_commit **base_out,
2045
	git_repository *repo,
2046 2047
	git_annotated_commit *our_commit,
	git_annotated_commit *their_commit,
2048
	size_t recursion_level,
2049 2050
	const git_merge_options *opts);

2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074
GIT_INLINE(int) insert_head_ids(
	git_array_oid_t *ids,
	const git_annotated_commit *annotated_commit)
{
	git_oid *id;
	size_t i;

	if (annotated_commit->type == GIT_ANNOTATED_COMMIT_REAL) {
		id = git_array_alloc(*ids);
		GITERR_CHECK_ALLOC(id);

		git_oid_cpy(id, git_commit_id(annotated_commit->commit));
	} else {
		for (i = 0; i < annotated_commit->parents.size; i++) {
			id = git_array_alloc(*ids);
			GITERR_CHECK_ALLOC(id);

			git_oid_cpy(id, &annotated_commit->parents.ptr[i]);
		}
	}

	return 0;
}

2075
static int create_virtual_base(
2076
	git_annotated_commit **out,
2077
	git_repository *repo,
2078 2079
	git_annotated_commit *one,
	git_annotated_commit *two,
2080
	const git_merge_options *opts,
2081
	size_t recursion_level)
2082
{
2083
	git_annotated_commit *result = NULL;
2084
	git_index *index = NULL;
2085
	git_merge_options virtual_opts = GIT_MERGE_OPTIONS_INIT;
2086

2087 2088 2089 2090 2091 2092 2093 2094 2095
	/* Conflicts in the merge base creation do not propagate to conflicts
	 * in the result; the conflicted base will act as the common ancestor.
	 */
	if (opts)
		memcpy(&virtual_opts, opts, sizeof(git_merge_options));

	virtual_opts.flags &= ~GIT_MERGE_FAIL_ON_CONFLICT;
	virtual_opts.flags |= GIT_MERGE__VIRTUAL_BASE;

2096
	if ((merge_annotated_commits(&index, NULL, repo, one, two,
2097
			recursion_level + 1, &virtual_opts)) < 0)
2098
		return -1;
2099

2100 2101
	result = git__calloc(1, sizeof(git_annotated_commit));
	GITERR_CHECK_ALLOC(result);
2102 2103
	result->type = GIT_ANNOTATED_COMMIT_VIRTUAL;
	result->index = index;
2104

2105 2106
	insert_head_ids(&result->parents, one);
	insert_head_ids(&result->parents, two);
2107

2108
	*out = result;
2109 2110
	return 0;
}
2111

2112 2113 2114 2115 2116
static int compute_base(
	git_annotated_commit **out,
	git_repository *repo,
	const git_annotated_commit *one,
	const git_annotated_commit *two,
2117
	const git_merge_options *given_opts,
2118 2119 2120 2121 2122
	size_t recursion_level)
{
	git_array_oid_t head_ids = GIT_ARRAY_INIT;
	git_oidarray bases = {0};
	git_annotated_commit *base = NULL, *other = NULL, *new_base = NULL;
2123
	git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
2124 2125
	size_t i;
	int error;
2126

2127
	*out = NULL;
2128

2129 2130 2131
	if (given_opts)
		memcpy(&opts, given_opts, sizeof(git_merge_options));

2132 2133
	if ((error = insert_head_ids(&head_ids, one)) < 0 ||
		(error = insert_head_ids(&head_ids, two)) < 0)
2134 2135
		goto done;

2136 2137 2138
	if ((error = git_merge_bases_many(&bases, repo,
			head_ids.size, head_ids.ptr)) < 0 ||
		(error = git_annotated_commit_lookup(&base, repo, &bases.ids[0])) < 0 ||
2139
		(opts.flags & GIT_MERGE_NO_RECURSIVE))
2140
		goto done;
2141

2142 2143
	for (i = 1; i < bases.count; i++) {
		recursion_level++;
2144

2145 2146 2147
		if (opts.recursion_limit && recursion_level > opts.recursion_limit)
			break;

2148 2149
		if ((error = git_annotated_commit_lookup(&other, repo,
				&bases.ids[i])) < 0 ||
2150
			(error = create_virtual_base(&new_base, repo, base, other, &opts,
2151
				recursion_level)) < 0)
2152 2153
			goto done;

2154 2155
		git_annotated_commit_free(base);
		git_annotated_commit_free(other);
2156

2157 2158 2159
		base = new_base;
		new_base = NULL;
		other = NULL;
2160 2161 2162
	}

done:
2163 2164 2165 2166
	if (error == 0)
		*out = base;
	else
		git_annotated_commit_free(base);
2167

2168 2169 2170 2171
	git_annotated_commit_free(other);
	git_annotated_commit_free(new_base);
	git_oidarray_free(&bases);
	git_array_clear(head_ids);
2172 2173
	return error;
}
2174

2175 2176 2177 2178 2179 2180 2181 2182 2183 2184
static int iterator_for_annotated_commit(
	git_iterator **out,
	git_annotated_commit *commit)
{
	git_iterator_options opts = GIT_ITERATOR_OPTIONS_INIT;
	int error;

	opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;

	if (commit == NULL) {
2185
		error = git_iterator_for_nothing(out, &opts);
2186
	} else if (commit->type == GIT_ANNOTATED_COMMIT_VIRTUAL) {
2187
		error = git_iterator_for_index(out, git_index_owner(commit->index), commit->index, &opts);
2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199
	} else {
		if (!commit->tree &&
			(error = git_commit_tree(&commit->tree, commit->commit)) < 0)
			goto done;

		error = git_iterator_for_tree(out, commit->tree, &opts);
	}

done:
	return error;
}

2200 2201 2202
static int merge_annotated_commits(
	git_index **index_out,
	git_annotated_commit **base_out,
2203
	git_repository *repo,
2204 2205
	git_annotated_commit *ours,
	git_annotated_commit *theirs,
2206
	size_t recursion_level,
2207
	const git_merge_options *opts)
2208
{
2209
	git_annotated_commit *base = NULL;
2210
	git_iterator *base_iter = NULL, *our_iter = NULL, *their_iter = NULL;
2211
	int error;
2212

2213
	if ((error = compute_base(&base, repo, ours, theirs, opts,
2214
		recursion_level)) < 0) {
2215

2216 2217
		if (error != GIT_ENOTFOUND)
			goto done;
2218

2219 2220
		giterr_clear();
	}
2221

2222 2223 2224 2225 2226
	if ((error = iterator_for_annotated_commit(&base_iter, base)) < 0 ||
		(error = iterator_for_annotated_commit(&our_iter, ours)) < 0 ||
		(error = iterator_for_annotated_commit(&their_iter, theirs)) < 0 ||
		(error = git_merge__iterators(index_out, repo, base_iter, our_iter,
			their_iter, opts)) < 0)
2227 2228
		goto done;

2229 2230 2231 2232
	if (base_out) {
		*base_out = base;
		base = NULL;
	}
2233 2234

done:
2235
	git_annotated_commit_free(base);
2236 2237 2238
	git_iterator_free(base_iter);
	git_iterator_free(our_iter);
	git_iterator_free(their_iter);
2239 2240 2241
	return error;
}

2242

2243 2244 2245 2246 2247 2248 2249
int git_merge_commits(
	git_index **out,
	git_repository *repo,
	const git_commit *our_commit,
	const git_commit *their_commit,
	const git_merge_options *opts)
{
2250 2251 2252 2253 2254 2255
	git_annotated_commit *ours = NULL, *theirs = NULL, *base = NULL;
	int error = 0;

	if ((error = git_annotated_commit_from_commit(&ours, (git_commit *)our_commit)) < 0 ||
		(error = git_annotated_commit_from_commit(&theirs, (git_commit *)their_commit)) < 0)
		goto done;
2256

2257
	error = merge_annotated_commits(out, &base, repo, ours, theirs, 0, opts);
2258

2259 2260 2261 2262
done:
	git_annotated_commit_free(ours);
	git_annotated_commit_free(theirs);
	git_annotated_commit_free(base);
2263 2264 2265
	return error;
}

Edward Thomson committed
2266 2267 2268 2269
/* Merge setup / cleanup */

static int write_merge_head(
	git_repository *repo,
2270
	const git_annotated_commit *heads[],
Edward Thomson committed
2271 2272 2273 2274 2275 2276 2277 2278 2279
	size_t heads_len)
{
	git_filebuf file = GIT_FILEBUF_INIT;
	git_buf file_path = GIT_BUF_INIT;
	size_t i;
	int error = 0;

	assert(repo && heads);

2280
	if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_HEAD_FILE)) < 0 ||
2281
		(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0)
Edward Thomson committed
2282 2283 2284
		goto cleanup;

	for (i = 0; i < heads_len; i++) {
2285
		if ((error = git_filebuf_printf(&file, "%s\n", heads[i]->id_str)) < 0)
Edward Thomson committed
2286 2287 2288
			goto cleanup;
	}

2289
	error = git_filebuf_commit(&file);
Edward Thomson committed
2290 2291 2292 2293 2294 2295 2296 2297 2298 2299

cleanup:
	if (error < 0)
		git_filebuf_cleanup(&file);

	git_buf_free(&file_path);

	return error;
}

2300
static int write_merge_mode(git_repository *repo)
Edward Thomson committed
2301 2302 2303 2304 2305 2306 2307
{
	git_filebuf file = GIT_FILEBUF_INIT;
	git_buf file_path = GIT_BUF_INIT;
	int error = 0;

	assert(repo);

2308
	if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MODE_FILE)) < 0 ||
2309
		(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0)
Edward Thomson committed
2310 2311
		goto cleanup;

2312 2313
	if ((error = git_filebuf_write(&file, "no-ff", 5)) < 0)
		goto cleanup;
2314

2315
	error = git_filebuf_commit(&file);
Edward Thomson committed
2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326

cleanup:
	if (error < 0)
		git_filebuf_cleanup(&file);

	git_buf_free(&file_path);

	return error;
}

struct merge_msg_entry {
2327
	const git_annotated_commit *merge_head;
Edward Thomson committed
2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514
	bool written;
};

static int msg_entry_is_branch(
	const struct merge_msg_entry *entry,
	git_vector *entries)
{
	GIT_UNUSED(entries);

	return (entry->written == 0 &&
		entry->merge_head->remote_url == NULL &&
		entry->merge_head->ref_name != NULL &&
		git__strncmp(GIT_REFS_HEADS_DIR, entry->merge_head->ref_name, strlen(GIT_REFS_HEADS_DIR)) == 0);
}

static int msg_entry_is_tracking(
	const struct merge_msg_entry *entry,
	git_vector *entries)
{
	GIT_UNUSED(entries);

	return (entry->written == 0 &&
		entry->merge_head->remote_url == NULL &&
		entry->merge_head->ref_name != NULL &&
		git__strncmp(GIT_REFS_REMOTES_DIR, entry->merge_head->ref_name, strlen(GIT_REFS_REMOTES_DIR)) == 0);
}

static int msg_entry_is_tag(
	const struct merge_msg_entry *entry,
	git_vector *entries)
{
	GIT_UNUSED(entries);

	return (entry->written == 0 &&
		entry->merge_head->remote_url == NULL &&
		entry->merge_head->ref_name != NULL &&
		git__strncmp(GIT_REFS_TAGS_DIR, entry->merge_head->ref_name, strlen(GIT_REFS_TAGS_DIR)) == 0);
}

static int msg_entry_is_remote(
	const struct merge_msg_entry *entry,
	git_vector *entries)
{
	if (entry->written == 0 &&
		entry->merge_head->remote_url != NULL &&
		entry->merge_head->ref_name != NULL &&
		git__strncmp(GIT_REFS_HEADS_DIR, entry->merge_head->ref_name, strlen(GIT_REFS_HEADS_DIR)) == 0)
	{
		struct merge_msg_entry *existing;

		/* Match only branches from the same remote */
		if (entries->length == 0)
			return 1;

		existing = git_vector_get(entries, 0);

		return (git__strcmp(existing->merge_head->remote_url,
			entry->merge_head->remote_url) == 0);
	}

	return 0;
}

static int msg_entry_is_oid(
	const struct merge_msg_entry *merge_msg_entry)
{
	return (merge_msg_entry->written == 0 &&
		merge_msg_entry->merge_head->ref_name == NULL &&
		merge_msg_entry->merge_head->remote_url == NULL);
}

static int merge_msg_entry_written(
	const struct merge_msg_entry *merge_msg_entry)
{
	return (merge_msg_entry->written == 1);
}

static int merge_msg_entries(
	git_vector *v,
	const struct merge_msg_entry *entries,
	size_t len,
	int (*match)(const struct merge_msg_entry *entry, git_vector *entries))
{
	size_t i;
	int matches, total = 0;

	git_vector_clear(v);

	for (i = 0; i < len; i++) {
		if ((matches = match(&entries[i], v)) < 0)
			return matches;
		else if (!matches)
			continue;

		git_vector_insert(v, (struct merge_msg_entry *)&entries[i]);
		total++;
	}

	return total;
}

static int merge_msg_write_entries(
	git_filebuf *file,
	git_vector *entries,
	const char *item_name,
	const char *item_plural_name,
	size_t ref_name_skip,
	const char *source,
	char sep)
{
	struct merge_msg_entry *entry;
	size_t i;
	int error = 0;

	if (entries->length == 0)
		return 0;

	if (sep && (error = git_filebuf_printf(file, "%c ", sep)) < 0)
		goto done;

	if ((error = git_filebuf_printf(file, "%s ",
		(entries->length == 1) ? item_name : item_plural_name)) < 0)
		goto done;

	git_vector_foreach(entries, i, entry) {
		if (i > 0 &&
			(error = git_filebuf_printf(file, "%s", (i == entries->length - 1) ? " and " : ", ")) < 0)
			goto done;

		if ((error = git_filebuf_printf(file, "'%s'", entry->merge_head->ref_name + ref_name_skip)) < 0)
			goto done;

		entry->written = 1;
	}

	if (source)
		error = git_filebuf_printf(file, " of %s", source);

done:
	return error;
}

static int merge_msg_write_branches(
	git_filebuf *file,
	git_vector *entries,
	char sep)
{
	return merge_msg_write_entries(file, entries,
		"branch", "branches", strlen(GIT_REFS_HEADS_DIR), NULL, sep);
}

static int merge_msg_write_tracking(
	git_filebuf *file,
	git_vector *entries,
	char sep)
{
	return merge_msg_write_entries(file, entries,
		"remote-tracking branch", "remote-tracking branches", 0, NULL, sep);
}

static int merge_msg_write_tags(
	git_filebuf *file,
	git_vector *entries,
	char sep)
{
	return merge_msg_write_entries(file, entries,
		"tag", "tags", strlen(GIT_REFS_TAGS_DIR), NULL, sep);
}

static int merge_msg_write_remotes(
	git_filebuf *file,
	git_vector *entries,
	char sep)
{
	const char *source;

	if (entries->length == 0)
		return 0;

	source = ((struct merge_msg_entry *)entries->contents[0])->merge_head->remote_url;

	return merge_msg_write_entries(file, entries,
		"branch", "branches", strlen(GIT_REFS_HEADS_DIR), source, sep);
}

static int write_merge_msg(
	git_repository *repo,
2515
	const git_annotated_commit *heads[],
Edward Thomson committed
2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528
	size_t heads_len)
{
	git_filebuf file = GIT_FILEBUF_INIT;
	git_buf file_path = GIT_BUF_INIT;
	struct merge_msg_entry *entries;
	git_vector matching = GIT_VECTOR_INIT;
	size_t i;
	char sep = 0;
	int error = 0;

	assert(repo && heads);

	entries = git__calloc(heads_len, sizeof(struct merge_msg_entry));
2529
	GITERR_CHECK_ALLOC(entries);
Edward Thomson committed
2530

2531 2532
	if (git_vector_init(&matching, heads_len, NULL) < 0) {
		git__free(entries);
Edward Thomson committed
2533
		return -1;
2534
	}
Edward Thomson committed
2535 2536 2537 2538

	for (i = 0; i < heads_len; i++)
		entries[i].merge_head = heads[i];

2539
	if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
2540
		(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0 ||
Edward Thomson committed
2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558
		(error = git_filebuf_write(&file, "Merge ", 6)) < 0)
		goto cleanup;

	/*
	 * This is to emulate the format of MERGE_MSG by core git.
	 *
	 * Core git will write all the commits specified by OID, in the order
	 * provided, until the first named branch or tag is reached, at which
	 * point all branches will be written in the order provided, then all
	 * tags, then all remote tracking branches and finally all commits that
	 * were specified by OID that were not already written.
	 *
	 * Yes.  Really.
	 */
	for (i = 0; i < heads_len; i++) {
		if (!msg_entry_is_oid(&entries[i]))
			break;

2559 2560
		if ((error = git_filebuf_printf(&file,
			"%scommit '%s'", (i > 0) ? "; " : "",
2561
			entries[i].merge_head->id_str)) < 0)
Edward Thomson committed
2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582
			goto cleanup;

		entries[i].written = 1;
	}

	if (i)
		sep = ';';

	if ((error = merge_msg_entries(&matching, entries, heads_len, msg_entry_is_branch)) < 0 ||
		(error = merge_msg_write_branches(&file, &matching, sep)) < 0)
		goto cleanup;

	if (matching.length)
		sep =',';

	if ((error = merge_msg_entries(&matching, entries, heads_len, msg_entry_is_tracking)) < 0 ||
		(error = merge_msg_write_tracking(&file, &matching, sep)) < 0)
		goto cleanup;

	if (matching.length)
		sep =',';
2583

Edward Thomson committed
2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607
	if ((error = merge_msg_entries(&matching, entries, heads_len, msg_entry_is_tag)) < 0 ||
		(error = merge_msg_write_tags(&file, &matching, sep)) < 0)
		goto cleanup;

	if (matching.length)
		sep =',';

	/* We should never be called with multiple remote branches, but handle
	 * it in case we are... */
	while ((error = merge_msg_entries(&matching, entries, heads_len, msg_entry_is_remote)) > 0) {
		if ((error = merge_msg_write_remotes(&file, &matching, sep)) < 0)
			goto cleanup;

		if (matching.length)
			sep =',';
	}

	if (error < 0)
		goto cleanup;

	for (i = 0; i < heads_len; i++) {
		if (merge_msg_entry_written(&entries[i]))
			continue;

2608
		if ((error = git_filebuf_printf(&file, "; commit '%s'",
2609
			entries[i].merge_head->id_str)) < 0)
Edward Thomson committed
2610 2611 2612 2613
			goto cleanup;
	}

	if ((error = git_filebuf_printf(&file, "\n")) < 0 ||
2614
		(error = git_filebuf_commit(&file)) < 0)
Edward Thomson committed
2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628
		goto cleanup;

cleanup:
	if (error < 0)
		git_filebuf_cleanup(&file);

	git_buf_free(&file_path);

	git_vector_free(&matching);
	git__free(entries);

	return error;
}

2629 2630
int git_merge__setup(
	git_repository *repo,
2631 2632
	const git_annotated_commit *our_head,
	const git_annotated_commit *heads[],
2633 2634 2635 2636 2637 2638
	size_t heads_len)
{
	int error = 0;

	assert (repo && our_head && heads);

2639
	if ((error = git_repository__set_orig_head(repo, git_annotated_commit_id(our_head))) == 0 &&
2640 2641 2642 2643 2644 2645 2646 2647
		(error = write_merge_head(repo, heads, heads_len)) == 0 &&
		(error = write_merge_mode(repo)) == 0) {
		error = write_merge_msg(repo, heads, heads_len);
	}

	return error;
}

2648 2649 2650
/* Merge branches */

static int merge_ancestor_head(
2651
	git_annotated_commit **ancestor_head,
2652
	git_repository *repo,
2653 2654
	const git_annotated_commit *our_head,
	const git_annotated_commit **their_heads,
2655 2656 2657
	size_t their_heads_len)
{
	git_oid *oids, ancestor_oid;
2658
	size_t i, alloc_len;
2659 2660 2661 2662
	int error = 0;

	assert(repo && our_head && their_heads);

2663 2664
	GITERR_CHECK_ALLOC_ADD(&alloc_len, their_heads_len, 1);
	oids = git__calloc(alloc_len, sizeof(git_oid));
2665 2666 2667 2668 2669
	GITERR_CHECK_ALLOC(oids);

	git_oid_cpy(&oids[0], git_commit_id(our_head->commit));

	for (i = 0; i < their_heads_len; i++)
2670
		git_oid_cpy(&oids[i + 1], git_annotated_commit_id(their_heads[i]));
2671 2672 2673 2674

	if ((error = git_merge_base_many(&ancestor_oid, repo, their_heads_len + 1, oids)) < 0)
		goto on_error;

2675
	error = git_annotated_commit_lookup(ancestor_head, repo, &ancestor_oid);
2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694

on_error:
	git__free(oids);
	return error;
}

const char *merge_their_label(const char *branchname)
{
	const char *slash;

	if ((slash = strrchr(branchname, '/')) == NULL)
		return branchname;

	if (*(slash+1) == '\0')
		return "theirs";

	return slash+1;
}

2695
static int merge_normalize_checkout_opts(
2696
	git_checkout_options *out,
2697
	git_repository *repo,
2698
	const git_checkout_options *given_checkout_opts,
2699
	unsigned int checkout_strategy,
2700
	git_annotated_commit *ancestor,
2701
	const git_annotated_commit *our_head,
2702 2703
	const git_annotated_commit **their_heads,
	size_t their_heads_len)
2704
{
2705
	git_checkout_options default_checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
2706 2707 2708 2709
	int error = 0;

	GIT_UNUSED(repo);

2710
	if (given_checkout_opts != NULL)
2711 2712 2713
		memcpy(out, given_checkout_opts, sizeof(git_checkout_options));
	else
		memcpy(out, &default_checkout_opts, sizeof(git_checkout_options));
2714

2715
	out->checkout_strategy = checkout_strategy;
2716

2717
	if (!out->ancestor_label) {
2718
		if (ancestor && ancestor->type == GIT_ANNOTATED_COMMIT_REAL)
2719
			out->ancestor_label = git_commit_summary(ancestor->commit);
2720
		else if (ancestor)
2721
			out->ancestor_label = "merged common ancestors";
2722 2723
		else
			out->ancestor_label = "empty base";
2724 2725
	}

2726
	if (!out->our_label) {
2727
		if (our_head && our_head->ref_name)
2728
			out->our_label = our_head->ref_name;
2729
		else
2730
			out->our_label = "ours";
2731
	}
2732

2733
	if (!out->their_label) {
2734
		if (their_heads_len == 1 && their_heads[0]->ref_name)
2735
			out->their_label = merge_their_label(their_heads[0]->ref_name);
2736
		else if (their_heads_len == 1)
2737
			out->their_label = their_heads[0]->id_str;
2738
		else
2739
			out->their_label = "theirs";
2740 2741 2742 2743 2744 2745 2746 2747 2748 2749
	}

	return error;
}

static int merge_check_index(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths)
{
	git_tree *head_tree = NULL;
	git_index *index_repo = NULL;
	git_iterator *iter_repo = NULL, *iter_new = NULL;
2750
	git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779
	git_diff *staged_diff_list = NULL, *index_diff_list = NULL;
	git_diff_delta *delta;
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
	git_vector staged_paths = GIT_VECTOR_INIT;
	size_t i;
	int error = 0;

	GIT_UNUSED(merged_paths);

	*conflicts = 0;

	/* No staged changes may exist unless the change staged is identical to
	 * the result of the merge.  This allows one to apply to merge manually,
	 * then run merge.  Any other staged change would be overwritten by
	 * a reset merge.
	 */
	if ((error = git_repository_head_tree(&head_tree, repo)) < 0 ||
		(error = git_repository_index(&index_repo, repo)) < 0 ||
		(error = git_diff_tree_to_index(&staged_diff_list, repo, head_tree, index_repo, &opts)) < 0)
		goto done;

	if (staged_diff_list->deltas.length == 0)
		goto done;

	git_vector_foreach(&staged_diff_list->deltas, i, delta) {
		if ((error = git_vector_insert(&staged_paths, (char *)delta->new_file.path)) < 0)
			goto done;
	}

2780
	iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
2781 2782
	iter_opts.pathlist.strings = (char **)staged_paths.contents;
	iter_opts.pathlist.count = staged_paths.length;
2783

2784 2785
	if ((error = git_iterator_for_index(&iter_repo, repo, index_repo, &iter_opts)) < 0 ||
		(error = git_iterator_for_index(&iter_new, repo, index_new, &iter_opts)) < 0 ||
2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808
		(error = git_diff__from_iterators(&index_diff_list, repo, iter_repo, iter_new, &opts)) < 0)
		goto done;

	*conflicts = index_diff_list->deltas.length;

done:
	git_tree_free(head_tree);
	git_index_free(index_repo);
	git_iterator_free(iter_repo);
	git_iterator_free(iter_new);
	git_diff_free(staged_diff_list);
	git_diff_free(index_diff_list);
	git_vector_free(&staged_paths);

	return error;
}

static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths)
{
	git_diff *wd_diff_list = NULL;
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
	int error = 0;

Russell Belfer committed
2809 2810
	GIT_UNUSED(index_new);

2811 2812
	*conflicts = 0;

2813 2814 2815 2816 2817 2818 2819 2820 2821 2822
	/* We need to have merged at least 1 file for the possibility to exist to
	 * have conflicts with the workdir. Passing 0 as the pathspec count paramter
	 * will consider all files in the working directory, that is, we may detect
	 * a conflict if there were untracked files in the workdir prior to starting
	 * the merge. This typically happens when cherry-picking a commmit whose
	 * changes have already been applied.
	 */
	if (merged_paths->length == 0)
		return 0;

2823 2824 2825 2826 2827 2828
	opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED;

	/* Workdir changes may exist iff they do not conflict with changes that
	 * will be applied by the merge (including conflicts).  Ensure that there
	 * are no changes in the workdir to these paths.
	 */
2829
	opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
2830 2831
	opts.pathspec.count = merged_paths->length;
	opts.pathspec.strings = (char **)merged_paths->contents;
2832
	opts.ignore_submodules = GIT_SUBMODULE_IGNORE_ALL;
2833

2834
	if ((error = git_diff_index_to_workdir(&wd_diff_list, repo, NULL, &opts)) < 0)
2835 2836 2837 2838 2839 2840 2841 2842 2843 2844
		goto done;

	*conflicts = wd_diff_list->deltas.length;

done:
	git_diff_free(wd_diff_list);

	return error;
}

2845
int git_merge__check_result(git_repository *repo, git_index *index_new)
2846
{
2847 2848
	git_tree *head_tree = NULL;
	git_iterator *iter_head = NULL, *iter_new = NULL;
2849
	git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
2850 2851 2852
	git_diff *merged_list = NULL;
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
	git_diff_delta *delta;
2853
	git_vector paths = GIT_VECTOR_INIT;
2854
	size_t i, index_conflicts = 0, wd_conflicts = 0, conflicts;
2855 2856 2857
	const git_index_entry *e;
	int error = 0;

2858 2859
	iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;

2860
	if ((error = git_repository_head_tree(&head_tree, repo)) < 0 ||
2861
		(error = git_iterator_for_tree(&iter_head, head_tree, &iter_opts)) < 0 ||
2862
		(error = git_iterator_for_index(&iter_new, repo, index_new, &iter_opts)) < 0 ||
2863
		(error = git_diff__from_iterators(&merged_list, repo, iter_head, iter_new, &opts)) < 0)
2864 2865
		goto done;

2866 2867 2868
	git_vector_foreach(&merged_list->deltas, i, delta) {
		if ((error = git_vector_insert(&paths, (char *)delta->new_file.path)) < 0)
			goto done;
2869 2870 2871 2872 2873
	}

	for (i = 0; i < git_index_entrycount(index_new); i++) {
		e = git_index_get_byindex(index_new, i);

2874
		if (git_index_entry_is_conflict(e) &&
2875 2876
			(git_vector_last(&paths) == NULL ||
			strcmp(git_vector_last(&paths), e->path) != 0)) {
2877

2878 2879 2880
			if ((error = git_vector_insert(&paths, (char *)e->path)) < 0)
				goto done;
		}
2881 2882
	}

2883 2884 2885 2886
	/* Make sure the index and workdir state do not prevent merging */
	if ((error = merge_check_index(&index_conflicts, repo, index_new, &paths)) < 0 ||
		(error = merge_check_workdir(&wd_conflicts, repo, index_new, &paths)) < 0)
		goto done;
2887

2888
	if ((conflicts = index_conflicts + wd_conflicts) > 0) {
2889
		giterr_set(GITERR_MERGE, "%" PRIuZ " uncommitted change%s would be overwritten by merge",
2890
			conflicts, (conflicts != 1) ? "s" : "");
2891
		error = GIT_ECONFLICT;
2892 2893 2894
	}

done:
2895 2896 2897 2898 2899
	git_vector_free(&paths);
	git_tree_free(head_tree);
	git_iterator_free(iter_head);
	git_iterator_free(iter_new);
	git_diff_free(merged_list);
2900 2901 2902 2903

	return error;
}

2904 2905 2906 2907 2908 2909 2910 2911 2912 2913
int git_merge__append_conflicts_to_merge_msg(
	git_repository *repo,
	git_index *index)
{
	git_filebuf file = GIT_FILEBUF_INIT;
	git_buf file_path = GIT_BUF_INIT;
	const char *last = NULL;
	size_t i;
	int error;

2914 2915 2916
	if (!git_index_has_conflicts(index))
		return 0;

2917
	if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
2918 2919 2920
		(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_APPEND, GIT_MERGE_FILE_MODE)) < 0)
		goto cleanup;

2921
	git_filebuf_printf(&file, "\nConflicts:\n");
2922 2923 2924 2925

	for (i = 0; i < git_index_entrycount(index); i++) {
		const git_index_entry *e = git_index_get_byindex(index, i);

2926
		if (!git_index_entry_is_conflict(e))
2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945
			continue;

		if (last == NULL || strcmp(e->path, last) != 0)
			git_filebuf_printf(&file, "\t%s\n", e->path);

		last = e->path;
	}

	error = git_filebuf_commit(&file);

cleanup:
	if (error < 0)
		git_filebuf_cleanup(&file);

	git_buf_free(&file_path);

	return error;
}

2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956
static int merge_state_cleanup(git_repository *repo)
{
	const char *state_files[] = {
		GIT_MERGE_HEAD_FILE,
		GIT_MERGE_MODE_FILE,
		GIT_MERGE_MSG_FILE,
	};

	return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files));
}

2957
static int merge_heads(
2958 2959
	git_annotated_commit **ancestor_head_out,
	git_annotated_commit **our_head_out,
2960
	git_repository *repo,
2961
	const git_annotated_commit **their_heads,
2962
	size_t their_heads_len)
2963
{
2964
	git_annotated_commit *ancestor_head = NULL, *our_head = NULL;
2965
	git_reference *our_ref = NULL;
2966 2967 2968 2969 2970 2971 2972 2973 2974
	int error = 0;

	*ancestor_head_out = NULL;
	*our_head_out = NULL;

	if ((error = git_repository__ensure_not_bare(repo, "merge")) < 0)
		goto done;

	if ((error = git_reference_lookup(&our_ref, repo, GIT_HEAD_FILE)) < 0 ||
2975
		(error = git_annotated_commit_from_ref(&our_head, repo, our_ref)) < 0)
2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990
		goto done;

	if ((error = merge_ancestor_head(&ancestor_head, repo, our_head, their_heads, their_heads_len)) < 0) {
		if (error != GIT_ENOTFOUND)
			goto done;

		giterr_clear();
		error = 0;
	}

	*ancestor_head_out = ancestor_head;
	*our_head_out = our_head;

done:
	if (error < 0) {
2991 2992
		git_annotated_commit_free(ancestor_head);
		git_annotated_commit_free(our_head);
2993 2994 2995 2996 2997 2998 2999
	}

	git_reference_free(our_ref);

	return error;
}

3000
static int merge_preference(git_merge_preference_t *out, git_repository *repo)
3001 3002 3003 3004 3005
{
	git_config *config;
	const char *value;
	int bool_value, error = 0;

3006
	*out = GIT_MERGE_PREFERENCE_NONE;
3007

Edward Thomson committed
3008
	if ((error = git_repository_config_snapshot(&config, repo)) < 0)
3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021
		goto done;

	if ((error = git_config_get_string(&value, config, "merge.ff")) < 0) {
		if (error == GIT_ENOTFOUND) {
			giterr_clear();
			error = 0;
		}

		goto done;
	}

	if (git_config_parse_bool(&bool_value, value) == 0) {
		if (!bool_value)
3022
			*out |= GIT_MERGE_PREFERENCE_NO_FASTFORWARD;
3023 3024
	} else {
		if (strcasecmp(value, "only") == 0)
3025
			*out |= GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY;
3026 3027 3028 3029 3030 3031 3032
	}

done:
	git_config_free(config);
	return error;
}

3033
int git_merge_analysis(
3034
	git_merge_analysis_t *analysis_out,
3035
	git_merge_preference_t *preference_out,
3036
	git_repository *repo,
3037
	const git_annotated_commit **their_heads,
3038 3039
	size_t their_heads_len)
{
3040
	git_annotated_commit *ancestor_head = NULL, *our_head = NULL;
3041 3042
	int error = 0;

3043
	assert(analysis_out && preference_out && repo && their_heads);
3044

3045
	if (their_heads_len != 1) {
3046
		giterr_set(GITERR_MERGE, "can only merge a single branch");
3047 3048 3049 3050
		error = -1;
		goto done;
	}

3051
	*analysis_out = GIT_MERGE_ANALYSIS_NONE;
3052

3053
	if ((error = merge_preference(preference_out, repo)) < 0)
3054
		goto done;
3055

3056
	if (git_repository_head_unborn(repo)) {
3057
		*analysis_out |= GIT_MERGE_ANALYSIS_FASTFORWARD | GIT_MERGE_ANALYSIS_UNBORN;
3058
		goto done;
3059 3060
	}

3061 3062
	if ((error = merge_heads(&ancestor_head, &our_head, repo, their_heads, their_heads_len)) < 0)
		goto done;
3063

3064
	/* We're up-to-date if we're trying to merge our own common ancestor. */
3065 3066
	if (ancestor_head && git_oid_equal(
		git_annotated_commit_id(ancestor_head), git_annotated_commit_id(their_heads[0])))
3067
		*analysis_out |= GIT_MERGE_ANALYSIS_UP_TO_DATE;
3068

3069
	/* We're fastforwardable if we're our own common ancestor. */
3070 3071
	else if (ancestor_head && git_oid_equal(
		git_annotated_commit_id(ancestor_head), git_annotated_commit_id(our_head)))
3072
		*analysis_out |= GIT_MERGE_ANALYSIS_FASTFORWARD | GIT_MERGE_ANALYSIS_NORMAL;
3073

3074 3075
	/* Otherwise, just a normal merge is possible. */
	else
3076
		*analysis_out |= GIT_MERGE_ANALYSIS_NORMAL;
3077

3078
done:
3079 3080
	git_annotated_commit_free(ancestor_head);
	git_annotated_commit_free(our_head);
3081 3082
	return error;
}
3083 3084 3085

int git_merge(
	git_repository *repo,
3086
	const git_annotated_commit **their_heads,
3087
	size_t their_heads_len,
3088
	const git_merge_options *merge_opts,
3089
	const git_checkout_options *given_checkout_opts)
3090 3091
{
	git_reference *our_ref = NULL;
3092
	git_checkout_options checkout_opts;
3093
	git_annotated_commit *our_head = NULL, *base = NULL;
3094
	git_index *index = NULL;
3095
	git_indexwriter indexwriter = GIT_INDEXWRITER_INIT;
3096
	unsigned int checkout_strategy;
3097
	int error = 0;
3098

3099
	assert(repo && their_heads);
3100 3101

	if (their_heads_len != 1) {
3102
		giterr_set(GITERR_MERGE, "can only merge a single branch");
3103 3104 3105
		return -1;
	}

3106 3107
	if ((error = git_repository__ensure_not_bare(repo, "merge")) < 0)
		goto done;
3108

3109 3110 3111
	checkout_strategy = given_checkout_opts ?
		given_checkout_opts->checkout_strategy :
		GIT_CHECKOUT_SAFE;
3112

3113 3114 3115
	if ((error = git_indexwriter_init_for_operation(&indexwriter, repo,
		&checkout_strategy)) < 0)
		goto done;
3116

3117 3118 3119 3120 3121
	/* Write the merge setup files to the repository. */
	if ((error = git_annotated_commit_from_head(&our_head, repo)) < 0 ||
		(error = git_merge__setup(repo, our_head, their_heads,
			their_heads_len)) < 0)
		goto done;
3122

3123
	/* TODO: octopus */
3124

3125
	if ((error = merge_annotated_commits(&index, &base, repo, our_head,
3126
			(git_annotated_commit *)their_heads[0], 0, merge_opts)) < 0 ||
3127
		(error = git_merge__check_result(repo, index)) < 0 ||
3128 3129
		(error = git_merge__append_conflicts_to_merge_msg(repo, index)) < 0)
		goto done;
3130

3131
	/* check out the merge results */
3132

3133 3134
	if ((error = merge_normalize_checkout_opts(&checkout_opts, repo,
			given_checkout_opts, checkout_strategy,
3135
			base, our_head, their_heads, their_heads_len)) < 0 ||
3136 3137 3138 3139
		(error = git_checkout_index(repo, index, &checkout_opts)) < 0)
		goto done;

	error = git_indexwriter_commit(&indexwriter);
3140 3141

done:
3142 3143
	if (error < 0)
		merge_state_cleanup(repo);
3144

3145
	git_indexwriter_cleanup(&indexwriter);
3146
	git_index_free(index);
3147
	git_annotated_commit_free(our_head);
3148
	git_annotated_commit_free(base);
3149 3150 3151 3152 3153
	git_reference_free(our_ref);

	return error;
}

3154
int git_merge_init_options(git_merge_options *opts, unsigned int version)
3155
{
3156 3157 3158
	GIT_INIT_STRUCTURE_FROM_TEMPLATE(
		opts, version, git_merge_options, GIT_MERGE_OPTIONS_INIT);
	return 0;
3159
}
3160

3161
int git_merge_file_init_input(git_merge_file_input *input, unsigned int version)
3162
{
3163 3164 3165
	GIT_INIT_STRUCTURE_FROM_TEMPLATE(
		input, version, git_merge_file_input, GIT_MERGE_FILE_INPUT_INIT);
	return 0;
3166 3167
}

3168 3169
int git_merge_file_init_options(
	git_merge_file_options *opts, unsigned int version)
3170
{
3171 3172 3173
	GIT_INIT_STRUCTURE_FROM_TEMPLATE(
		opts, version, git_merge_file_options, GIT_MERGE_FILE_OPTIONS_INIT);
	return 0;
3174
}