From 364af8b4e4091d265942a64865adeb19cff97874 Mon Sep 17 00:00:00 2001 From: Caio Gallo Date: Mon, 30 Mar 2026 09:11:34 -0300 Subject: [PATCH 1/2] fix(git): prevent app freeze on repos with large untracked directories --- packages/git/src/queries.ts | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/git/src/queries.ts b/packages/git/src/queries.ts index 4fc901a04..2e52db47c 100644 --- a/packages/git/src/queries.ts +++ b/packages/git/src/queries.ts @@ -143,7 +143,7 @@ export async function getStatus( return manager.executeRead( baseDir, async (git) => { - const status = await git.status(); + const status = await git.status(["--untracked-files=normal"]); return { isClean: status.isClean(), staged: status.staged, @@ -164,7 +164,7 @@ export async function hasChanges( return manager.executeRead( baseDir, async (git) => { - const status = await git.status(); + const status = await git.status(["--untracked-files=normal"]); return !status.isClean(); }, { signal: options?.abortSignal }, @@ -189,7 +189,7 @@ export async function getAheadBehind( return null; } - const status = await git.status(); + const status = await git.status(["--untracked-files=no"]); return { aheadOfRemote: status.ahead, behind: status.behind, @@ -339,7 +339,7 @@ export async function getChangedFiles( } catch {} } - const status = await git.status(); + const status = await git.status(["--untracked-files=normal"]); for (const file of [ ...status.modified, ...status.created, @@ -430,7 +430,7 @@ export async function getChangedFilesDetailed( try { const [diffSummary, status] = await Promise.all([ git.diffSummary(["-M", "HEAD"]), - git.status(), + git.status(["--untracked-files=normal"]), ]); const seenPaths = new Set(); @@ -468,6 +468,8 @@ export async function getChangedFilesDetailed( if (hasFrom) seenPaths.add(file.from as string); } + const MAX_UNTRACKED_LINE_COUNT = 10_000; + let untrackedProcessed = 0; for (const file of status.not_added) { if (!seenPaths.has(file)) { if ( @@ -476,13 +478,17 @@ export async function getChangedFilesDetailed( ) { continue; } - const lineCount = await countFileLines(path.join(baseDir, file)); + const lineCount = + untrackedProcessed < MAX_UNTRACKED_LINE_COUNT + ? await countFileLines(path.join(baseDir, file)) + : 0; files.push({ path: file, status: "untracked", linesAdded: lineCount, linesRemoved: 0, }); + untrackedProcessed++; } } @@ -664,7 +670,7 @@ export async function getSyncStatus( baseDir, async (git) => { try { - const status = await git.status(); + const status = await git.status(["--untracked-files=no"]); const isDetached = status.detached || status.current === "HEAD"; const currentBranch = isDetached ? null : status.current || null; From ec50cb877bcbf13763df68569cbf213b99598d10 Mon Sep 17 00:00:00 2001 From: Caio Gallo Date: Mon, 30 Mar 2026 10:21:44 -0300 Subject: [PATCH 2/2] fix(git): rename MAX_UNTRACKED_LINE_COUNT to MAX_UNTRACKED_FILES --- packages/git/src/queries.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/git/src/queries.ts b/packages/git/src/queries.ts index 2e52db47c..032180ed6 100644 --- a/packages/git/src/queries.ts +++ b/packages/git/src/queries.ts @@ -468,9 +468,10 @@ export async function getChangedFilesDetailed( if (hasFrom) seenPaths.add(file.from as string); } - const MAX_UNTRACKED_LINE_COUNT = 10_000; + const MAX_UNTRACKED_FILES = 10_000; let untrackedProcessed = 0; for (const file of status.not_added) { + if (untrackedProcessed >= MAX_UNTRACKED_FILES) break; if (!seenPaths.has(file)) { if ( excludePatterns && @@ -478,10 +479,7 @@ export async function getChangedFilesDetailed( ) { continue; } - const lineCount = - untrackedProcessed < MAX_UNTRACKED_LINE_COUNT - ? await countFileLines(path.join(baseDir, file)) - : 0; + const lineCount = await countFileLines(path.join(baseDir, file)); files.push({ path: file, status: "untracked",