Пример #1
0
static int ll_merge_in_worktree(struct notes_merge_options *o,
				struct notes_merge_pair *p)
{
	mmbuffer_t result_buf;
	mmfile_t base, local, remote;
	int status;

	read_mmblob(&base, p->base);
	read_mmblob(&local, p->local);
	read_mmblob(&remote, p->remote);

	status = ll_merge(&result_buf, sha1_to_hex(p->obj), &base, NULL,
			  &local, o->local_ref, &remote, o->remote_ref, NULL);

	free(base.ptr);
	free(local.ptr);
	free(remote.ptr);

	if ((status < 0) || !result_buf.ptr)
		die("Failed to execute internal merge");

	write_buf_to_worktree(p->obj, result_buf.ptr, result_buf.size);
	free(result_buf.ptr);

	return status;
}
static int merge_3way(struct merge_options *o,
		      mmbuffer_t *result_buf,
		      struct diff_filespec *one,
		      struct diff_filespec *a,
		      struct diff_filespec *b,
		      const char *branch1,
		      const char *branch2)
{
	mmfile_t orig, src1, src2;
	char *base_name, *name1, *name2;
	int merge_status;
	int favor;

	if (o->call_depth)
		favor = 0;
	else {
		switch (o->recursive_variant) {
		case MERGE_RECURSIVE_OURS:
			favor = XDL_MERGE_FAVOR_OURS;
			break;
		case MERGE_RECURSIVE_THEIRS:
			favor = XDL_MERGE_FAVOR_THEIRS;
			break;
		default:
			favor = 0;
			break;
		}
	}

	if (strcmp(a->path, b->path) ||
	    (o->ancestor != NULL && strcmp(a->path, one->path) != 0)) {
		base_name = o->ancestor == NULL ? NULL :
			xstrdup(mkpath("%s:%s", o->ancestor, one->path));
		name1 = xstrdup(mkpath("%s:%s", branch1, a->path));
		name2 = xstrdup(mkpath("%s:%s", branch2, b->path));
	} else {
		base_name = o->ancestor == NULL ? NULL :
			xstrdup(mkpath("%s", o->ancestor));
		name1 = xstrdup(mkpath("%s", branch1));
		name2 = xstrdup(mkpath("%s", branch2));
	}

	read_mmblob(&orig, one->sha1);
	read_mmblob(&src1, a->sha1);
	read_mmblob(&src2, b->sha1);

	merge_status = ll_merge(result_buf, a->path, &orig, base_name,
				&src1, name1, &src2, name2,
				(!!o->call_depth) | (favor << 1));

	free(name1);
	free(name2);
	free(orig.ptr);
	free(src1.ptr);
	free(src2.ptr);
	return merge_status;
}
Пример #3
0
static int checkout_merged(int pos, const struct checkout *state, int *nr_checkouts)
{
	struct cache_entry *ce = active_cache[pos];
	const char *path = ce->name;
	mmfile_t ancestor, ours, theirs;
	int status;
	struct object_id oid;
	mmbuffer_t result_buf;
	struct object_id threeway[3];
	unsigned mode = 0;

	memset(threeway, 0, sizeof(threeway));
	while (pos < active_nr) {
		int stage;
		stage = ce_stage(ce);
		if (!stage || strcmp(path, ce->name))
			break;
		oidcpy(&threeway[stage - 1], &ce->oid);
		if (stage == 2)
			mode = create_ce_mode(ce->ce_mode);
		pos++;
		ce = active_cache[pos];
	}
	if (is_null_oid(&threeway[1]) || is_null_oid(&threeway[2]))
		return error(_("path '%s' does not have necessary versions"), path);

	read_mmblob(&ancestor, &threeway[0]);
	read_mmblob(&ours, &threeway[1]);
	read_mmblob(&theirs, &threeway[2]);

	/*
	 * NEEDSWORK: re-create conflicts from merges with
	 * merge.renormalize set, too
	 */
	status = ll_merge(&result_buf, path, &ancestor, "base",
			  &ours, "ours", &theirs, "theirs",
			  state->istate, NULL);
	free(ancestor.ptr);
	free(ours.ptr);
	free(theirs.ptr);
	if (status < 0 || !result_buf.ptr) {
		free(result_buf.ptr);
		return error(_("path '%s': cannot merge"), path);
	}

	/*
	 * NEEDSWORK:
	 * There is absolutely no reason to write this as a blob object
	 * and create a phony cache entry.  This hack is primarily to get
	 * to the write_entry() machinery that massages the contents to
	 * work-tree format and writes out which only allows it for a
	 * cache entry.  The code in write_entry() needs to be refactored
	 * to allow us to feed a <buffer, size, mode> instead of a cache
	 * entry.  Such a refactoring would help merge_recursive as well
	 * (it also writes the merge result to the object database even
	 * when it may contain conflicts).
	 */
	if (write_object_file(result_buf.ptr, result_buf.size, blob_type, &oid))
		die(_("Unable to add merge result for '%s'"), path);
	free(result_buf.ptr);
	ce = make_transient_cache_entry(mode, &oid, path, 2);
	if (!ce)
		die(_("make_cache_entry failed for path '%s'"), path);
	status = checkout_entry(ce, state, NULL, nr_checkouts);
	discard_cache_entry(ce);
	return status;
}