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

[PATCH 2/2] update-index: use unmerge_index_entry() to support removal

From
Junio C Hamano <gitster@pobox.com>
Date
Jul 27, 2023, 21:51 UTC
Message-ID
<xmqqtttp9g6r.fsf@gitster.g>
In-Reply-To
<xmqq3519auz5.fsf@gitster.g>

"update-index --unresolve" used the unmerge_index_entry_at() that assumed that the path to be unresolved must be in the index, which made it impossible to unresolve a path that was resolved as removal.

Rewrite unresolve_one() to use the unmerge_index_entry() to support unresolving such a path.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 * Now getting rid of unmerge_index_entry_at() is a bigger task.  The
   only remaining user of it is the "checkout -m -- $path" codepath.
 builtin/update-index.c    | 33 +++++++++++++++++----------------
 t/t2030-unresolve-info.sh | 29 +++++++++++++++++++++++++----
 2 files changed, 42 insertions(+), 20 deletions(-)
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 853ec9eb7a..d02ac55313 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -661,26 +661,26 @@ static int unresolve_one(const char *path)
 	int pos;
 	int ret = 0;
 	struct cache_entry *ce_2 = NULL, *ce_3 = NULL;
+	struct resolve_undo_info *ru = NULL;
+
+	if (the_index.resolve_undo) {
+		struct string_list_item *item;
+		item = string_list_lookup(the_index.resolve_undo, path);
+		if (item)
+			ru = item->util;
+	}
+
+	/* resolve-undo record exists for the path */
+	if (ru)
+		return unmerge_index_entry(&the_index, path, ru);
 
 	/* See if there is such entry in the index. */
 	pos = index_name_pos(&the_index, path, namelen);
 	if (0 <= pos) {
-		/* already merged */
-		pos = unmerge_index_entry_at(&the_index, pos);
-		if (pos < the_index.cache_nr) {
-			const struct cache_entry *ce = the_index.cache[pos];
-			if (ce_stage(ce) &&
-			    ce_namelen(ce) == namelen &&
-			    !memcmp(ce->name, path, namelen))
-				return 0;
-		}
-		/* no resolve-undo information; fall back */
+		; /* resolve-undo record was used already -- fall back */
 	} else {
-		/* If there isn't, either it is unmerged, or
-		 * resolved as "removed" by mistake.  We do not
-		 * want to do anything in the former case.
-		 */
-		pos = -pos-1;
+		/* Is it unmerged? */
+		pos = -pos - 1;
 		if (pos < the_index.cache_nr) {
 			const struct cache_entry *ce = the_index.cache[pos];
 			if (ce_namelen(ce) == namelen &&
@@ -688,9 +688,10 @@ static int unresolve_one(const char *path)
 				fprintf(stderr,
 					"%s: skipping still unmerged path.\n",
 					path);
-				goto free_return;
 			}
+			goto free_return;
 		}
+		/* No, such a path does not exist -- removed */
 	}
 
 	/*
diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh
index d4e7760df5..6a3af64e0f 100755
--- a/t/t2030-unresolve-info.sh
+++ b/t/t2030-unresolve-info.sh
@@ -37,11 +37,17 @@ prime_resolve_undo () {
 	git checkout second^0 &&
 	test_tick &&
 	test_must_fail git merge third^0 &&
-	echo merge does not leave anything &&
 	check_resolve_undo empty &&
-	echo different >fi/le &&
-	git add fi/le &&
-	echo resolving records &&
+
+	# how should the conflict be resolved?
+	case "$1" in
+	remove)
+		rm -f file/le && git rm fi/le
+		;;
+	*) # modify
+		echo different >fi/le && git add fi/le
+		;;
+	esac
 	check_resolve_undo recorded fi/le initial:fi/le second:fi/le third:fi/le
 }
 
@@ -134,6 +140,21 @@ test_expect_success 'unmerge can be done even after committing' '
 	test_line_count = 3 actual
 '
 
+test_expect_success 'unmerge removal' '
+	prime_resolve_undo remove &&
+	git update-index --unresolve fi/le &&
+	git ls-files -u actual &&
+	test_line_count = 3 actual
+'
+
+test_expect_success 'unmerge removal after committing' '
+	prime_resolve_undo remove &&
+	git commit -m "record to nuke MERGE_HEAD" &&
+	git update-index --unresolve fi/le &&
+	git ls-files -u actual &&
+	test_line_count = 3 actual
+'
+
 test_expect_success 'rerere and rerere forget' '
 	mkdir .git/rr-cache &&
 	prime_resolve_undo &&
-- 
2.41.0-459-gb4fce4b6e4
Previous: Junio C HamanoNext: Junio C Hamano
Message 2 of 3 in “resolve-undo: allow resurrecting conflicted state that resolved to deletion”
  1. 1/2 resolve-undo: allow resurrecting conflicted state that resolved to deletionJunio C Hamano, Jul 27, 2023
  2. 2/2 update-index: use unmerge_index_entry() to support removalJunio C Hamano, Jul 27, 2023
  3. 3/2 update-index: remove stale fallback code for "--unresolve"Junio C Hamano, Jul 28, 2023

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.