Use helper function for copying index entry information
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 23 Feb 2008 04:41:17 +0000 (20:41 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sat, 23 Feb 2008 05:24:47 +0000 (21:24 -0800)
We used to just memcpy() the index entry when we copied the stat() and
SHA1 hash information, which worked well enough back when the index
entry was just an exact bit-for-bit representation of the information on
disk.

However, these days we actually have various management information in
the cache entry too, and we should be careful to not overwrite it when
we copy the stat information from another index entry.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
cache.h
unpack-trees.c

diff --git a/cache.h b/cache.h
index 88d3b92d2ec7a8a601d84002a0c862b9db307548..fa5a9e523eda0f075a4e36fcf3b4c0760e54f583 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -110,7 +110,6 @@ struct ondisk_cache_entry {
 };
 
 struct cache_entry {
-       struct cache_entry *next;
        unsigned int ce_ctime;
        unsigned int ce_mtime;
        unsigned int ce_dev;
@@ -121,6 +120,7 @@ struct cache_entry {
        unsigned int ce_size;
        unsigned int ce_flags;
        unsigned char sha1[20];
+       struct cache_entry *next;
        char name[FLEX_ARRAY]; /* more */
 };
 
@@ -137,6 +137,22 @@ struct cache_entry {
 #define CE_HASHED    (0x100000)
 #define CE_UNHASHED  (0x200000)
 
+/*
+ * Copy the sha1 and stat state of a cache entry from one to
+ * another. But we never change the name, or the hash state!
+ */
+#define CE_STATE_MASK (CE_HASHED | CE_UNHASHED)
+static inline void copy_cache_entry(struct cache_entry *dst, struct cache_entry *src)
+{
+       unsigned int state = dst->ce_flags & CE_STATE_MASK;
+
+       /* Don't copy hash chain and name */
+       memcpy(dst, src, offsetof(struct cache_entry, next));
+
+       /* Restore the hash state */
+       dst->ce_flags = (dst->ce_flags & ~CE_STATE_MASK) | state;
+}
+
 /*
  * We don't actually *remove* it, we can just mark it invalid so that
  * we won't find it in lookups.
index ec558f9005fab372f9bf62d8c3df9ea34f5222bb..07c4c28a5a0a38a3ae81cccd967ba3117917a513 100644 (file)
@@ -590,7 +590,7 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old,
                 * a match.
                 */
                if (same(old, merge)) {
-                       memcpy(merge, old, offsetof(struct cache_entry, name));
+                       copy_cache_entry(merge, old);
                } else {
                        verify_uptodate(old, o);
                        invalidate_ce_path(old);