MCPcopy
hub / github.com/codeaashu/claude-code / getFilesUsingGit

Function getFilesUsingGit

src/hooks/fileSuggestions.ts:248–383  ·  view source on GitHub ↗

* Get files using git ls-files (much faster than ripgrep for git repos) * Returns tracked files immediately, fetches untracked in background * @param respectGitignore If true, excludes gitignored files from untracked results * * Note: Unlike ripgrep --follow, git ls-files doesn't follow symlinks

(
  abortSignal: AbortSignal,
  respectGitignore: boolean,
)

Source from the content-addressed store, hash-verified

246 * This is intentional as git tracks symlinks as symlinks.
247 */
248async function getFilesUsingGit(
249 abortSignal: AbortSignal,
250 respectGitignore: boolean,
251): Promise<string[] | null> {
252 const startTime = Date.now()
253 logForDebugging(`[FileIndex] getFilesUsingGit called`)
254
255 // Check if we're in a git repo. findGitRoot is LRU-memoized per path.
256 const repoRoot = findGitRoot(getCwd())
257 if (!repoRoot) {
258 logForDebugging(`[FileIndex] not a git repo, returning null`)
259 return null
260 }
261
262 try {
263 const cwd = getCwd()
264
265 // Get tracked files (fast - reads from git index)
266 // Run from repoRoot so paths are relative to repo root, not CWD
267 const lsFilesStart = Date.now()
268 const trackedResult = await execFileNoThrowWithCwd(
269 gitExe(),
270 ['-c', 'core.quotepath=false', 'ls-files', '--recurse-submodules'],
271 { timeout: 5000, abortSignal, cwd: repoRoot },
272 )
273 logForDebugging(
274 `[FileIndex] git ls-files (tracked) took ${Date.now() - lsFilesStart}ms`,
275 )
276
277 if (trackedResult.code !== 0) {
278 logForDebugging(
279 `[FileIndex] git ls-files failed (code=${trackedResult.code}, stderr=${trackedResult.stderr}), falling back to ripgrep`,
280 )
281 return null
282 }
283
284 const trackedFiles = trackedResult.stdout.trim().split('\n').filter(Boolean)
285
286 // Normalize paths relative to the current working directory
287 let normalizedTracked = normalizeGitPaths(trackedFiles, repoRoot, cwd)
288
289 // Apply .ignore/.rgignore patterns if present (faster than falling back to ripgrep)
290 const ignorePatterns = await loadRipgrepIgnorePatterns(repoRoot, cwd)
291 if (ignorePatterns) {
292 const beforeCount = normalizedTracked.length
293 normalizedTracked = ignorePatterns.filter(normalizedTracked)
294 logForDebugging(
295 `[FileIndex] applied ignore patterns: ${beforeCount} -> ${normalizedTracked.length} files`,
296 )
297 }
298
299 // Cache tracked files for later merge with untracked
300 cachedTrackedFiles = normalizedTracked
301
302 const duration = Date.now() - startTime
303 logForDebugging(
304 `[FileIndex] git ls-files: ${normalizedTracked.length} tracked files in ${duration}ms`,
305 )

Callers 1

getProjectFilesFunction · 0.85

Calls 8

logForDebuggingFunction · 0.85
getCwdFunction · 0.85
execFileNoThrowWithCwdFunction · 0.85
normalizeGitPathsFunction · 0.85
logEventFunction · 0.85
errorMessageFunction · 0.50

Tested by

no test coverage detected