read-cache: clean up casting and byte decoding
[gitweb.git] / read-cache.c
index 7b1354d7590a70ecbd6e508bdd95eafd4793efcc..6ba99e2c9692ce394efd646162f07885ccacf86d 100644 (file)
@@ -213,7 +213,7 @@ static int ce_compare_data(const struct cache_entry *ce, struct stat *st)
        if (fd >= 0) {
                struct object_id oid;
                if (!index_fd(&oid, fd, st, OBJ_BLOB, ce->name, 0))
-                       match = oidcmp(&oid, &ce->oid);
+                       match = !oideq(&oid, &ce->oid);
                /* index_fd() closed the file descriptor already */
        }
        return match;
@@ -254,7 +254,7 @@ static int ce_compare_gitlink(const struct cache_entry *ce)
         */
        if (resolve_gitlink_ref(ce->name, "HEAD", &oid) < 0)
                return 0;
-       return oidcmp(&oid, &ce->oid);
+       return !oideq(&oid, &ce->oid);
 }
 
 static int ce_modified_check_fs(const struct cache_entry *ce, struct stat *st)
@@ -767,7 +767,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
        /* It was suspected to be racily clean, but it turns out to be Ok */
        was_same = (alias &&
                    !ce_stage(alias) &&
-                   !oidcmp(&alias->oid, &ce->oid) &&
+                   oideq(&alias->oid, &ce->oid) &&
                    ce->ce_mode == alias->ce_mode);
 
        if (pretend)
@@ -1476,8 +1476,8 @@ int refresh_index(struct index_state *istate, unsigned int flags,
        const char *typechange_fmt;
        const char *added_fmt;
        const char *unmerged_fmt;
-       uint64_t start = getnanotime();
 
+       trace_performance_enter();
        modified_fmt = (in_porcelain ? "M\t%s\n" : "%s: needs update\n");
        deleted_fmt = (in_porcelain ? "D\t%s\n" : "%s: needs update\n");
        typechange_fmt = (in_porcelain ? "T\t%s\n" : "%s needs update\n");
@@ -1547,7 +1547,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
 
                replace_index_entry(istate, i, new_entry);
        }
-       trace_performance_since(start, "refresh index");
+       trace_performance_leave("refresh index");
        return has_errors;
 }
 
@@ -1650,7 +1650,7 @@ int verify_index_checksum;
 /* Allow fsck to force verification of the cache entry order. */
 int verify_ce_order;
 
