perf: classify large bulk discard paths safely (#3743)

This commit is contained in:
Neil
2026-05-30 08:33:10 -07:00
committed by GitHub
parent f933c396c5
commit b0435c1ac5
2 changed files with 27 additions and 1 deletions
+20
View File
@@ -210,6 +210,26 @@ describe('bulk git helpers', () => {
expect(rmMock).not.toHaveBeenCalled()
})
it('handles large tracked path lists during bulk discard classification', async () => {
const trackedStdout = Array.from({ length: 150_000 }, (_, index) => `docs/file-${index}.ts`)
.join('\0')
.concat('\0')
gitExecFileAsyncMock.mockResolvedValueOnce({ stdout: trackedStdout }).mockResolvedValueOnce({
stdout: ''
})
await bulkDiscardChanges('/repo', ['docs'])
expect(gitExecFileAsyncMock).toHaveBeenNthCalledWith(
2,
['restore', '--worktree', '--source=HEAD', '--', ':(literal)docs'],
{
cwd: '/repo'
}
)
expect(rmMock).not.toHaveBeenCalled()
})
it('rejects bulk discard paths that traverse outside the worktree', async () => {
await expect(bulkDiscardChanges('/repo', ['src/file.ts', '../outside.txt'])).rejects.toThrow(
'resolves outside the worktree'
+7 -1
View File
@@ -1158,7 +1158,13 @@ async function listTrackedPathSpecs(
cwd: worktreePath
}
)
trackedPaths.push(...stdout.split('\0').filter(Boolean))
// Why: a tracked directory can contain enough paths for push(...split)
// to exceed the JavaScript argument limit before discard decisions run.
for (const trackedPath of stdout.split('\0')) {
if (trackedPath) {
trackedPaths.push(trackedPath)
}
}
}
return trackedPaths
}