18def enumerate_repository_files(repo_root: Path, suffix: str =
"",
19 skip_dirs: frozenset = frozenset()) -> list:
21 @brief List tracked plus non-ignored untracked files that exist on disk.
23 @details Paths the index tracks but the worktree no longer holds are filtered out:
24 a deletion staged or unstaged is still a deletion, and reading it would
25 raise rather than report a finding.
26 @param[in] repo_root Repository root directory.
27 @param[in] suffix Restrict to paths with this suffix, or empty for all files.
28 @param[in] skip_dirs Path components whose presence excludes a file.
29 @return Sorted existing paths, or None when git enumeration is unavailable.
32 for args
in ([
"ls-files",
"-z"], [
"ls-files",
"-z",
"--others",
"--exclude-standard"]):
33 result = subprocess.run(
34 [
"git",
"-C", str(repo_root), *args], capture_output=
True, text=
True, check=
False
36 if result.returncode != 0:
39 entry
for entry
in result.stdout.split(
"\0")
40 if entry
and (
not suffix
or entry.endswith(suffix))
43 repo_root / entry
for entry
in entries
44 if not skip_dirs.intersection(Path(entry).parts)
45 and (repo_root / entry).is_file()