diff options
-rw-r--r-- | read-cache.c | 10 | ||||
-rw-r--r-- | split-index.c | 57 | ||||
-rw-r--r-- | split-index.h | 1 |
3 files changed, 21 insertions, 47 deletions
diff --git a/read-cache.c b/read-cache.c index 8da84ae2d1..0d0081a11b 100644 --- a/read-cache.c +++ b/read-cache.c @@ -1877,9 +1877,15 @@ int discard_index(struct index_state *istate) { int i; - unshare_split_index(istate, 1); - for (i = 0; i < istate->cache_nr; i++) + for (i = 0; i < istate->cache_nr; i++) { + if (istate->cache[i]->index && + istate->split_index && + istate->split_index->base && + istate->cache[i]->index <= istate->split_index->base->cache_nr && + istate->cache[i] == istate->split_index->base->cache[istate->cache[i]->index - 1]) + continue; free(istate->cache[i]); + } resolve_undo_clear_index(istate); istate->cache_nr = 0; istate->cache_changed = 0; diff --git a/split-index.c b/split-index.c index 49bd197f71..f519e60f87 100644 --- a/split-index.c +++ b/split-index.c @@ -73,17 +73,10 @@ 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. + * do not delete old si->base, its index entries may be shared + * with istate->cache[]. Accept a bit of leaking here because + * this code is only used by short-lived update-index. */ - assert(si->refcount <= 1); - - unshare_split_index(istate, 0); - if (si->base) { - discard_index(si->base); - free(si->base); - } si->base = xcalloc(1, sizeof(*si->base)); si->base->version = istate->version; /* zero timestamp disables racy test in ce_write_index() */ @@ -282,41 +275,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) @@ -365,8 +328,14 @@ 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) { + /* + * can't discard_split_index(&the_index); because that + * will destroy split_index->base->cache[], which may + * be shared with the_index.cache[]. So yeah we're + * leaking a bit here. + */ + istate->split_index = NULL; + istate->cache_changed |= SOMETHING_CHANGED; + } } diff --git a/split-index.h b/split-index.h index 65c0f09b2b..df91c1bda8 100644 --- a/split-index.h +++ b/split-index.h @@ -33,6 +33,5 @@ void finish_writing_split_index(struct index_state *istate); void discard_split_index(struct index_state *istate); void add_split_index(struct index_state *istate); void remove_split_index(struct index_state *istate); -void unshare_split_index(struct index_state *istate, int discard); #endif |