]> git.ipfire.org Git - thirdparty/git.git/blobdiff - read-cache.c
t2203: avoid hard-coded object ID values
[thirdparty/git.git] / read-cache.c
index b298c7f5351d572a300cf274dffb7ee5b00bc9df..4dd22f4f6eb60ffa8f7c31a535a14b16fb403e53 100644 (file)
@@ -17,6 +17,7 @@
 #include "commit.h"
 #include "blob.h"
 #include "resolve-undo.h"
+#include "run-command.h"
 #include "strbuf.h"
 #include "varint.h"
 #include "split-index.h"
@@ -194,7 +195,7 @@ int match_stat_data(const struct stat_data *sd, struct stat *st)
  * cache, ie the parts that aren't tracked by GIT, and only used
  * to validate the cache.
  */
-void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
+void fill_stat_cache_info(struct index_state *istate, struct cache_entry *ce, struct stat *st)
 {
        fill_stat_data(&ce->ce_stat_data, st);
 
@@ -203,7 +204,7 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
 
        if (S_ISREG(st->st_mode)) {
                ce_mark_uptodate(ce);
-               mark_fsmonitor_valid(ce);
+               mark_fsmonitor_valid(istate, ce);
        }
 }
 
@@ -588,13 +589,19 @@ int remove_index_entry_at(struct index_state *istate, int pos)
  * CE_REMOVE is set in ce_flags.  This is much more effective than
  * calling remove_index_entry_at() for each entry to be removed.
  */
-void remove_marked_cache_entries(struct index_state *istate)
+void remove_marked_cache_entries(struct index_state *istate, int invalidate)
 {
        struct cache_entry **ce_array = istate->cache;
        unsigned int i, j;
 
        for (i = j = 0; i < istate->cache_nr; i++) {
                if (ce_array[i]->ce_flags & CE_REMOVE) {
+                       if (invalidate) {
+                               cache_tree_invalidate_path(istate,
+                                                          ce_array[i]->name);
+                               untracked_cache_remove_from_index(istate,
+                                                                 ce_array[i]->name);
+                       }
                        remove_name_hash(istate, ce_array[i]);
                        save_or_free_index_entry(istate, ce_array[i]);
                }
@@ -702,6 +709,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
        int add_option = (ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|
                          (intent_only ? ADD_CACHE_NEW_ONLY : 0));
        int hash_flags = HASH_WRITE_OBJECT;
+       struct object_id oid;
 
        if (flags & ADD_CACHE_RENORMALIZE)
                hash_flags |= HASH_RENORMALIZE;
@@ -711,6 +719,8 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
 
        namelen = strlen(path);
        if (S_ISDIR(st_mode)) {
+               if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
+                       return error(_("'%s' does not have a commit checked out"), path);
                while (namelen && path[namelen-1] == '/')
                        namelen--;
        }
@@ -718,7 +728,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
        memcpy(ce->name, path, namelen);
        ce->ce_namelen = namelen;
        if (!intent_only)
-               fill_stat_cache_info(ce, st);
+               fill_stat_cache_info(istate, ce, st);
        else
                ce->ce_flags |= CE_INTENT_TO_ADD;
 
@@ -1422,7 +1432,7 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
                         */
                        if (!S_ISGITLINK(ce->ce_mode)) {
                                ce_mark_uptodate(ce);
-                               mark_fsmonitor_valid(ce);
+                               mark_fsmonitor_valid(istate, ce);
                        }
                        return ce;
                }
@@ -1437,7 +1447,7 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
        updated = make_empty_cache_entry(istate, ce_namelen(ce));
        copy_cache_entry(updated, ce);
        memcpy(updated->name, ce->name, ce->ce_namelen + 1);
-       fill_stat_cache_info(updated, &st);
+       fill_stat_cache_info(istate, updated, &st);
        /*
         * If ignore_valid is not set, we should leave CE_VALID bit
         * alone.  Otherwise, paths marked with --no-assume-unchanged
@@ -1634,39 +1644,24 @@ struct ondisk_cache_entry {
        uint32_t uid;
        uint32_t gid;
        uint32_t size;
-       unsigned char sha1[20];
-       uint16_t flags;
-       char name[FLEX_ARRAY]; /* more */
-};
-
-/*
- * This struct is used when CE_EXTENDED bit is 1
- * The struct must match ondisk_cache_entry exactly from
- * ctime till flags
- */
-struct ondisk_cache_entry_extended {
-       struct cache_time ctime;
-       struct cache_time mtime;
-       uint32_t dev;
-       uint32_t ino;
-       uint32_t mode;
-       uint32_t uid;
-       uint32_t gid;
-       uint32_t size;
-       unsigned char sha1[20];
-       uint16_t flags;
-       uint16_t flags2;
-       char name[FLEX_ARRAY]; /* more */
+       /*
+        * unsigned char hash[hashsz];
+        * uint16_t flags;
+        * if (flags & CE_EXTENDED)
+        *      uint16_t flags2;
+        */
+       unsigned char data[GIT_MAX_RAWSZ + 2 * sizeof(uint16_t)];
+       char name[FLEX_ARRAY];
 };
 
 /* These are only used for v3 or lower */
 #define align_padding_size(size, len) ((size + (len) + 8) & ~7) - (size + len)
