Merge branch 'sh/enable-preloadindex'
[gitweb.git] / read-cache.c
index 4b4effd64b842173d6a06656935436515c755242..7f5645e74546e459efdb584dbf63e1fd75857317 100644 (file)
@@ -48,6 +48,7 @@ static void replace_index_entry(struct index_state *istate, int nr, struct cache
        struct cache_entry *old = istate->cache[nr];
 
        remove_name_hash(istate, old);
+       free(old);
        set_index_entry(istate, nr, ce);
        istate->cache_changed = 1;
 }
@@ -59,7 +60,7 @@ void rename_index_entry_at(struct index_state *istate, int nr, const char *new_n
 
        new = xmalloc(cache_entry_size(namelen));
        copy_cache_entry(new, old);
-       new->ce_flags &= ~CE_STATE_MASK;
+       new->ce_flags &= ~CE_HASHED;
        new->ce_namelen = namelen;
        memcpy(new->name, new_name, namelen + 1);
 
@@ -479,6 +480,7 @@ int remove_index_entry_at(struct index_state *istate, int pos)
 
        record_resolve_undo(istate, ce);
        remove_name_hash(istate, ce);
+       free(ce);
        istate->cache_changed = 1;
        istate->cache_nr--;
        if (pos >= istate->cache_nr)
@@ -500,8 +502,10 @@ void remove_marked_cache_entries(struct index_state *istate)
        unsigned int i, j;
 
        for (i = j = 0; i < istate->cache_nr; i++) {
-               if (ce_array[i]->ce_flags & CE_REMOVE)
+               if (ce_array[i]->ce_flags & CE_REMOVE) {
                        remove_name_hash(istate, ce_array[i]);
+                       free(ce_array[i]);
+               }
                else
                        ce_array[j++] = ce_array[i];
        }
@@ -580,7 +584,7 @@ static struct cache_entry *create_alias_ce(struct cache_entry *ce, struct cache_
        return new;
 }
 
-static void record_intent_to_add(struct cache_entry *ce)
+void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)
 {
        unsigned char sha1[20];
        if (write_sha1_file("", 0, blob_type, sha1))
@@ -666,7 +670,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
                if (index_path(ce->sha1, path, st, HASH_WRITE_OBJECT))
                        return error("unable to index file %s", path);
        } else
-               record_intent_to_add(ce);
+               set_object_name_for_intent_to_add_entry(ce);
 
        if (ignore_case && alias && different_name(ce, alias))
                ce = create_alias_ce(ce, alias);
@@ -986,11 +990,7 @@ int add_index_entry(struct index_state *istate, struct cache_entry *ce, int opti
        }
 
        /* Make sure the array is big enough .. */
-       if (istate->cache_nr == istate->cache_alloc) {
-               istate->cache_alloc = alloc_nr(istate->cache_alloc);
-               istate->cache = xrealloc(istate->cache,
-                                       istate->cache_alloc * sizeof(*istate->cache));
-       }
+       ALLOC_GROW(istate->cache, istate->cache_nr + 1, istate->cache_alloc);
 
        /* Add it in.. */
        istate->cache_nr++;
@@ -1216,6 +1216,42 @@ static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
 
 #define INDEX_FORMAT_DEFAULT 3
 
+static int index_format_config(const char *var, const char *value, void *cb)
+{
+       unsigned int *version = cb;
+       if (!strcmp(var, "index.version")) {
+               *version = git_config_int(var, value);
+               return 0;
+       }
+       return 1;
+}
+
+static unsigned int get_index_format_default(void)
+{
+       char *envversion = getenv("GIT_INDEX_VERSION");
+       char *endp;
+       unsigned int version = INDEX_FORMAT_DEFAULT;
+
+       if (!envversion) {
+               git_config(index_format_config, &version);
+               if (version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < version) {
+                       warning(_("index.version set, but the value is invalid.\n"
+                                 "Using version %i"), INDEX_FORMAT_DEFAULT);
+                       return INDEX_FORMAT_DEFAULT;
+               }
+               return version;
+       }
+
+       version = strtoul(envversion, &endp, 10);
+       if (*endp ||
+           version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < version) {
+               warning(_("GIT_INDEX_VERSION set, but the value is invalid.\n"
+                         "Using version %i"), INDEX_FORMAT_DEFAULT);
+               version = INDEX_FORMAT_DEFAULT;
+       }
+       return version;
+}
+
 /*
  * dev/ino/uid/gid/size are also just tracked to the low 32 bits
  * Again - this is just a (very strong in practice) heuristic that
@@ -1310,26 +1346,6 @@ int read_index(struct index_state *istate)
        return read_index_from(istate, get_index_file());
 }
 
-#ifndef NEEDS_ALIGNED_ACCESS
-#define ntoh_s(var) ntohs(var)
-#define ntoh_l(var) ntohl(var)
-#else
-static inline uint16_t ntoh_s_force_align(void *p)
-{
-       uint16_t x;
-       memcpy(&x, p, sizeof(x));
-       return ntohs(x);
-}
-static inline uint32_t ntoh_l_force_align(void *p)
-{
-       uint32_t x;
-       memcpy(&x, p, sizeof(x));
-       return ntohl(x);
-}
-#define ntoh_s(var) ntoh_s_force_align(&(var))
-#define ntoh_l(var) ntoh_l_force_align(&(var))
-#endif
-
 static struct cache_entry *cache_entry_from_ondisk(struct ondisk_cache_entry *ondisk,
                                                   unsigned int flags,
                                                   const char *name,
@@ -1337,16 +1353,16 @@ static struct cache_entry *cache_entry_from_ondisk(struct ondisk_cache_entry *on
 {
        struct cache_entry *ce = xmalloc(cache_entry_size(len));
 
-       ce->ce_stat_data.sd_ctime.sec = ntoh_l(ondisk->ctime.sec);
-       ce->ce_stat_data.sd_mtime.sec = ntoh_l(ondisk->mtime.sec);
-       ce->ce_stat_data.sd_ctime.nsec = ntoh_l(ondisk->ctime.nsec);
-       ce->ce_stat_data.sd_mtime.nsec = ntoh_l(ondisk->mtime.nsec);
-       ce->ce_stat_data.sd_dev   = ntoh_l(ondisk->dev);
-       ce->ce_stat_data.sd_ino   = ntoh_l(ondisk->ino);
-       ce->ce_mode  = ntoh_l(ondisk->mode);
-       ce->ce_stat_data.sd_uid   = ntoh_l(ondisk->uid);
-       ce->ce_stat_data.sd_gid   = ntoh_l(ondisk->gid);
-       ce->ce_stat_data.sd_size  = ntoh_l(ondisk->size);
+       ce->ce_stat_data.sd_ctime.sec = get_be32(&ondisk->ctime.sec);
+       ce->ce_stat_data.sd_mtime.sec = get_be32(&ondisk->mtime.sec);
+       ce->ce_stat_data.sd_ctime.nsec = get_be32(&ondisk->ctime.nsec);
+       ce->ce_stat_data.sd_mtime.nsec = get_be32(&ondisk->mtime.nsec);
+       ce->ce_stat_data.sd_dev   = get_be32(&ondisk->dev);
+       ce->ce_stat_data.sd_ino   = get_be32(&ondisk->ino);
+       ce->ce_mode  = get_be32(&ondisk->mode);
+       ce->ce_stat_data.sd_uid   = get_be32(&ondisk->uid);
+       ce->ce_stat_data.sd_gid   = get_be32(&ondisk->gid);
+       ce->ce_stat_data.sd_size  = get_be32(&ondisk->size);
        ce->ce_flags = flags & ~CE_NAMEMASK;
        ce->ce_namelen = len;
        hashcpy(ce->sha1, ondisk->sha1);
@@ -1386,14 +1402,14 @@ static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk,
        unsigned int flags;
 
        /* On-disk flags are just 16 bits */
