MCPcopy
hub / github.com/claude-code-best/claude-code / fetchGitDiff

Function fetchGitDiff

src/utils/gitDiff.ts:49–108  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

47 * made by the user.
48 */
49export async function fetchGitDiff(): Promise<GitDiffResult | null> {
50 const isGit = await getIsGit()
51 if (!isGit) return null
52
53 // Skip diff calculation during transient git states since the
54 // working tree contains incoming changes, not user-intentional edits
55 if (await isInTransientGitState()) {
56 return null
57 }
58
59 // Quick probe: use --shortstat to get totals without loading all content.
60 // This is O(1) memory and lets us detect massive diffs (e.g., jj workspaces)
61 // before committing to expensive operations.
62 const { stdout: shortstatOut, code: shortstatCode } = await execFileNoThrow(
63 gitExe(),
64 ['--no-optional-locks', 'diff', 'HEAD', '--shortstat'],
65 { timeout: GIT_TIMEOUT_MS, preserveOutputOnError: false },
66 )
67
68 if (shortstatCode === 0) {
69 const quickStats = parseShortstat(shortstatOut)
70 if (quickStats && quickStats.filesCount > MAX_FILES_FOR_DETAILS) {
71 // Too many files - return accurate totals but skip per-file details
72 // to avoid loading hundreds of MB into memory
73 return {
74 stats: quickStats,
75 perFileStats: new Map(),
76 hunks: new Map(),
77 }
78 }
79 }
80
81 // Get stats via --numstat (all uncommitted changes vs HEAD)
82 const { stdout: numstatOut, code: numstatCode } = await execFileNoThrow(
83 gitExe(),
84 ['--no-optional-locks', 'diff', 'HEAD', '--numstat'],
85 { timeout: GIT_TIMEOUT_MS, preserveOutputOnError: false },
86 )
87
88 if (numstatCode !== 0) return null
89
90 const { stats, perFileStats } = parseGitNumstat(numstatOut)
91
92 // Include untracked files (new files not yet staged)
93 // Just filenames - no content reading for performance
94 const remainingSlots = MAX_FILES - perFileStats.size
95 if (remainingSlots > 0) {
96 const untrackedStats = await fetchUntrackedFiles(remainingSlots)
97 if (untrackedStats) {
98 stats.filesCount += untrackedStats.size
99 for (const [path, fileStats] of untrackedStats) {
100 perFileStats.set(path, fileStats)
101 }
102 }
103 }
104
105 // Return stats only - hunks are fetched on-demand via fetchGitDiffHunks()
106 // to avoid expensive git diff HEAD call on every poll

Callers 1

loadDiffDataFunction · 0.85

Calls 6

isInTransientGitStateFunction · 0.85
parseShortstatFunction · 0.85
parseGitNumstatFunction · 0.85
fetchUntrackedFilesFunction · 0.85
setMethod · 0.80
execFileNoThrowFunction · 0.70

Tested by

no test coverage detected