submodule.c: remove implicit dependency on the_index
[gitweb.git] / split-index.c
index 49bd197f715ae783d7fdbe8e1d638a1bcac0073c..84f067e10d2cec1d77ec1a51f0f38cc5a29dd89f 100644 (file)
@@ -18,12 +18,12 @@ int read_link_extension(struct index_state *istate,
        struct split_index *si;
        int ret;
 
-       if (sz < 20)
+       if (sz < the_hash_algo->rawsz)
                return error("corrupt link extension (too short)");
        si = init_split_index(istate);
-       hashcpy(si->base_sha1, data);
-       data += 20;
-       sz -= 20;
+       hashcpy(si->base_oid.hash, data);
+       data += the_hash_algo->rawsz;
+       sz -= the_hash_algo->rawsz;
        if (!sz)
                return 0;
        si->delete_bitmap = ewah_new();
@@ -45,7 +45,7 @@ int write_link_extension(struct strbuf *sb,
                         struct index_state *istate)
 {
        struct split_index *si = istate->split_index;
-       strbuf_add(sb, si->base_sha1, 20);
+       strbuf_add(sb, si->base_oid.hash, the_hash_algo->rawsz);
        if (!si->delete_bitmap && !si->replace_bitmap)
                return 0;
        ewah_serialize_strbuf(si->delete_bitmap, sb);
@@ -73,23 +73,31 @@ void move_cache_to_base_index(struct index_state *istate)
        int i;
 
        /*
-        * If "si" is shared with another index_state (e.g. by
-        * unpack-trees code), we will need to duplicate split_index
-        * struct. It's not happening now though, luckily.
+        * If there was a previous base index, then transfer ownership of allocated
+        * entries to the parent index.
         */
-       assert(si->refcount <= 1);
+       if (si->base &&
+               si->base->ce_mem_pool) {
 
-       unshare_split_index(istate, 0);
-       if (si->base) {
-               discard_index(si->base);
-               free(si->base);
+               if (!istate->ce_mem_pool)
+                       mem_pool_init(&istate->ce_mem_pool, 0);
+
+               mem_pool_combine(istate->ce_mem_pool, istate->split_index->base->ce_mem_pool);
        }
+
        si->base = xcalloc(1, sizeof(*si->base));
        si->base->version = istate->version;
        /* zero timestamp disables racy test in ce_write_index() */
        si->base->timestamp = istate->timestamp;
        ALLOC_GROW(si->base->cache, istate->cache_nr, si->base->cache_alloc);
        si->base->cache_nr = istate->cache_nr;
+
+       /*
+        * The mem_pool needs to move with the allocated entries.
+        */
+       si->base->ce_mem_pool = istate->ce_mem_pool;
+       istate->ce_mem_pool = NULL;
+
        COPY_ARRAY(si->base->cache, istate->cache, istate->cache_nr);
        mark_base_index_entries(si->base);
        for (i = 0; i < si->base->cache_nr; i++)
@@ -130,7 +138,7 @@ static void replace_entry(size_t pos, void *data)
        src->ce_flags |= CE_UPDATE_IN_BASE;
        src->ce_namelen = dst->ce_namelen;
        copy_cache_entry(dst, src);
-       free(src);
+       discard_cache_entry(src);
        si->nr_replacements++;
 }
 
@@ -174,10 +182,9 @@ void merge_base_index(struct index_state *istate)
 
        ewah_free(si->delete_bitmap);
        ewah_free(si->replace_bitmap);
-       free(si->saved_cache);
+       FREE_AND_NULL(si->saved_cache);
        si->delete_bitmap  = NULL;
        si->replace_bitmap = NULL;
-       si->saved_cache    = NULL;
        si->saved_cache_nr = 0;
 }
 
@@ -232,7 +239,7 @@ void prepare_to_write_split_index(struct index_state *istate)
                        base->ce_flags = base_flags;
                        if (ret)
                                ce->ce_flags |= CE_UPDATE_IN_BASE;
-                       free(base);
+                       discard_cache_entry(base);
                        si->base->cache[ce->index - 1] = ce;
                }
                for (i = 0; i < si->base->cache_nr; i++) {
@@ -246,6 +253,8 @@ void prepare_to_write_split_index(struct index_state *istate)
                                ALLOC_GROW(entries, nr_entries+1, nr_alloc);
                                entries[nr_entries++] = ce;
                        }