-#define align_flex_name(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7)
+#define align_flex_name(STRUCT,len) ((offsetof(struct STRUCT,data) + (len) + 8) & ~7)
 #define ondisk_cache_entry_size(len) align_flex_name(ondisk_cache_entry,len)
-#define ondisk_cache_entry_extended_size(len) align_flex_name(ondisk_cache_entry_extended,len)
-#define ondisk_ce_size(ce) (((ce)->ce_flags & CE_EXTENDED) ? \
-                           ondisk_cache_entry_extended_size(ce_namelen(ce)) : \
-                           ondisk_cache_entry_size(ce_namelen(ce)))
+#define ondisk_data_size(flags, len) (the_hash_algo->rawsz + \
+                                    ((flags & CE_EXTENDED) ? 2 : 1) * sizeof(uint16_t) + len)
+#define ondisk_data_size_max(len) (ondisk_data_size(CE_EXTENDED, len))
+#define ondisk_ce_size(ce) (ondisk_cache_entry_size(ondisk_data_size((ce)->ce_flags, ce_namelen(ce))))
 
 /* Allow fsck to force verification of the index checksum. */
 int verify_index_checksum;
@@ -1740,6 +1735,8 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
        struct cache_entry *ce;
        size_t len;
        const char *name;
+       const unsigned hashsz = the_hash_algo->rawsz;
+       const uint16_t *flagsp = (const uint16_t *)(ondisk->data + hashsz);
        unsigned int flags;
        size_t copy_len = 0;
        /*
@@ -1752,22 +1749,20 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
        int expand_name_field = version == 4;
 
        /* On-disk flags are just 16 bits */
-       flags = get_be16(&ondisk->flags);
+       flags = get_be16(flagsp);
        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 = get_be16(&ondisk2->flags2) << 16;
+               extended_flags = get_be16(flagsp + 1) << 16;
                /* We do not yet understand any bit out of CE_EXTENDED_FLAGS */
                if (extended_flags & ~CE_EXTENDED_FLAGS)
                        die(_("unknown index entry format 0x%08x"), extended_flags);
                flags |= extended_flags;
-               name = ondisk2->name;
+               name = (const char *)(flagsp + 2);
        }
        else
