Skip to content

Commit 681f26b

Browse files
derrickstoleegitster
authored andcommitted
ls-files: conditionally leave index sparse
When running 'git ls-files' with a pathspec, the index entries get filtered according to that pathspec before iterating over them in show_files(). In 7808709 (ls-files: add --sparse option, 2021-12-22), this iteration was prefixed with a check for the '--sparse' option which allows the command to output directory entries; this created a pre-loop call to ensure_full_index(). However, when a user runs 'git ls-files' where the pathspec matches directories that are recursively matched in the sparse-checkout, there are not any sparse directories that match the pathspec so they would not be written to the output. The expansion in this case is just a performance drop for no behavior difference. Replace this global check to expand the index with a check inside the loop for a matched sparse directory. If we see one, then expand the index and continue from the current location. This is safe since the previous entries in the index did not have any sparse directories and thus would remain stable in this expansion. A test in t1092 confirms that this changes the behavior. Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f368df4 commit 681f26b

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

builtin/ls-files.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,14 +413,21 @@ static void show_files(struct repository *repo, struct dir_struct *dir)
413413
if (!(show_cached || show_stage || show_deleted || show_modified))
414414
return;
415415

416-
if (!show_sparse_dirs)
417-
ensure_full_index(repo->index);
418-
419416
for (i = 0; i < repo->index->cache_nr; i++) {
420417
const struct cache_entry *ce = repo->index->cache[i];
421418
struct stat st;
422419
int stat_err;
423420

421+
if (S_ISSPARSEDIR(ce->ce_mode) && !show_sparse_dirs) {
422+
/*
423+
* This is the first time we've hit a sparse dir,
424+
* so expansion will leave the first 'i' entries
425+
* alone.
426+
*/
427+
ensure_full_index(repo->index);
428+
ce = repo->index->cache[i];
429+
}
430+
424431
construct_fullname(&fullname, repo, ce);
425432

426433
if ((dir->flags & DIR_SHOW_IGNORED) &&

t/t1092-sparse-checkout-compatibility.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,8 @@ test_expect_success 'sparse-index is not expanded' '
15061506
ensure_not_expanded reset --hard &&
15071507
ensure_not_expanded restore -s rename-out-to-out -- deep/deeper1 &&
15081508
1509+
ensure_not_expanded ls-files deep/deeper1 &&
1510+
15091511
echo >>sparse-index/README.md &&
15101512
ensure_not_expanded add -A &&
15111513
echo >>sparse-index/extra.txt &&
@@ -1607,6 +1609,17 @@ test_expect_success 'describe tested on all' '
16071609
test_all_match git describe --dirty
16081610
'
16091611

1612+
test_expect_success 'ls-files filtering and expansion' '
1613+
init_repos &&
1614+
1615+
# This filtering will hit a sparse directory midway
1616+
# through the iteration.
1617+
test_all_match git ls-files deep &&
1618+
1619+
# This pathspec will filter the index to only a sparse
1620+
# directory.
1621+
test_all_match git ls-files folder1
1622+
'
16101623

16111624
test_expect_success 'sparse-index is not expanded: describe' '
16121625
init_repos &&

0 commit comments

Comments
 (0)