+                       if (is_null_oid(&ce->oid))
+                               istate->drop_cache_tree = 1;
                }
        }
 
@@ -282,41 +291,11 @@ void finish_writing_split_index(struct index_state *istate)
        istate->cache_nr = si->saved_cache_nr;
 }
 
-void unshare_split_index(struct index_state *istate, int discard)
-{
-       struct split_index *si = istate->split_index;
-       int i;
-
-       if (!si || !si->base)
-               return;
-
-       for (i = 0; i < istate->cache_nr; i++) {
-               struct cache_entry *ce = istate->cache[i];
-               struct cache_entry *new = NULL;
-
-               if (!ce->index ||
-                   ce->index > si->base->cache_nr ||
-                   ce != si->base->cache[ce->index - 1])
-                       continue;
-
-               if (!discard) {
-                       int len = ce_namelen(ce);
-                       new = xcalloc(1, cache_entry_size(len));
-                       copy_cache_entry(new, ce);
-                       memcpy(new->name, ce->name, len);
-                       new->index = 0;
-               }
-               istate->cache[i] = new;
-       }
-}
-
-
 void discard_split_index(struct index_state *istate)
 {
        struct split_index *si = istate->split_index;
        if (!si)
                return;
-       unshare_split_index(istate, 0);
        istate->split_index = NULL;
        si->refcount--;
        if (si->refcount)
@@ -337,21 +316,21 @@ void save_or_free_index_entry(struct index_state *istate, struct cache_entry *ce
            ce == istate->split_index->base->cache[ce->index - 1])
                ce->ce_flags |= CE_REMOVE;
        else
-               free(ce);
+               discard_cache_entry(ce);
 }
 
 void replace_index_entry_in_base(struct index_state *istate,
-                                struct cache_entry *old,
-                                struct cache_entry *new)
+                                struct cache_entry *old_entry,
+                                struct cache_entry *new_entry)
 {
-       if (old->index &&
+       if (old_entry->index &&
            istate->split_index &&
            istate->split_index->base &&
-           old->index <= istate->split_index->base->cache_nr) {
-               new->index = old->index;
-               if (old != istate->split_index->base->cache[new->index - 1])
-                       free(istate->split_index->base->cache[new->index - 1]);
-               istate->split_index->base->cache[new->index - 1] = new;
+           old_entry->index <= istate->split_index->base->cache_nr) {
+               new_entry->index = old_entry->index;
+               if (old_entry != istate->split_index->base->cache[new_entry->index - 1])
+                       discard_cache_entry(istate->split_index->base->cache[new_entry->index - 1]);
+               istate->split_index->base->cache[new_entry->index - 1] = new_entry;
        }
 }
 
@@ -365,8 +344,33 @@ void add_split_index(struct index_state *istate)
 
 void remove_split_index(struct index_state *istate)
 {
-       if (!istate->split_index)
-               return;
-       discard_split_index(istate);
-       istate->cache_changed |= SOMETHING_CHANGED;
+       if (istate->split_index) {
+               /*
+                * When removing the split index, we need to move
+                * ownership of the mem_pool associated with the
+                * base index to the main index. There may be cache entries
+                * allocated from the base's memory pool that are shared with
+                * the_index.cache[].
+                */
+               mem_pool_combine(istate->ce_mem_pool, istate->split_index->base->ce_mem_pool);
+
+               /*
+                * The split index no longer owns the mem_pool backing
+                * its cache array. As we are discarding this index,
+                * mark the index as having no cache entries, so it
+                * will not attempt to clean up the cache entries or
+                * validate them.
+                */
+               if (istate->split_index->base)
+                       istate->split_index->base->cache_nr = 0;
+
+               /*
+                * We can discard the split index because its
+                * memory pool has been incorporated into the
+                * memory pool associated with the the_index.
+                */
+               discard_split_index(istate);
+
+               istate->cache_changed |= SOMETHING_CHANGED;
+       }
 }