Thread (1 message) 1 message, 1 author, 2016-06-15
DORMANTno replies

[PATCH] Handle entry removals during merge correctly.

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:41:59
Subsystem: the rest · Maintainer: Linus Torvalds

From: Linus Torvalds <torvalds@osdl.org>

We could handle delete the same way - to set the ce_mode to zero
and add them to the "dst" array, and teach write-cache not to
write them out. Then the same loop that goes around doing the
CE_UPDATE thing could check for the delete case.

Signed-off-by: Junio C Hamano <redacted>
---

*** Linus, did I get the patch submission format right?  This is
*** essentially what you wrote (with one correction) but not
*** really "a forwarded e-mail".

 read-cache.c |   10 ++++++++--
 read-tree.c  |   30 ++++++++++++++++++++----------
 2 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/read-cache.c b/read-cache.c
--- a/read-cache.c
+++ b/read-cache.c
@@ -440,11 +440,15 @@ int write_cache(int newfd, struct cache_
 {
 	SHA_CTX c;
 	struct cache_header hdr;
-	int i;
+	int i, removed;
+
+	for (i = removed = 0; i < entries; i++)
+		if (!cache[i]->ce_mode)
+			removed++;
 
 	hdr.hdr_signature = htonl(CACHE_SIGNATURE);
 	hdr.hdr_version = htonl(2);
-	hdr.hdr_entries = htonl(entries);
+	hdr.hdr_entries = htonl(entries - removed);
 
 	SHA1_Init(&c);
 	if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
@@ -452,6 +456,8 @@ int write_cache(int newfd, struct cache_
 
 	for (i = 0; i < entries; i++) {
 		struct cache_entry *ce = cache[i];
+		if (!ce->ce_mode)
+			continue;
 		if (ce_write(&c, newfd, ce, ce_size(ce)) < 0)
 			return -1;
 	}
diff --git a/read-tree.c b/read-tree.c
--- a/read-tree.c
+++ b/read-tree.c
@@ -124,6 +124,15 @@ static int merged_entry(struct cache_ent
 	return 1;
 }
 
+static int deleted_entry(struct cache_entry *ce, struct cache_entry *old, struct cache_entry **dst)
+{
+	if (old)
+		verify_uptodate(old);
+	ce->ce_mode = 0;
+	*dst++ = ce;
+	return 1;
+}
+
 static int threeway_merge(struct cache_entry *stages[4], struct cache_entry **dst)
 {
 	struct cache_entry *i = stages[0];
@@ -181,25 +190,21 @@ static int twoway_merge(struct cache_ent
 			*dst++ = current;
 			return 1;
 		}
-		else if (oldtree && !newtree && same(current, oldtree)) {
+		else if (oldtree && !newtree && same(current, oldtree))
 			/* 10 or 11 */
-			verify_uptodate(current);
-			return 0;
-		}
+			return deleted_entry(oldtree, current, dst);
 		else if (oldtree && newtree &&
-			 same(current, oldtree) && !same(current, newtree)) {
+			 same(current, oldtree) && !same(current, newtree))
 			/* 20 or 21 */
-			verify_uptodate(current);
-			return merged_entry(newtree, NULL, dst);
-		}
+			return merged_entry(newtree, current, dst);
 		else
 			/* all other failures */
 			return -1;
 	}
 	else if (newtree)
-		return merged_entry(newtree, NULL, dst);
+		return merged_entry(newtree, current, dst);
 	else
-		return 0;
+		return deleted_entry(oldtree, current, dst);
 }
 
 /*
@@ -236,6 +241,11 @@ static void check_updates(struct cache_e
 	unsigned short mask = htons(CE_UPDATE);
 	while (nr--) {
 		struct cache_entry *ce = *src++;
+		if (!ce->ce_mode) {
+			if (update)
+				unlink(ce->name);
+			continue;
+		}
 		if (ce->ce_flags & mask) {
 			ce->ce_flags &= ~mask;
 			if (update)
------------
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help