-static int verify_hdr(struct cache_header *hdr, unsigned long size)
+static int verify_hdr(const struct cache_header *hdr, unsigned long size)
 {
        git_hash_ctx c;
        unsigned char hash[GIT_MAX_RAWSZ];
@@ -1668,13 +1668,13 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
        the_hash_algo->init_fn(&c);
        the_hash_algo->update_fn(&c, hdr, size - the_hash_algo->rawsz);
        the_hash_algo->final_fn(hash, &c);
-       if (hashcmp(hash, (unsigned char *)hdr + size - the_hash_algo->rawsz))
+       if (!hasheq(hash, (unsigned char *)hdr + size - the_hash_algo->rawsz))
                return error("bad index file sha1 signature");
        return 0;
 }
 
 static int read_index_extension(struct index_state *istate,
-                               const char *ext, void *data, unsigned long sz)
+                               const char *ext, const char *data, unsigned long sz)
 {
        switch (CACHE_EXT(ext)) {
        case CACHE_EXT_TREE:
@@ -1713,63 +1713,24 @@ int read_index(struct index_state *istate)
        return read_index_from(istate, get_index_file(), get_git_dir());
 }
 
-static struct cache_entry *cache_entry_from_ondisk(struct mem_pool *mem_pool,
-                                                  struct ondisk_cache_entry *ondisk,
-                                                  unsigned int flags,
-                                                  const char *name,
-                                                  size_t len)
-{
-       struct cache_entry *ce = mem_pool__ce_alloc(mem_pool, len);
-
-       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;
-       ce->index = 0;
-       hashcpy(ce->oid.hash, ondisk->sha1);
-       memcpy(ce->name, name, len);
-       ce->name[len] = '\0';
-       return ce;
-}
-
-/*
- * Adjacent cache entries tend to share the leading paths, so it makes
- * sense to only store the differences in later entries.  In the v4
- * on-disk format of the index, each on-disk cache entry stores the
- * number of bytes to be stripped from the end of the previous name,
- * and the bytes to append to the result, to come up with its name.
- */
-static unsigned long expand_name_field(struct strbuf *name, const char *cp_)
-{
-       const unsigned char *ep, *cp = (const unsigned char *)cp_;
-       size_t len = decode_varint(&cp);
-
-       if (name->len < len)
-               die("malformed name field in the index");
-       strbuf_remove(name, name->len - len, len);
-       for (ep = cp; *ep; ep++)
-               ; /* find the end */
-       strbuf_add(name, cp, ep - cp);
-       return (const char *)ep + 1 - cp_;
-}
-
-static struct cache_entry *create_from_disk(struct mem_pool *mem_pool,
+static struct cache_entry *create_from_disk(struct index_state *istate,
                                            struct ondisk_cache_entry *ondisk,
                                            unsigned long *ent_size,
-                                           struct strbuf *previous_name)
+                                           const struct cache_entry *previous_ce)
 {
        struct cache_entry *ce;
        size_t len;
        const char *name;
        unsigned int flags;
+       size_t copy_len;
+       /*
+        * Adjacent cache entries tend to share the leading paths, so it makes
+        * sense to only store the differences in later entries.  In the v4
+        * on-disk format of the index, each on-disk cache entry stores the
+        * number of bytes to be stripped from the end of the previous name,
+        * and the bytes to append to the result, to come up with its name.
+        */
+       int expand_name_field = istate->version == 4;
 
        /* On-disk flags are just 16 bits */
        flags = get_be16(&ondisk->flags);
@@ -1789,21 +1750,54 @@ static struct cache_entry *create_from_disk(struct mem_pool *mem_pool,
        else
                name = ondisk->name;
 
-       if (!previous_name) {
-               /* v3 and earlier */
-               if (len == CE_NAMEMASK)
-                       len = strlen(name);
-               ce = cache_entry_from_ondisk(mem_pool, ondisk, flags, name, len);
+       if (expand_name_field) {
+               const unsigned char *cp = (const unsigned char *)name;
+               size_t strip_len, previous_len;
 
-               *ent_size = ondisk_ce_size(ce);
-       } else {
-               unsigned long consumed;
-               consumed = expand_name_field(previous_name, name);
-               ce = cache_entry_from_ondisk(mem_pool, ondisk, flags,
-                                            previous_name->buf,
-                                            previous_name->len);
+               previous_len = previous_ce ? previous_ce->ce_namelen : 0;
+               strip_len = decode_varint(&cp);
+               if (previous_len < strip_len) {
+                       if (previous_ce)
+                               die(_("malformed name field in the index, near path '%s'"),
+                                   previous_ce->name);
+                       else
+                               die(_("malformed name field in the index in the first path"));
+               }
+               copy_len = previous_len - strip_len;
+               name = (const char *)cp;
+       }
 
-               *ent_size = (name - ((char *)ondisk)) + consumed;
+       if (len == CE_NAMEMASK) {
+               len = strlen(name);
+               if (expand_name_field)
+                       len += copy_len;
+       }
+
+       ce = mem_pool__ce_alloc(istate->ce_mem_pool, len);
+
+       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;
+       ce->index = 0;
+       hashcpy(ce->oid.hash, ondisk->sha1);
+
+       if (expand_name_field) {
+               if (copy_len)
+                       memcpy(ce->name, previous_ce->name, copy_len);
+               memcpy(ce->name + copy_len, name, len + 1 - copy_len);
+               *ent_size = (name - ((char *)ondisk)) + len + 1 - copy_len;
+       } else {
+               memcpy(ce->name, name, len + 1);
+               *ent_size = ondisk_ce_size(ce);
        }
        return ce;
 }
@@ -1895,10 +1889,10 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
        int fd, i;
        struct stat st;
        unsigned long src_offset;
-       struct cache_header *hdr;
-       void *mmap;
+       const struct cache_header *hdr;
+       const char *mmap;
        size_t mmap_size;
-       struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
+       const struct cache_entry *previous_ce = NULL;
 
        if (istate->initialized)
                return istate->cache_nr;
@@ -1924,7 +1918,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
                die_errno("unable to map index file");
        close(fd);
 
-       hdr = mmap;
+       hdr = (const struct cache_header *)mmap;
        if (verify_hdr(hdr, mmap_size) < 0)
                goto unmap;
 
@@ -1936,11 +1930,9 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
        istate->initialized = 1;
 
        if (istate->version == 4) {
-               previous_name = &previous_name_buf;
                mem_pool_init(&istate->ce_mem_pool,
                              estimate_cache_size_from_compressed(istate->cache_nr));
        } else {
-               previous_name = NULL;
                mem_pool_init(&istate->ce_mem_pool,
                              estimate_cache_size(mmap_size, istate->cache_nr));
        }
@@ -1951,13 +1943,13 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
                struct cache_entry *ce;
                unsigned long consumed;
 
-               disk_ce = (struct ondisk_cache_entry *)((char *)mmap + src_offset);
-               ce = create_from_disk(istate->ce_mem_pool, disk_ce, &consumed, previous_name);
+               disk_ce = (struct ondisk_cache_entry *)(mmap + src_offset);
+               ce = create_from_disk(istate, disk_ce, &consumed, previous_ce);
                set_index_entry(istate, i, ce);
 
                src_offset += consumed;
+               previous_ce = ce;
        }
-       strbuf_release(&previous_name_buf);
        istate->timestamp.sec = st.st_mtime;
        istate->timestamp.nsec = ST_MTIME_NSEC(st);
 
@@ -1969,21 +1961,20 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
                 * in 4-byte network byte order.
                 */
                uint32_t extsize;
-               memcpy(&extsize, (char *)mmap + src_offset + 4, 4);
-               extsize = ntohl(extsize);
+               extsize = get_be32(mmap + src_offset + 4);
                if (read_index_extension(istate,
-                                        (const char *) mmap + src_offset,
-                                        (char *) mmap + src_offset + 8,
+                                        mmap + src_offset,
+                                        mmap + src_offset + 8,
                                         extsize) < 0)
                        goto unmap;
                src_offset += 8;
                src_offset += extsize;
        }
-       munmap(mmap, mmap_size);
+       munmap((void *)mmap, mmap_size);
        return istate->cache_nr;
 
 unmap:
-       munmap(mmap, mmap_size);
+       munmap((void *)mmap, mmap_size);
        die("index file corrupt");
 }
 
