git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH 7/7] checkout: allow "checkout -m path" to unmerge removed paths
Date: Mon, 31 Jul 2023 15:44:09 -0700	[thread overview]
Message-ID: <20230731224409.4181277-8-gitster@pobox.com> (raw)
In-Reply-To: <20230731224409.4181277-1-gitster@pobox.com>

"git checkout -m -- path" uses the unmerge_marked_index() API, whose
implementation is incapable of unresolving a path that was resolved
as removed.  Extend the unmerge_index() API function so that we can
mark the ce_flags member of the cache entries we add to the index as
unmerged, and replace use of unmerge_marked_index() with it.

Now, together with its unmerge_index_entry_at() helper function,
unmerge_marked_index() function is no longer called by anybody, and
can safely be removed.

This makes two known test failures in t2070 and t7201 to succeed.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/checkout.c     |  6 ++--
 builtin/update-index.c |  2 +-
 rerere.c               |  2 +-
 resolve-undo.c         | 75 +++---------------------------------------
 resolve-undo.h         |  6 ++--
 t/t2070-restore.sh     |  2 +-
 t/t7201-co.sh          |  2 +-
 7 files changed, 13 insertions(+), 82 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index b8dfba57c6..98fcf1220a 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -566,6 +566,8 @@ static int checkout_paths(const struct checkout_opts *opts,
 
 	if (opts->source_tree)
 		read_tree_some(opts->source_tree, &opts->pathspec);
+	if (opts->merge)
+		unmerge_index(&the_index, &opts->pathspec, CE_MATCHED);
 
 	ps_matched = xcalloc(opts->pathspec.nr, 1);
 
@@ -589,10 +591,6 @@ static int checkout_paths(const struct checkout_opts *opts,
 	}
 	free(ps_matched);
 
-	/* "checkout -m path" to recreate conflicted state */
-	if (opts->merge)
-		unmerge_marked_index(&the_index);
-
 	/* Any unmerged paths? */
 	for (pos = 0; pos < the_index.cache_nr; pos++) {
 		const struct cache_entry *ce = the_index.cache[pos];
diff --git a/builtin/update-index.c b/builtin/update-index.c
index def7f98504..69fe9c8fcb 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -646,7 +646,7 @@ static int unresolve_one(const char *path)
 	item = string_list_lookup(the_index.resolve_undo, path);
 	if (!item)
 		return res; /* no resolve-undo record for the path */
-	res = unmerge_index_entry(&the_index, path, item->util);
+	res = unmerge_index_entry(&the_index, path, item->util, 0);
 	FREE_AND_NULL(item->util);
 	return res;
 }
diff --git a/rerere.c b/rerere.c
index e968d413d6..b525dd9230 100644
--- a/rerere.c
+++ b/rerere.c
@@ -1112,7 +1112,7 @@ int rerere_forget(struct repository *r, struct pathspec *pathspec)
 	 * recover the original conflicted state and then
 	 * find the conflicted paths.
 	 */
-	unmerge_index(r->index, pathspec);
+	unmerge_index(r->index, pathspec, 0);
 	find_conflict(r, &conflict);
 	for (i = 0; i < conflict.nr; i++) {
 		struct string_list_item *it = &conflict.items[i];
diff --git a/resolve-undo.c b/resolve-undo.c
index 3b0244e210..8e5a8072ed 100644
--- a/resolve-undo.c
+++ b/resolve-undo.c
@@ -115,75 +115,8 @@ void resolve_undo_clear_index(struct index_state *istate)
 	istate->cache_changed |= RESOLVE_UNDO_CHANGED;
 }
 
-int unmerge_index_entry_at(struct index_state *istate, int pos)
-{
-	const struct cache_entry *ce;
-	struct string_list_item *item;
-	struct resolve_undo_info *ru;
-	int i, err = 0, matched;
-	char *name;
-
-	if (!istate->resolve_undo)
-		return pos;
-
-	ce = istate->cache[pos];
-	if (ce_stage(ce)) {
-		/* already unmerged */
-		while ((pos < istate->cache_nr) &&
-		       ! strcmp(istate->cache[pos]->name, ce->name))
-			pos++;
-		return pos - 1; /* return the last entry processed */
-	}
-	item = string_list_lookup(istate->resolve_undo, ce->name);
-	if (!item)
-		return pos;
-	ru = item->util;
-	if (!ru)
-		return pos;
-	matched = ce->ce_flags & CE_MATCHED;
-	name = xstrdup(ce->name);
-	remove_index_entry_at(istate, pos);
-	for (i = 0; i < 3; i++) {
-		struct cache_entry *nce;
-		if (!ru->mode[i])
-			continue;
-		nce = make_cache_entry(istate,
-				       ru->mode[i],
-				       &ru->oid[i],
-				       name, i + 1, 0);
-		if (matched)
-			nce->ce_flags |= CE_MATCHED;
-		if (add_index_entry(istate, nce, ADD_CACHE_OK_TO_ADD)) {
-			err = 1;
-			error("cannot unmerge '%s'", name);
-		}
-	}
-	free(name);
-	if (err)
-		return pos;
-	free(ru);
-	item->util = NULL;
-	return unmerge_index_entry_at(istate, pos);
-}
-
-void unmerge_marked_index(struct index_state *istate)
-{
-	int i;
-
-	if (!istate->resolve_undo)
-		return;
-
-	/* TODO: audit for interaction with sparse-index. */
-	ensure_full_index(istate);
-	for (i = 0; i < istate->cache_nr; i++) {
-		const struct cache_entry *ce = istate->cache[i];
-		if (ce->ce_flags & CE_MATCHED)
-			i = unmerge_index_entry_at(istate, i);
-	}
-}
-
 int unmerge_index_entry(struct index_state *istate, const char *path,
-			struct resolve_undo_info *ru)
+			struct resolve_undo_info *ru, unsigned ce_flags)
 {
 	int i = index_name_pos(istate, path, strlen(path));
 
@@ -206,13 +139,15 @@ int unmerge_index_entry(struct index_state *istate, const char *path,
 			continue;
 		ce = make_cache_entry(istate, ru->mode[i], &ru->oid[i],
 				      path, i + 1, 0);
+		ce->ce_flags |= ce_flags;
 		if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD))
 			return error("cannot unmerge '%s'", path);
 	}
 	return 0;
 }
 
