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