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

[PATCH v2 02/10] merge-ort: handle directory/file conflicts that remain

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

When a directory/file conflict remains, we can leave the directory where it is, but need to move the information about the file to a different pathname. After moving the file to a different pathname, we allow subsequent process_entry() logic to handle any additional details that might be relevant.

This depends on a new helper function, unique_path(), that dies with an unimplemented error currently but will be implemented in a subsequent commit.

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 merge-ort.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 84 insertions(+), 2 deletions(-)
diff --git a/merge-ort.c b/merge-ort.c
index dd90987ae3d..d300a02810e 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -343,6 +343,13 @@ static void path_msg(struct merge_options *opt,
 	strbuf_addch(sb, '\n');
 }
 
+static char *unique_path(struct strmap *existing_paths,
+			 const char *path,
+			 const char *branch)
+{
+	die("Not yet implemented.");
+}
+
 /*** Function Grouping: functions related to collect_merge_info() ***/
 
 static void setup_path_info(struct merge_options *opt,
@@ -962,6 +969,8 @@ static void process_entry(struct merge_options *opt,
 			  struct conflict_info *ci,
 			  struct directory_versions *dir_metadata)
 {
+	int df_file_index = 0;
+
 	VERIFY_CI(ci);
 	assert(ci->filemask >= 0 && ci->filemask <= 7);
 	/* ci->match_mask == 7 was handled in collect_merge_info_callback() */
@@ -998,13 +1007,86 @@ static void process_entry(struct merge_options *opt,
 			oidcpy(&ci->stages[i].oid, &null_oid);
 		}
 	} else if (ci->df_conflict && ci->merged.result.mode != 0) {
-		die("Not yet implemented.");
+		/*
+		 * This started out as a D/F conflict, and the entries in
+		 * the competing directory were not removed by the merge as
+		 * evidenced by write_completed_directory() writing a value
+		 * to ci->merged.result.mode.
+		 */
+		struct conflict_info *new_ci;
+		const char *branch;
+		const char *old_path = path;
+		int i;
+
+		assert(ci->merged.result.mode == S_IFDIR);
+
+		/*
+		 * If filemask is 1, we can just ignore the file as having
+		 * been deleted on both sides.  We do not want to overwrite
+		 * ci->merged.result, since it stores the tree for all the
+		 * files under it.
+		 */
+		if (ci->filemask == 1) {
+			ci->filemask = 0;
+			return;
+		}
+
+		/*
+		 * This file still exists on at least one side, and we want
+		 * the directory to remain here, so we need to move this
+		 * path to some new location.
+		 */
+		new_ci = xcalloc(1, sizeof(*new_ci));
+		/* We don't really want new_ci->merged.result copied, but it'll
+		 * be overwritten below so it doesn't matter.  We also don't
+		 * want any directory mode/oid values copied, but we'll zero
+		 * those out immediately.  We do want the rest of ci copied.
+		 */
+		memcpy(new_ci, ci, sizeof(*ci));
+		new_ci->match_mask = (new_ci->match_mask & ~new_ci->dirmask);
+		new_ci->dirmask = 0;
+		for (i = MERGE_BASE; i <= MERGE_SIDE2; i++) {
+			if (new_ci->filemask & (1 << i))
+				continue;
+			/* zero out any entries related to directories */
+			new_ci->stages[i].mode = 0;
+			oidcpy(&new_ci->stages[i].oid, &null_oid);
+		}
+
+		/*
+		 * Find out which side this file came from; note that we
+		 * cannot just use ci->filemask, because renames could cause
+		 * the filemask to go back to 7.  So we use dirmask, then
+		 * pick the opposite side's index.
+		 */
+		df_file_index = (ci->dirmask & (1 << 1)) ? 2 : 1;
+		branch = (df_file_index == 1) ? opt->branch1 : opt->branch2;
+		path = unique_path(&opt->priv->paths, path, branch);
+		strmap_put(&opt->priv->paths, path, new_ci);
+
+		path_msg(opt, path, 0,
+			 _("CONFLICT (file/directory): directory in the way "
+			   "of %s from %s; moving it to %s instead."),
+			 old_path, branch, path);
+
+		/*
+		 * Zero out the filemask for the old ci.  At this point, ci
+		 * was just an entry for a directory, so we don't need to
+		 * do anything more with it.
+		 */
+		ci->filemask = 0;
+
+		/*
+		 * Now note that we're working on the new entry (path was
+		 * updated above.
+		 */
+		ci = new_ci;
 	}
 
 	/*
 	 * NOTE: Below there is a long switch-like if-elseif-elseif... block
 	 *       which the code goes through even for the df_conflict cases
-	 *       above.  Well, it will once we don't die-not-implemented above.
+	 *       above.
 	 */
 	if (ci->match_mask) {
 		ci->merged.clean = 1;
-- 
gitgitgadget
Previous: Elijah Newren via GitGitGadgetNext: Elijah Newren via GitGitGadget
Message 31 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.