merge-ort: add implementation of checkout()

Since merge-ort creates a tree for its output, when there are no
conflicts, updating the working tree and index is as simple as using the
unpack_trees() machinery with a twoway_merge (i.e. doing the equivalent
of a "checkout" operation).

If there were conflicts in the merge, then since the tree we created
included all the conflict markers, then using the unpack_trees machinery
in this manner will still update the working tree correctly.  Further,
all index entries corresponding to cleanly merged files will also be
updated correctly by this procedure.  Index entries corresponding to
conflicted entries will appear as though the user had run "git add -u"
after the merge to accept all files as-is with conflict markers.

Thus, after running unpack_trees(), there needs to be a separate step
for updating the entries in the index corresponding to conflicted files.
This will be the job for the function record_conflicted_index_entris(),
which will be implemented in a subsequent commit.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Elijah Newren 2020-12-13 08:04:24 +00:00 committed by Junio C Hamano
parent 9fefce68dc
commit 6681ce5cf6
1 changed files with 44 additions and 1 deletions

View File

@ -19,9 +19,11 @@
#include "diff.h"
#include "diffcore.h"
#include "dir.h"
#include "object-store.h"
#include "strmap.h"
#include "tree.h"
#include "unpack-trees.h"
#include "xdiff-interface.h"
/*
@ -975,7 +977,48 @@ static int checkout(struct merge_options *opt,
struct tree *prev,
struct tree *next)
{
die("Not yet implemented.");
/* Switch the index/working copy from old to new */
int ret;
struct tree_desc trees[2];
struct unpack_trees_options unpack_opts;
memset(&unpack_opts, 0, sizeof(unpack_opts));
unpack_opts.head_idx = -1;
unpack_opts.src_index = opt->repo->index;
unpack_opts.dst_index = opt->repo->index;
setup_unpack_trees_porcelain(&unpack_opts, "merge");
/*
* NOTE: if this were just "git checkout" code, we would probably
* read or refresh the cache and check for a conflicted index, but
* builtin/merge.c or sequencer.c really needs to read the index
* and check for conflicted entries before starting merging for a
* good user experience (no sense waiting for merges/rebases before
* erroring out), so there's no reason to duplicate that work here.
*/
/* 2-way merge to the new branch */
unpack_opts.update = 1;
unpack_opts.merge = 1;
unpack_opts.quiet = 0; /* FIXME: sequencer might want quiet? */
unpack_opts.verbose_update = (opt->verbosity > 2);
unpack_opts.fn = twoway_merge;
if (1/* FIXME: opts->overwrite_ignore*/) {
unpack_opts.dir = xcalloc(1, sizeof(*unpack_opts.dir));
unpack_opts.dir->flags |= DIR_SHOW_IGNORED;
setup_standard_excludes(unpack_opts.dir);
}
parse_tree(prev);
init_tree_desc(&trees[0], prev->buffer, prev->size);
parse_tree(next);
init_tree_desc(&trees[1], next->buffer, next->size);
ret = unpack_trees(2, trees, &unpack_opts);
clear_unpack_trees_porcelain(&unpack_opts);
dir_clear(unpack_opts.dir);
FREE_AND_NULL(unpack_opts.dir);
return ret;
}
static int record_conflicted_index_entries(struct merge_options *opt,