[PATCH] Handle entry removals during merge correctly.
- From
Junio C Hamano <junkio@cox.net>
- Date
- Jun 9, 2005, 22:47 UTC
- Message-ID
- <7voeaf9mhd.fsf_-_@assigned-by-dhcp.cox.net>
- In-Reply-To
- <Pine.LNX.4.58.0506091152530.2286@ppc970.osdl.org>
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 <junkio@cox.net> ---
*** 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) ------------