sparse-index: complete partial expansion

To complete the implementation of expand_to_pattern_list(), we need to detect when a sparse directory entry should remain sparse. This avoids a full expansion, so we now need to use the PARTIALLY_SPARSE mode to indicate this state. There still are no callers to this method, but we will add one in the next change. Signed-off-by: Derrick Stolee <derrickstolee@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed May 23, 2022 at 13:48 UTC ac8acb4f2c70dd95c582bd5d4fb4f689f82ff3c6
1 file changed +36 -3
sparse-index.c
+36 -3
@@ -308,8 +308,24 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
308 * continue. A NULL pattern set indicates a full expansion to a
309 * full index.
310 */
311 - if (pl && !pl->use_cone_patterns)
311 + if (pl && !pl->use_cone_patterns) {
312 pl = NULL;
313 + } else {
314 + /*
315 + * We might contract file entries into sparse-directory
316 + * entries, and for that we will need the cache tree to
317 + * be recomputed.
318 + */
319 + cache_tree_free(&istate->cache_tree);
320 +
321 + /*
322 + * If there is a problem creating the cache tree, then we
323 + * need to expand to a full index since we cannot satisfy
324 + * the current request as a sparse index.
325 + */
326 + if (cache_tree_update(istate, 0))
327 + pl = NULL;
328 + }
329
330 if (!istate->repo)
331 istate->repo = the_repository;
@@ -327,8 +343,14 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
343 full = xcalloc(1, sizeof(struct index_state));
344 memcpy(full, istate, sizeof(struct index_state));
345
346 + /*
347 + * This slightly-misnamed 'full' index might still be sparse if we
348 + * are only modifying the list of sparse directories. This hinges
349 + * on whether we have a non-NULL pattern list.
350 + */
351 + full->sparse_index = pl ? INDEX_PARTIALLY_SPARSE : INDEX_EXPANDED;
352 +
353 /* then change the necessary things */
331 - full->sparse_index = 0;
354 full->cache_alloc = (3 * istate->cache_alloc) / 2;
355 full->cache_nr = 0;
356 ALLOC_ARRAY(full->cache, full->cache_alloc);
@@ -340,11 +362,22 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
362 struct cache_entry *ce = istate->cache[i];
363 struct tree *tree;
364 struct pathspec ps;
365 + int dtype;
366
367 if (!S_ISSPARSEDIR(ce->ce_mode)) {
368 set_index_entry(full, full->cache_nr++, ce);
369 continue;
370 }
371 +
372 + /* We now have a sparse directory entry. Should we expand? */
373 + if (pl &&
374 + path_matches_pattern_list(ce->name, ce->ce_namelen,
375 + NULL, &dtype,
376 + pl, istate) == NOT_MATCHED) {
377 + set_index_entry(full, full->cache_nr++, ce);
378 + continue;
379 + }
380 +
381 if (!(ce->ce_flags & CE_SKIP_WORKTREE))
382 warning(_("index entry is a directory, but not sparse (%08x)"),
383 ce->ce_flags);
@@ -370,7 +403,7 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
403 /* Copy back into original index. */
404 memcpy(&istate->name_hash, &full->name_hash, sizeof(full->name_hash));
405 memcpy(&istate->dir_hash, &full->dir_hash, sizeof(full->dir_hash));
373 - istate->sparse_index = 0;
406 + istate->sparse_index = pl ? INDEX_PARTIALLY_SPARSE : INDEX_EXPANDED;
407 free(istate->cache);
408 istate->cache = full->cache;
409 istate->cache_nr = full->cache_nr;