-void unmerge_index(struct index_state *istate, const struct pathspec *pathspec)
+void unmerge_index(struct index_state *istate, const struct pathspec *pathspec,
+		   unsigned ce_flags)
 {
 	struct string_list_item *item;
 
@@ -231,7 +166,7 @@ void unmerge_index(struct index_state *istate, const struct pathspec *pathspec)
 				    item->string, strlen(item->string),
 				    0, NULL, 0))
 			continue;
-		unmerge_index_entry(istate, path, ru);
+		unmerge_index_entry(istate, path, ru, ce_flags);
 		free(ru);
 		item->util = NULL;
 	}
diff --git a/resolve-undo.h b/resolve-undo.h
index 1ae321c88b..f3f8462751 100644
--- a/resolve-undo.h
+++ b/resolve-undo.h
@@ -17,9 +17,7 @@ void record_resolve_undo(struct index_state *, struct cache_entry *);
 void resolve_undo_write(struct strbuf *, struct string_list *);
 struct string_list *resolve_undo_read(const char *, unsigned long);
 void resolve_undo_clear_index(struct index_state *);
-int unmerge_index_entry_at(struct index_state *, int);
-int unmerge_index_entry(struct index_state *, const char *, struct resolve_undo_info *);
-void unmerge_index(struct index_state *, const struct pathspec *);
-void unmerge_marked_index(struct index_state *);
+int unmerge_index_entry(struct index_state *, const char *, struct resolve_undo_info *, unsigned);
+void unmerge_index(struct index_state *, const struct pathspec *, unsigned);
 
 #endif
diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh
index d97ecc2483..16d6348b69 100755
--- a/t/t2070-restore.sh
+++ b/t/t2070-restore.sh
@@ -180,7 +180,7 @@ test_expect_success 'restore --merge to unresolve after (mistaken) resolution' '
 	test_cmp expect file
 '
 
-test_expect_failure 'restore --merge to unresolve after (mistaken) resolution' '
+test_expect_success 'restore --merge to unresolve after (mistaken) resolution' '
 	O=$(echo original | git hash-object -w --stdin) &&
 	A=$(echo ourside | git hash-object -w --stdin) &&
 	B=$(echo theirside | git hash-object -w --stdin) &&
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 4b07a26c14..df582295df 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -543,7 +543,7 @@ test_expect_success 'checkout -m works after (mistaken) resolution' '
 	test_cmp merged file
 '
 
-test_expect_failure 'checkout -m works after (mistaken) resolution to remove' '
+test_expect_success 'checkout -m works after (mistaken) resolution to remove' '
 	setup_conflicting_index &&
 	echo "none of the above" >sample &&
 	cat sample >fild &&
-- 
2.41.0-478-gee48e70a82


  parent reply	other threads:[~2023-07-31 22:45 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-31 22:44 [PATCH 0/7] unresolve removal Junio C Hamano
2023-07-31 22:44 ` [PATCH 1/7] update-index: do not read HEAD and MERGE_HEAD unconditionally Junio C Hamano
2023-07-31 22:44 ` [PATCH 2/7] resolve-undo: allow resurrecting conflicted state that resolved to deletion Junio C Hamano
2023-07-31 22:44 ` [PATCH 3/7] update-index: use unmerge_index_entry() to support removal Junio C Hamano
2023-07-31 23:14   ` Junio C Hamano
2023-07-31 22:44 ` [PATCH 4/7] update-index: remove stale fallback code for "--unresolve" Junio C Hamano
2023-07-31 22:44 ` [PATCH 5/7] checkout/restore: refuse unmerging paths unless checking out of the index Junio C Hamano
2023-07-31 22:44 ` [PATCH 6/7] checkout/restore: add basic tests for --merge Junio C Hamano
2023-07-31 22:44 ` Junio C Hamano [this message]
2023-08-04 19:03 ` [PATCH 0/7] unresolve removal Taylor Blau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230731224409.4181277-8-gitster@pobox.com \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).