@@ -2002,7 +1993,6 @@ static void freshen_shared_index(const char *shared_index, int warn)
 int read_index_from(struct index_state *istate, const char *path,
                    const char *gitdir)
 {
-       uint64_t start = getnanotime();
        struct split_index *split_index;
        int ret;
        char *base_oid_hex;
@@ -2012,8 +2002,9 @@ int read_index_from(struct index_state *istate, const char *path,
        if (istate->initialized)
                return istate->cache_nr;
 
+       trace_performance_enter();
        ret = do_read_index(istate, path, 0);
-       trace_performance_since(start, "read cache %s", path);
+       trace_performance_leave("read cache %s", path);
 
        split_index = istate->split_index;
        if (!split_index || is_null_oid(&split_index->base_oid)) {
@@ -2021,6 +2012,7 @@ int read_index_from(struct index_state *istate, const char *path,
                return ret;
        }
 
+       trace_performance_enter();
        if (split_index->base)
                discard_index(split_index->base);
        else
@@ -2029,7 +2021,7 @@ int read_index_from(struct index_state *istate, const char *path,
        base_oid_hex = oid_to_hex(&split_index->base_oid);
        base_path = xstrfmt("%s/sharedindex.%s", gitdir, base_oid_hex);
        ret = do_read_index(split_index->base, base_path, 1);
-       if (oidcmp(&split_index->base_oid, &split_index->base->oid))
+       if (!oideq(&split_index->base_oid, &split_index->base->oid))
                die("broken index, expect %s in %s, got %s",
                    base_oid_hex, base_path,
                    oid_to_hex(&split_index->base->oid));
@@ -2037,8 +2029,8 @@ int read_index_from(struct index_state *istate, const char *path,
        freshen_shared_index(base_path, 0);
        merge_base_index(istate);
        post_read_index_from(istate);
-       trace_performance_since(start, "read cache %s", base_path);
        free(base_path);
+       trace_performance_leave("read cache %s", base_path);
        return ret;
 }
 
@@ -2395,7 +2387,7 @@ static int verify_index_from(const struct index_state *istate, const char *path)
        if (n != the_hash_algo->rawsz)
                goto out;
 
-       if (hashcmp(istate->oid.hash, hash))
+       if (!hasheq(istate->oid.hash, hash))
                goto out;
 
        close(fd);
@@ -2743,6 +2735,9 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
        int new_shared_index, ret;
        struct split_index *si = istate->split_index;
 
+       if (git_env_bool("GIT_TEST_CHECK_CACHE_TREE", 0))
+               cache_tree_verify(istate);
+
        if ((flags & SKIP_IF_UNCHANGED) && !istate->cache_changed) {
                if (flags & COMMIT_LOCK)
                        rollback_lock_file(lock);
@@ -2939,6 +2934,8 @@ void move_index_extensions(struct index_state *dst, struct index_state *src)
 {
        dst->untracked = src->untracked;
        src->untracked = NULL;
+       dst->cache_tree = src->cache_tree;
+       src->cache_tree = NULL;
 }
 
 struct cache_entry *dup_cache_entry(const struct cache_entry *ce,