-               name = ondisk->name;
+               name = (const char *)(flagsp + 1);
 
        if (expand_name_field) {
                const unsigned char *cp = (const unsigned char *)name;
@@ -1806,7 +1801,9 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
        ce->ce_flags = flags & ~CE_NAMEMASK;
        ce->ce_namelen = len;
        ce->index = 0;
-       hashcpy(ce->oid.hash, ondisk->sha1);
+       hashcpy(ce->oid.hash, ondisk->data);
+       memcpy(ce->name, name, len);
+       ce->name[len] = '\0';
 
        if (expand_name_field) {
                if (copy_len)
@@ -2040,7 +2037,7 @@ static void *load_cache_entries_thread(void *_data)
 }
 
 static unsigned long load_cache_entries_threaded(struct index_state *istate, const char *mmap, size_t mmap_size,
-                       unsigned long src_offset, int nr_threads, struct index_entry_offset_table *ieot)
+                                                int nr_threads, struct index_entry_offset_table *ieot)
 {
        int i, offset, ieot_blocks, ieot_start, err;
        struct load_cache_entries_thread_data *data;
@@ -2201,7 +2198,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
                ieot = read_ieot_extension(mmap, mmap_size, extension_offset);
 
        if (ieot) {
-               src_offset += load_cache_entries_threaded(istate, mmap, mmap_size, src_offset, nr_threads, ieot);
+               src_offset += load_cache_entries_threaded(istate, mmap, mmap_size, nr_threads, ieot);
                free(ieot);
        } else {
                src_offset += load_all_cache_entries(istate, mmap, mmap_size, src_offset);
@@ -2220,6 +2217,16 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
                load_index_extensions(&p);
        }
        munmap((void *)mmap, mmap_size);
+
+       /*
+        * TODO trace2: replace "the_repository" with the actual repo instance
+        * that is associated with the given "istate".
+        */
+       trace2_data_intmax("index", the_repository, "read/version",
+                          istate->version);
+       trace2_data_intmax("index", the_repository, "read/cache_nr",
+                          istate->cache_nr);
+
        return istate->cache_nr;
 
 unmap:
@@ -2251,9 +2258,17 @@ int read_index_from(struct index_state *istate, const char *path,
        if (istate->initialized)
                return istate->cache_nr;
 
+       /*
+        * TODO trace2: replace "the_repository" with the actual repo instance
+        * that is associated with the given "istate".
+        */
+       trace2_region_enter_printf("index", "do_read_index", the_repository,
+                                  "%s", path);
        trace_performance_enter();
        ret = do_read_index(istate, path, 0);
        trace_performance_leave("read cache %s", path);
+       trace2_region_leave_printf("index", "do_read_index", the_repository,
+                                  "%s", path);
 
        split_index = istate->split_index;
        if (!split_index || is_null_oid(&split_index->base_oid)) {
@@ -2269,7 +2284,11 @@ 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);
+       trace2_region_enter_printf("index", "shared/do_read_index",
+                                  the_repository, "%s", base_path);
        ret = do_read_index(split_index->base, base_path, 1);
+       trace2_region_leave_printf("index", "shared/do_read_index",
+                                  the_repository, "%s", base_path);
        if (!oideq(&split_index->base_oid, &split_index->base->oid))
                die(_("broken index, expect %s in %s, got %s"),
                    base_oid_hex, base_path,
@@ -2529,6 +2548,8 @@ static void copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
                                       struct cache_entry *ce)
 {
        short flags;
+       const unsigned hashsz = the_hash_algo->rawsz;
+       uint16_t *flagsp = (uint16_t *)(ondisk->data + hashsz);
 
        ondisk->ctime.sec = htonl(ce->ce_stat_data.sd_ctime.sec);
        ondisk->mtime.sec = htonl(ce->ce_stat_data.sd_mtime.sec);
@@ -2540,15 +2561,13 @@ static void copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
        ondisk->uid  = htonl(ce->ce_stat_data.sd_uid);
        ondisk->gid  = htonl(ce->ce_stat_data.sd_gid);
        ondisk->size = htonl(ce->ce_stat_data.sd_size);
-       hashcpy(ondisk->sha1, ce->oid.hash);
+       hashcpy(ondisk->data, ce->oid.hash);
 
        flags = ce->ce_flags & ~CE_NAMEMASK;
        flags |= (ce_namelen(ce) >= CE_NAMEMASK ? CE_NAMEMASK : ce_namelen(ce));
-       ondisk->flags = htons(flags);
+       flagsp[0] = htons(flags);
        if (ce->ce_flags & CE_EXTENDED) {
-               struct ondisk_cache_entry_extended *ondisk2;
-               ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
-               ondisk2->flags2 = htons((ce->ce_flags & CE_EXTENDED_FLAGS) >> 16);
+               flagsp[1] = htons((ce->ce_flags & CE_EXTENDED_FLAGS) >> 16);
        }
 }
 
@@ -2567,10 +2586,7 @@ static int ce_write_entry(git_hash_ctx *c, int fd, struct cache_entry *ce,
                stripped_name = 1;
        }
 
-       if (ce->ce_flags & CE_EXTENDED)
-               size = offsetof(struct ondisk_cache_entry_extended, name);
-       else
-               size = offsetof(struct ondisk_cache_entry, name);
+       size = offsetof(struct ondisk_cache_entry,data) + ondisk_data_size(ce->ce_flags, 0);
 
        if (!previous_name) {
                int len = ce_namelen(ce);
@@ -2728,7 +2744,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
        struct cache_entry **cache = istate->cache;
        int entries = istate->cache_nr;
        struct stat st;
-       struct ondisk_cache_entry_extended ondisk;
+       struct ondisk_cache_entry ondisk;
        struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
        int drop_cache_tree = istate->drop_cache_tree;
        off_t offset;
@@ -2895,7 +2911,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
                        return -1;
        }
 
-       if (!strip_extensions && istate->split_index) {
+       if (!strip_extensions && istate->split_index &&
+           !is_null_oid(&istate->split_index->base_oid)) {
                struct strbuf sb = STRBUF_INIT;
 
                err = write_link_extension(&sb, istate) < 0 ||
@@ -2977,6 +2994,16 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
        istate->timestamp.sec = (unsigned int)st.st_mtime;
        istate->timestamp.nsec = ST_MTIME_NSEC(st);
        trace_performance_since(start, "write index, changed mask = %x", istate->cache_changed);
+
+       /*
+        * TODO trace2: replace "the_repository" with the actual repo instance
+        * that is associated with the given "istate".
+        */
+       trace2_data_intmax("index", the_repository, "write/version",
+                          istate->version);
+       trace2_data_intmax("index", the_repository, "write/cache_nr",
+                          istate->cache_nr);
+
        return 0;
 }
 
@@ -2996,12 +3023,32 @@ static int commit_locked_index(struct lock_file *lk)
 static int do_write_locked_index(struct index_state *istate, struct lock_file *lock,
                                 unsigned flags)
 {
-       int ret = do_write_index(istate, lock->tempfile, 0);
+       int ret;
+
+       /*
+        * TODO trace2: replace "the_repository" with the actual repo instance
+        * that is associated with the given "istate".
+        */
+       trace2_region_enter_printf("index", "do_write_index", the_repository,
+                                  "%s", lock->tempfile->filename.buf);
+       ret = do_write_index(istate, lock->tempfile, 0);
+       trace2_region_leave_printf("index", "do_write_index", the_repository,
+                                  "%s", lock->tempfile->filename.buf);
+
        if (ret)
                return ret;
        if (flags & COMMIT_LOCK)
-               return commit_locked_index(lock);
-       return close_lock_file_gently(lock);
+               ret = commit_locked_index(lock);
+       else
+               ret = close_lock_file_gently(lock);
+
+       run_hook_le(NULL, "post-index-change",
+                       istate->updated_workdir ? "1" : "0",
+                       istate->updated_skipworktree ? "1" : "0", NULL);
+       istate->updated_workdir = 0;
+       istate->updated_skipworktree = 0;
+
+       return ret;
 }
 
 static int write_split_index(struct index_state *istate,
@@ -3081,7 +3128,13 @@ static int write_shared_index(struct index_state *istate,
        int ret;
 
        move_cache_to_base_index(istate);
+
+       trace2_region_enter_printf("index", "shared/do_write_index",
+                                  the_repository, "%s", (*temp)->filename.buf);
        ret = do_write_index(si->base, *temp, 1);
+       trace2_region_leave_printf("index", "shared/do_write_index",
+                                  the_repository, "%s", (*temp)->filename.buf);
+
        if (ret)
                return ret;
        ret = adjust_shared_perm(get_tempfile_path(*temp));
@@ -3190,7 +3243,7 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
        ret = write_split_index(istate, lock, flags);
 
        /* Freshen the shared index only if the split-index was written */
-       if (!ret && !new_shared_index) {
+       if (!ret && !new_shared_index && !is_null_oid(&si->base_oid)) {
                const char *shared_index = git_path("sharedindex.%s",
                                                    oid_to_hex(&si->base_oid));
                freshen_shared_index(shared_index, 1);