ls-files: filter pathspec before lstat
In --deleted and --modified modes, show_files() calls lstat() for each index entry before show_ce() applies the pathspec. prune_index() avoids most of these calls for pathspecs with a common directory prefix, but not for a top-level name or leading wildcard. Match before lstat() to avoid accessing the worktree for entries that cannot be shown. Treat this as a prefilter: do not update ps_matched, and retain the match in show_ce() so --error-unmatch is satisfied only by entries that the selected modes actually show. Prefilter only a single pathspec item, bounding the added work for each index entry. Applying match_pathspec() to multiple arguments can cost more than the lstat() calls it avoids. In a synthetic repository with 10,000 clean files, passing every path to ls-files --modified increased runtime from 112.5 ms to 494.1 ms when the prefilter was unconditional. With $parent and $this exported as paths to binaries built from the parent and this commit, on a repository with 881,290 index entries: hyperfine --warmup 0 --runs 3 \ --command-name parent \ '$parent -c core.fsmonitor=false ls-files --deleted -- README.md >/dev/null' \ --command-name this-commit \ '$this -c core.fsmonitor=false ls-files --deleted -- README.md >/dev/null' reported means of 65.790 seconds for the parent and 4.987 seconds for this commit. Link: https://lore.kernel.org/r/xmqqfr2tnfk0.fsf@gitster.g Helped-by: Jeff King <peff@peff.net> Signed-off-by: Tamir Duberstein <tamird@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>