fix: handle large worktree auth caches

This commit is contained in:
Neil
2026-05-30 05:51:22 -07:00
parent dcd087ba1e
commit 4b3b85b2ed
2 changed files with 54 additions and 1 deletions
+49
View File
@@ -0,0 +1,49 @@
import { resolve } from 'node:path'
import { afterEach, describe, expect, it, vi } from 'vitest'
import type { Store } from '../persistence'
import { listRepoWorktrees } from '../repo-worktrees'
import {
invalidateAuthorizedRootsCache,
rebuildAuthorizedRootsCache,
resolveRegisteredWorktreePath
} from './filesystem-auth'
vi.mock('../repo-worktrees', () => ({
isRepoRoot: vi.fn(() => false),
listRepoWorktrees: vi.fn()
}))
const listRepoWorktreesMock = vi.mocked(listRepoWorktrees)
function createStore(repoPath: string): Store {
return {
getRepos: () => [{ id: 'repo-1', path: repoPath }],
getSettings: () => ({ workspaceDir: '' })
} as unknown as Store
}
afterEach(() => {
invalidateAuthorizedRootsCache()
listRepoWorktreesMock.mockReset()
vi.restoreAllMocks()
})
describe('filesystem auth registered worktree roots', () => {
it('registers very large worktree lists during cache rebuild', async () => {
const repoPath = '/repo/main'
const targetWorktreePath = '/linked-worktrees/worktree-129999'
const worktrees = Array.from({ length: 130_000 }, (_, index) => ({
path: `/linked-worktrees/worktree-${index}`
}))
listRepoWorktreesMock.mockResolvedValue(
worktrees as Awaited<ReturnType<typeof listRepoWorktrees>>
)
vi.spyOn(console, 'warn').mockImplementation(() => {})
await rebuildAuthorizedRootsCache(createStore(repoPath))
await expect(
resolveRegisteredWorktreePath(targetWorktreePath, createStore(repoPath))
).resolves.toBe(resolve(targetWorktreePath))
})
})
+5 -1
View File
@@ -1,3 +1,5 @@
/* eslint-disable max-lines -- Why: filesystem authorization shares module-local
* root caches with the path validation entrypoints that consume them. */
import { resolve, relative, dirname, basename, isAbsolute } from 'path'
import { realpathSync } from 'fs'
import { realpath } from 'fs/promises'
@@ -102,7 +104,9 @@ export async function rebuildAuthorizedRootsCache(store: Store): Promise<void> {
const worktrees = await listRepoWorktrees(repo)
const worktreeRoots = worktrees.map((wt) => resolve(wt.path))
roots.push(...worktreeRoots)
for (const worktreeRoot of worktreeRoots) {
roots.push(worktreeRoot)
}
} catch (error) {
// Why: a single inaccessible repo (EACCES, EIO, etc.) must not break
// the entire cache rebuild — that would disable File Explorer and