git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 07/10] merge-ort: copy and adapt merge_submodule() from merge-recursive.c

From
Elijah Newren via GitGitGadget <gitgitgadget@gmail.com>
Date
Jan 1, 2021, 02:34 UTC
Message-ID
<2ddf6ece9d0e3ec4d98d33f56e168466439ae421.1609468488.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.815.v2.git.1609468488.gitgitgadget@gmail.com>
From: Elijah Newren <newren@gmail.com>

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>
---
 merge-ort.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 125 insertions(+), 1 deletion(-)
diff --git a/merge-ort.c b/merge-ort.c
index a59adb42aa6..2dfab1858fc 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -26,6 +26,7 @@
 #include "ll-merge.h"
 #include "object-store.h"
 #include "strmap.h"
+#include "submodule.h"
 #include "tree.h"
 #include "unpack-trees.h"
 #include "xdiff-interface.h"
@@ -323,6 +324,13 @@ static int err(struct merge_options *opt, const char *err, ...)
 	return -1;
 }
 
+static void format_commit(struct strbuf *sb,
+			  int indent,
+			  struct commit *commit)
+{
+	die("Not yet implemented.");
+}
+
 __attribute__((format (printf, 4, 5)))
 static void path_msg(struct merge_options *opt,
 		     const char *path,
@@ -632,6 +640,15 @@ static int collect_merge_info(struct merge_options *opt,
 
 /*** Function Grouping: functions related to threeway content merges ***/
 
+static int find_first_merges(struct repository *repo,
+			     const char *path,
+			     struct commit *a,
+			     struct commit *b,
+			     struct object_array *result)
+{
+	die("Not yet implemented.");
+}
+
 static int merge_submodule(struct merge_options *opt,
 			   const char *path,
 			   const struct object_id *o,
@@ -639,7 +656,114 @@ static int merge_submodule(struct merge_options *opt,
 			   const struct object_id *b,
 			   struct object_id *result)
 {
-	die("Not yet implemented.");
+	struct commit *commit_o, *commit_a, *commit_b;
+	int parent_count;
+	struct object_array merges;
+	struct strbuf sb = STRBUF_INIT;
+
+	int i;
+	int search = !opt->priv->call_depth;
+
+	/* store fallback answer in result in case we fail */
+	oidcpy(result, opt->priv->call_depth ? o : a);
+
+	/* we can not handle deletion conflicts */
+	if (is_null_oid(o))
+		return 0;
+	if (is_null_oid(a))
+		return 0;
+	if (is_null_oid(b))
+		return 0;
+
+	if (add_submodule_odb(path)) {
+		path_msg(opt, path, 0,
+			 _("Failed to merge submodule %s (not checked out)"),
+			 path);
+		return 0;
+	}
+
+	if (!(commit_o = lookup_commit_reference(opt->repo, o)) ||
+	    !(commit_a = lookup_commit_reference(opt->repo, a)) ||
+	    !(commit_b = lookup_commit_reference(opt->repo, b))) {
+		path_msg(opt, path, 0,
+			 _("Failed to merge submodule %s (commits not present)"),
+			 path);
+		return 0;
+	}
+
+	/* check whether both changes are forward */
+	if (!in_merge_bases(commit_o, commit_a) ||
+	    !in_merge_bases(commit_o, commit_b)) {
+		path_msg(opt, path, 0,
+			 _("Failed to merge submodule %s "
+			   "(commits don't follow merge-base)"),
+			 path);
+		return 0;
+	}
+
+	/* Case #1: a is contained in b or vice versa */
+	if (in_merge_bases(commit_a, commit_b)) {
+		oidcpy(result, b);
+		path_msg(opt, path, 1,
+			 _("Note: Fast-forwarding submodule %s to %s"),
+			 path, oid_to_hex(b));
+		return 1;
+	}
+	if (in_merge_bases(commit_b, commit_a)) {
+		oidcpy(result, a);
+		path_msg(opt, path, 1,
+			 _("Note: Fast-forwarding submodule %s to %s"),
+			 path, oid_to_hex(a));
+		return 1;
+	}
+
+	/*
+	 * Case #2: There are one or more merges that contain a and b in
+	 * the submodule. If there is only one, then present it as a
+	 * suggestion to the user, but leave it marked unmerged so the
+	 * user needs to confirm the resolution.
+	 */
+
+	/* Skip the search if makes no sense to the calling context.  */
+	if (!search)
+		return 0;
+
+	/* find commit which merges them */
+	parent_count = find_first_merges(opt->repo, path, commit_a, commit_b,
+					 &merges);
+	switch (parent_count) {
+	case 0:
+		path_msg(opt, path, 0, _("Failed to merge submodule %s"), path);
+		break;
+
+	case 1:
+		format_commit(&sb, 4,
+			      (struct commit *)merges.objects[0].item);
+		path_msg(opt, path, 0,
+			 _("Failed to merge submodule %s, but a possible merge "
+			   "resolution exists:\n%s\n"),
+			 path, sb.buf);
+		path_msg(opt, path, 1,
+			 _("If this is correct simply add it to the index "
+			   "for example\n"
+			   "by using:\n\n"
+			   "  git update-index --cacheinfo 160000 %s \"%s\"\n\n"
+			   "which will accept this suggestion.\n"),
+			 oid_to_hex(&merges.objects[0].item->oid), path);
+		strbuf_release(&sb);
+		break;
+	default:
+		for (i = 0; i < merges.nr; i++)
+			format_commit(&sb, 4,
+				      (struct commit *)merges.objects[i].item);
+		path_msg(opt, path, 0,
+			 _("Failed to merge submodule %s, but multiple "
+			   "possible merges exist:\n%s"), path, sb.buf);
+		strbuf_release(&sb);
+	}
+
+	object_array_clear(&merges);
+	return 0;
 }
 
 static int merge_3way(struct merge_options *opt,
-- 
gitgitgadget
Previous: Elijah Newren via GitGitGadgetNext: Elijah Newren via GitGitGadget
Message 30 of 37 in “merge-ort: add more handling of basic conflict types”
  1. 00/10 merge-ort: add more handling of basic conflict typesElijah Newren via GitGitGadget, Dec 18, 2020
  2. 01/10 merge-ort: handle D/F conflict where directory disappears due to mergeElijah Newren via GitGitGadget, Dec 18, 2020
  3. Derrick StoleeDec 30, 2020
  4. Elijah NewrenDec 30, 2020
  5. Derrick StoleeDec 31, 2020
  6. Elijah NewrenDec 31, 2020
  7. 03/10 merge-ort: implement unique_path() helperElijah Newren via GitGitGadget, Dec 18, 2020
  8. Derrick StoleeDec 30, 2020
  9. Elijah NewrenDec 30, 2020
  10. Derrick StoleeDec 31, 2020
  11. 04/10 merge-ort: handle book-keeping around two- and three-way content mergeElijah Newren via GitGitGadget, Dec 18, 2020
  12. 02/10 merge-ort: handle directory/file conflicts that remainElijah Newren via GitGitGadget, Dec 18, 2020
  13. 05/10 merge-ort: flesh out implementation of handle_content_merge()Elijah Newren via GitGitGadget, Dec 18, 2020
  14. 07/10 merge-ort: copy and adapt merge_submodule() from merge-recursive.cElijah Newren via GitGitGadget, Dec 18, 2020
  15. 09/10 merge-ort: copy find_first_merges() implementation from merge-recursive.cElijah Newren via GitGitGadget, Dec 18, 2020
  16. 10/10 merge-ort: add handling for different types of files at same pathElijah Newren via GitGitGadget, Dec 18, 2020
  17. 06/10 merge-ort: copy and adapt merge_3way() from merge-recursive.cElijah Newren via GitGitGadget, Dec 18, 2020
  18. 08/10 merge-ort: implement format_commit()Elijah Newren via GitGitGadget, Dec 18, 2020
  19. Elijah NewrenDec 29, 2020
  20. 00/10 merge-ort: add more handling of basic conflict typesElijah Newren via GitGitGadget, Jan 1, 2021
  21. 01/10 merge-ort: handle D/F conflict where directory disappears due to mergeElijah Newren via GitGitGadget, Jan 1, 2021
  22. 05/10 merge-ort: flesh out implementation of handle_content_merge()Elijah Newren via GitGitGadget, Jan 1, 2021
  23. A merge-ort TODO comment, and how to test merge-ort?Ævar Arnfjörð Bjarmason, Mar 4, 2021
  24. Elijah NewrenMar 4, 2021
  25. Ævar Arnfjörð BjarmasonMar 4, 2021
  26. Elijah NewrenMar 4, 2021
  27. Ævar Arnfjörð BjarmasonMar 8, 2021
  28. 03/10 merge-ort: implement unique_path() helperElijah Newren via GitGitGadget, Jan 1, 2021
  29. 04/10 merge-ort: handle book-keeping around two- and three-way content mergeElijah Newren via GitGitGadget, Jan 1, 2021
  30. 07/10 merge-ort: copy and adapt merge_submodule() from merge-recursive.cElijah Newren via GitGitGadget, Jan 1, 2021
  31. 02/10 merge-ort: handle directory/file conflicts that remainElijah Newren via GitGitGadget, Jan 1, 2021
  32. 09/10 merge-ort: copy find_first_merges() implementation from merge-recursive.cElijah Newren via GitGitGadget, Jan 1, 2021
  33. 08/10 merge-ort: implement format_commit()Elijah Newren via GitGitGadget, Jan 1, 2021
  34. 10/10 merge-ort: add handling for different types of files at same pathElijah Newren via GitGitGadget, Jan 1, 2021
  35. 06/10 merge-ort: copy and adapt merge_3way() from merge-recursive.cElijah Newren via GitGitGadget, Jan 1, 2021
  36. Derrick StoleeJan 5, 2021
  37. Elijah NewrenJan 6, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.