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>

Elijah Newren committed Jan 1, 2021 at 02:34 UTC 62fdec17a111e419b750938d24b6d65e3076b76d
1 file changed +143 -6
merge-ort.c
+143 -6
@@ -631,6 +631,28 @@ static int collect_merge_info(struct merge_options *opt,
631
632 /*** Function Grouping: functions related to threeway content merges ***/
633
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 +
656 static int handle_content_merge(struct merge_options *opt,
657 const char *path,
658 const struct version_info *o,
@@ -640,14 +662,129 @@ static int handle_content_merge(struct merge_options *opt,
662 const int extra_marker_size,
663 struct version_info *result)
664 {
643 - int clean = 0;
665 /*
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.
677 */
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 +
788 return clean;
789 }
790