-       flags = ntoh_s(ondisk->flags);
+       flags = get_be16(&ondisk->flags);
        len = flags & CE_NAMEMASK;
 
        if (flags & CE_EXTENDED) {
                struct ondisk_cache_entry_extended *ondisk2;
                int extended_flags;
                ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
-               extended_flags = ntoh_s(ondisk2->flags2) << 16;
+               extended_flags = get_be16(&ondisk2->flags2) << 16;
                /* We do not yet understand any bit out of CE_EXTENDED_FLAGS */
                if (extended_flags & ~CE_EXTENDED_FLAGS)
                        die("Unknown index entry format %08x", extended_flags);
@@ -1461,6 +1477,7 @@ int read_index_from(struct index_state *istate, const char *path)
        if (verify_hdr(hdr, mmap_size) < 0)
                goto unmap;
 
+       hashcpy(istate->sha1, (unsigned char *)hdr + mmap_size - 20);
        istate->version = ntohl(hdr->hdr_version);
        istate->cache_nr = ntohl(hdr->hdr_entries);
        istate->cache_alloc = alloc_nr(istate->cache_nr);
@@ -1744,6 +1761,50 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce,
        return result;
 }
 
+/*
+ * This function verifies if index_state has the correct sha1 of the
+ * index file.  Don't die if we have any other failure, just return 0.
+ */
+static int verify_index_from(const struct index_state *istate, const char *path)
+{
+       int fd;
+       ssize_t n;
+       struct stat st;
+       unsigned char sha1[20];
+
+       if (!istate->initialized)
+               return 0;
+
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
+               return 0;
+
+       if (fstat(fd, &st))
+               goto out;
+
+       if (st.st_size < sizeof(struct cache_header) + 20)
+               goto out;
+
+       n = pread_in_full(fd, sha1, 20, st.st_size - 20);
+       if (n != 20)
+               goto out;
+
+       if (hashcmp(istate->sha1, sha1))
+               goto out;
+
+       close(fd);
+       return 1;
+
+out:
+       close(fd);
+       return 0;
+}
+
+static int verify_index(const struct index_state *istate)
+{
+       return verify_index_from(istate, get_index_file());
+}
+
 static int has_racy_timestamp(struct index_state *istate)
 {
        int entries = istate->cache_nr;
@@ -1763,7 +1824,7 @@ static int has_racy_timestamp(struct index_state *istate)
 void update_index_if_able(struct index_state *istate, struct lock_file *lockfile)
 {
        if ((istate->cache_changed || has_racy_timestamp(istate)) &&
-           !write_index(istate, lockfile->fd))
+           verify_index(istate) && !write_index(istate, lockfile->fd))
                commit_locked_index(lockfile);
        else
                rollback_lock_file(lockfile);
@@ -1792,7 +1853,7 @@ int write_index(struct index_state *istate, int newfd)
        }
 
        if (!istate->version)
-               istate->version = INDEX_FORMAT_DEFAULT;
+               istate->version = get_index_format_default();
 
        /* demote version 3 to version 2 when the latter suffices */
        if (istate->version == 3 || istate->version == 2)
@@ -1891,7 +1952,7 @@ int read_index_unmerged(struct index_state *istate)
                new_ce->ce_mode = ce->ce_mode;
                if (add_index_entry(istate, new_ce, 0))
                        return error("%s: cannot drop to stage #0",
-                                    ce->name);
+                                    new_ce->name);
                i = index_name_pos(istate, new_ce->name, len);
        }
        return unmerged;