@@ -308,8 +308,24 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
* continue. A NULL pattern set indicates a full expansion to a
* full index.
*/
- if (pl && !pl->use_cone_patterns)
+ if (pl && !pl->use_cone_patterns) {
pl = NULL;
+ } else {
+ /*
+ * We might contract file entries into sparse-directory
+ * entries, and for that we will need the cache tree to
+ * be recomputed.
+ */
+ cache_tree_free(&istate->cache_tree);
+
+ /*
+ * If there is a problem creating the cache tree, then we
+ * need to expand to a full index since we cannot satisfy
+ * the current request as a sparse index.
+ */
+ if (cache_tree_update(istate, 0))
+ pl = NULL;
+ }
if (!istate->repo)
istate->repo = the_repository;
@@ -327,8 +343,14 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
full = xcalloc(1, sizeof(struct index_state));
memcpy(full, istate, sizeof(struct index_state));
+ /*
+ * This slightly-misnamed 'full' index might still be sparse if we
+ * are only modifying the list of sparse directories. This hinges
+ * on whether we have a non-NULL pattern list.
+ */
+ full->sparse_index = pl ? INDEX_PARTIALLY_SPARSE : INDEX_EXPANDED;
+
/* then change the necessary things */
- full->sparse_index = 0;
full->cache_alloc = (3 * istate->cache_alloc) / 2;
full->cache_nr = 0;
ALLOC_ARRAY(full->cache, full->cache_alloc);
@@ -340,11 +362,22 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
struct cache_entry *ce = istate->cache[i];
struct tree *tree;
struct pathspec ps;
+ int dtype;
if (!S_ISSPARSEDIR(ce->ce_mode)) {
set_index_entry(full, full->cache_nr++, ce);
continue;
}
+
+ /* We now have a sparse directory entry. Should we expand? */
+ if (pl &&
+ path_matches_pattern_list(ce->name, ce->ce_namelen,
+ NULL, &dtype,
+ pl, istate) == NOT_MATCHED) {
+ set_index_entry(full, full->cache_nr++, ce);
+ continue;
+ }
+
if (!(ce->ce_flags & CE_SKIP_WORKTREE))
warning(_("index entry is a directory, but not sparse (%08x)"),
ce->ce_flags);
@@ -370,7 +403,7 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
/* Copy back into original index. */
memcpy(&istate->name_hash, &full->name_hash, sizeof(full->name_hash));
memcpy(&istate->dir_hash, &full->dir_hash, sizeof(full->dir_hash));
- istate->sparse_index = 0;
+ istate->sparse_index = pl ? INDEX_PARTIALLY_SPARSE : INDEX_EXPANDED;
free(istate->cache);
istate->cache = full->cache;
istate->cache_nr = full->cache_nr;