Skip to content

Commit 62fdec1

Browse files
newrengitster
authored andcommitted
merge-ort: flesh out implementation of handle_content_merge()
This implementation is based heavily on merge_mode_and_contents() from merge-recursive.c, though it has some fixes for recursive merges (i.e. when call_depth > 0), and has a number of changes throughout based on slight differences in data structures and in how the functions are called. It is, however, based on two new helper functions -- merge_3way() and merge_submodule -- for which we only provide die-not-implemented stubs at this point. Future commits will add implementations of these functions. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 991bbdc commit 62fdec1

File tree

1 file changed

+143
-6
lines changed

1 file changed

+143
-6
lines changed

merge-ort.c

Lines changed: 143 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,28 @@ static int collect_merge_info(struct merge_options *opt,
631631

632632
/*** Function Grouping: functions related to threeway content merges ***/
633633

634+
static int merge_submodule(struct merge_options *opt,
635+
const char *path,
636+
const struct object_id *o,
637+
const struct object_id *a,
638+
const struct object_id *b,
639+
struct object_id *result)
640+
{
641+
die("Not yet implemented.");
642+
}
643+
644+
static int merge_3way(struct merge_options *opt,
645+
const char *path,
646+
const struct object_id *o,
647+
const struct object_id *a,
648+
const struct object_id *b,
649+
const char *pathnames[3],
650+
const int extra_marker_size,
651+
mmbuffer_t *result_buf)
652+
{
653+
die("Not yet implemented.");
654+
}
655+
634656
static int handle_content_merge(struct merge_options *opt,
635657
const char *path,
636658
const struct version_info *o,
@@ -640,14 +662,129 @@ static int handle_content_merge(struct merge_options *opt,
640662
const int extra_marker_size,
641663
struct version_info *result)
642664
{
643-
int clean = 0;
644665
/*
645-
* TODO: Needs a two-way or three-way content merge, but we're
646-
* just being lazy and copying the version from HEAD and
647-
* leaving it as conflicted.
666+
* path is the target location where we want to put the file, and
667+
* is used to determine any normalization rules in ll_merge.
668+
*
669+
* The normal case is that path and all entries in pathnames are
670+
* identical, though renames can affect which path we got one of
671+
* the three blobs to merge on various sides of history.
672+
*
673+
* extra_marker_size is the amount to extend conflict markers in
674+
* ll_merge; this is neeed if we have content merges of content
675+
* merges, which happens for example with rename/rename(2to1) and
676+
* rename/add conflicts.
648677
*/
649-
result->mode = a->mode;
650-
oidcpy(&result->oid, &a->oid);
678+
unsigned clean = 1;
679+
680+
/*
681+
* handle_content_merge() needs both files to be of the same type, i.e.
682+
* both files OR both submodules OR both symlinks. Conflicting types
683+
* needs to be handled elsewhere.
684+
*/
685+
assert((S_IFMT & a->mode) == (S_IFMT & b->mode));
686+
687+
/* Merge modes */
688+
if (a->mode == b->mode || a->mode == o->mode)
689+
result->mode = b->mode;
690+
else {
691+
/* must be the 100644/100755 case */
692+
assert(S_ISREG(a->mode));
693+
result->mode = a->mode;
694+
clean = (b->mode == o->mode);
695+
/*
696+
* FIXME: If opt->priv->call_depth && !clean, then we really
697+
* should not make result->mode match either a->mode or
698+
* b->mode; that causes t6036 "check conflicting mode for
699+
* regular file" to fail. It would be best to use some other
700+
* mode, but we'll confuse all kinds of stuff if we use one
701+
* where S_ISREG(result->mode) isn't true, and if we use
702+
* something like 0100666, then tree-walk.c's calls to
703+
* canon_mode() will just normalize that to 100644 for us and
704+
* thus not solve anything.
705+
*
706+
* Figure out if there's some kind of way we can work around
707+
* this...
708+
*/
709+
}
710+
711+
/*
712+
* Trivial oid merge.
713+
*
714+
* Note: While one might assume that the next four lines would
715+
* be unnecessary due to the fact that match_mask is often
716+
* setup and already handled, renames don't always take care
717+
* of that.
718+
*/
719+
if (oideq(&a->oid, &b->oid) || oideq(&a->oid, &o->oid))
720+
oidcpy(&result->oid, &b->oid);
721+
else if (oideq(&b->oid, &o->oid))
722+
oidcpy(&result->oid, &a->oid);
723+
724+
/* Remaining rules depend on file vs. submodule vs. symlink. */
725+
else if (S_ISREG(a->mode)) {
726+
mmbuffer_t result_buf;
727+
int ret = 0, merge_status;
728+
int two_way;
729+
730+
/*
731+
* If 'o' is different type, treat it as null so we do a
732+
* two-way merge.
733+
*/
734+
two_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));
735+
736+
merge_status = merge_3way(opt, path,
737+
two_way ? &null_oid : &o->oid,
738+
&a->oid, &b->oid,
739+
pathnames, extra_marker_size,
740+
&result_buf);
741+
742+
if ((merge_status < 0) || !result_buf.ptr)
743+
ret = err(opt, _("Failed to execute internal merge"));
744+
745+
if (!ret &&
746+
write_object_file(result_buf.ptr, result_buf.size,
747+
blob_type, &result->oid))
748+
ret = err(opt, _("Unable to add %s to database"),
749+
path);
750+
751+
free(result_buf.ptr);
752+
if (ret)
753+
return -1;
754+
clean &= (merge_status == 0);
755+
path_msg(opt, path, 1, _("Auto-merging %s"), path);
756+
} else if (S_ISGITLINK(a->mode)) {
757+
int two_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));
758+
clean = merge_submodule(opt, pathnames[0],
759+
two_way ? &null_oid : &o->oid,
760+
&a->oid, &b->oid, &result->oid);
761+
if (opt->priv->call_depth && two_way && !clean) {
762+
result->mode = o->mode;
763+
oidcpy(&result->oid, &o->oid);
764+
}
765+
} else if (S_ISLNK(a->mode)) {
766+
if (opt->priv->call_depth) {
767+
clean = 0;
768+
result->mode = o->mode;
769+
oidcpy(&result->oid, &o->oid);
770+
} else {
771+
switch (opt->recursive_variant) {
772+
case MERGE_VARIANT_NORMAL:
773+
clean = 0;
774+
oidcpy(&result->oid, &a->oid);
775+
break;
776+
case MERGE_VARIANT_OURS:
777+
oidcpy(&result->oid, &a->oid);
778+
break;
779+
case MERGE_VARIANT_THEIRS:
780+
oidcpy(&result->oid, &b->oid);
781+
break;
782+
}
783+
}
784+
} else
785+
BUG("unsupported object type in the tree: %06o for %s",
786+
a->mode, path);
787+
651788
return clean;
652789
}
653790

0 commit comments

Comments
 (0)