merge-ort: copy and adapt merge_submodule() from merge-recursive.c
Take merge_submodule() from merge-recursive.c and make slight adjustments, predominantly around deferring output using path_msg() instead of using merge-recursive's output() and show() functions. There's also a fix for recursive cases (when call_depth > 0) and a slight change to argument order for find_first_merges(). find_first_merges() and format_commit() are left unimplemented for now, but will be added by subsequent commits. 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
c73cda76b104795d1455ecbf031a18045ab37a84
1 file changed
+125
-1
merge-ort.c
+125
-1
@@ -26,6 +26,7 @@
26
#include "ll-merge.h"
27
#include "object-store.h"
28
#include "strmap.h"
29
+#include "submodule.h"
30
#include "tree.h"
31
#include "unpack-trees.h"
32
#include "xdiff-interface.h"
@@ -323,6 +324,13 @@ static int err(struct merge_options *opt, const char *err, ...)
324
return -1;
325
}
326
327
+static void format_commit(struct strbuf *sb,
328
+ int indent,
329
+ struct commit *commit)
330
+{
331
+ die("Not yet implemented.");
332
+}
333
+
334
__attribute__((format (printf, 4, 5)))
335
static void path_msg(struct merge_options *opt,
336
const char *path,
@@ -632,6 +640,15 @@ static int collect_merge_info(struct merge_options *opt,
640
641
/*** Function Grouping: functions related to threeway content merges ***/
642
643
+static int find_first_merges(struct repository *repo,
644
+ const char *path,
645
+ struct commit *a,
646
+ struct commit *b,
647
+ struct object_array *result)
648
+{
649
+ die("Not yet implemented.");
650
+}
651
+
652
static int merge_submodule(struct merge_options *opt,
653
const char *path,
654
const struct object_id *o,
@@ -639,7 +656,114 @@ static int merge_submodule(struct merge_options *opt,
656
const struct object_id *b,
657
struct object_id *result)
658
{
642
- die("Not yet implemented.");
659
+ struct commit *commit_o, *commit_a, *commit_b;
660
+ int parent_count;
661
+ struct object_array merges;
662
+ struct strbuf sb = STRBUF_INIT;
663
+
664
+ int i;
665
+ int search = !opt->priv->call_depth;
666
+
667
+ /* store fallback answer in result in case we fail */
668
+ oidcpy(result, opt->priv->call_depth ? o : a);
669
+
670
+ /* we can not handle deletion conflicts */
671
+ if (is_null_oid(o))
672
+ return 0;
673
+ if (is_null_oid(a))
674
+ return 0;
675
+ if (is_null_oid(b))
676
+ return 0;
677
+
678
+ if (add_submodule_odb(path)) {
679
+ path_msg(opt, path, 0,
680
+ _("Failed to merge submodule %s (not checked out)"),
681
+ path);
682
+ return 0;
683
+ }
684
+
685
+ if (!(commit_o = lookup_commit_reference(opt->repo, o)) ||
686
+ !(commit_a = lookup_commit_reference(opt->repo, a)) ||
687
+ !(commit_b = lookup_commit_reference(opt->repo, b))) {
688
+ path_msg(opt, path, 0,
689
+ _("Failed to merge submodule %s (commits not present)"),
690
+ path);
691
+ return 0;
692
+ }
693
+
694
+ /* check whether both changes are forward */
695
+ if (!in_merge_bases(commit_o, commit_a) ||
696
+ !in_merge_bases(commit_o, commit_b)) {
697
+ path_msg(opt, path, 0,
698
+ _("Failed to merge submodule %s "
699
+ "(commits don't follow merge-base)"),
700
+ path);
701
+ return 0;
702
+ }
703
+
704
+ /* Case #1: a is contained in b or vice versa */
705
+ if (in_merge_bases(commit_a, commit_b)) {
706
+ oidcpy(result, b);
707
+ path_msg(opt, path, 1,
708
+ _("Note: Fast-forwarding submodule %s to %s"),
709
+ path, oid_to_hex(b));
710
+ return 1;
711
+ }
712
+ if (in_merge_bases(commit_b, commit_a)) {
713
+ oidcpy(result, a);
714
+ path_msg(opt, path, 1,
715
+ _("Note: Fast-forwarding submodule %s to %s"),
716
+ path, oid_to_hex(a));
717
+ return 1;
718
+ }
719
+
720
+ /*
721
+ * Case #2: There are one or more merges that contain a and b in
722
+ * the submodule. If there is only one, then present it as a
723
+ * suggestion to the user, but leave it marked unmerged so the
724
+ * user needs to confirm the resolution.
725
+ */
726
+
727
+ /* Skip the search if makes no sense to the calling context. */
728
+ if (!search)
729
+ return 0;
730
+
731
+ /* find commit which merges them */
732
+ parent_count = find_first_merges(opt->repo, path, commit_a, commit_b,
733
+ &merges);
734
+ switch (parent_count) {
735
+ case 0:
736
+ path_msg(opt, path, 0, _("Failed to merge submodule %s"), path);
737
+ break;
738
+
739
+ case 1:
740
+ format_commit(&sb, 4,
741
+ (struct commit *)merges.objects[0].item);
742
+ path_msg(opt, path, 0,
743
+ _("Failed to merge submodule %s, but a possible merge "
744
+ "resolution exists:\n%s\n"),
745
+ path, sb.buf);
746
+ path_msg(opt, path, 1,
747
+ _("If this is correct simply add it to the index "
748
+ "for example\n"
749
+ "by using:\n\n"
750
+ " git update-index --cacheinfo 160000 %s \"%s\"\n\n"
751
+ "which will accept this suggestion.\n"),
752
+ oid_to_hex(&merges.objects[0].item->oid), path);
753
+ strbuf_release(&sb);
754
+ break;
755
+ default:
756
+ for (i = 0; i < merges.nr; i++)
757
+ format_commit(&sb, 4,
758
+ (struct commit *)merges.objects[i].item);
759
+ path_msg(opt, path, 0,
760
+ _("Failed to merge submodule %s, but multiple "
761
+ "possible merges exist:\n%s"), path, sb.buf);
762
+ strbuf_release(&sb);
763
+ }
764
+
765
+ object_array_clear(&merges);
766
+ return 0;
767
}
768
769
static int merge_3way(struct merge_options *opt,