refactor(main): import filesystem-auth, markdown-documents and preflight seams from their defining modules (#30440)

The three ipc modules re-exported symbols owned elsewhere. Importers and test mocks now name the
defining module, and the re-export lines are gone (no barrels).
This commit is contained in:
Neil
2026-10-18 15:41:29 -07:00
committed by GitHub
parent 687328ae41
commit 7a9170cf77
35 changed files with 68 additions and 65 deletions
+4 -1
View File
@@ -21,7 +21,10 @@ import {
trustFloatingWorkspaceDirectory,
resolveFloatingTerminalCwd
} from './floating-workspace-directory'
import { isMarkdownDocumentName, markdownDocumentFromFilePath } from './markdown-documents'
import {
isMarkdownDocumentName,
markdownDocumentFromFilePath
} from '../../shared/markdown-document-paths'
import { registerMacSymbolicHotkeysProbeHandler } from './macos-symbolic-hotkeys-probe'
import { registerRendererShutdownCheckpointHandler } from './renderer-shutdown-checkpoint'
import { readMacKeyboardLayoutSnapshot } from './macos-keyboard-layout-snapshot'
+1 -1
View File
@@ -7,7 +7,7 @@ import {
type BitbucketConnectResult,
type BitbucketConnectionStatus
} from '../bitbucket/credential-connection'
import { _resetPreflightCache } from './preflight'
import { _resetPreflightCache } from '../preflight/agent-detection'
function optionalString(value: unknown): string | null {
return typeof value === 'string' ? value : null
-6
View File
@@ -10,12 +10,6 @@ import {
isRegisteredWorktreePath
} from './registered-worktree-roots-cache'
// Compatibility exports for runtime command modules that historically imported these seams from
// filesystem-auth. The implementations remain owned by their focused modules.
export { invalidateAuthorizedRootsCache } from './registered-worktree-roots-cache'
export { invalidateAuthorizedRootsCacheForRepo } from './registered-worktree-roots-scoped-invalidation'
export { isENOENT } from './filesystem-path-containment'
export const PATH_ACCESS_DENIED_MESSAGE = `${PATH_OUTSIDE_ALLOWED_DIRECTORIES}. If this blocks a legitimate workflow, please file a GitHub issue.`
/** One allowed-root list shared by every check in a single authorization, built on first use. */
type AllowedRootsSnapshot = { get: () => readonly string[] }
@@ -80,8 +80,7 @@ vi.mock('./local-worktree-runtime-options', () => ({
}))
vi.mock('./markdown-documents', () => ({
listMarkdownDocuments: vi.fn(),
markdownDocumentsFromRelativePaths: vi.fn()
listMarkdownDocuments: vi.fn()
}))
import { registerFilesystemHandlers } from './filesystem'
@@ -74,8 +74,7 @@ vi.mock('./local-worktree-runtime-options', () => ({
}))
vi.mock('./markdown-documents', () => ({
listMarkdownDocuments: vi.fn(),
markdownDocumentsFromRelativePaths: vi.fn()
listMarkdownDocuments: vi.fn()
}))
import { registerFilesystemHandlers } from './filesystem'
@@ -9,7 +9,7 @@ const mocks = vi.hoisted(() => ({
listFavouriteFilters: vi.fn()
}))
vi.mock('electron', () => ({ ipcMain: { handle: mocks.handle } }))
vi.mock('./preflight', () => ({ _resetPreflightCache: vi.fn() }))
vi.mock('../preflight/agent-detection', () => ({ _resetPreflightCache: vi.fn() }))
vi.mock('../jira/favourite-filters', () => ({ listFavouriteFilters: mocks.listFavouriteFilters }))
vi.mock('../jira/client', () => ({
connect: vi.fn(),
+1 -1
View File
@@ -4,7 +4,7 @@ import { ipcMain } from 'electron'
import type { JiraMediaFormat } from '../../shared/jira-attachment-image'
import { connect, disconnect, getStatus, selectSite, testConnection } from '../jira/client'
import { listFavouriteFilters } from '../jira/favourite-filters'
import { _resetPreflightCache } from './preflight'
import { _resetPreflightCache } from '../preflight/agent-detection'
import { JiraCancellableRequests } from './jira-cancellable-requests'
import { registerJiraUserSearchHandlers } from './jira-user-search'
import { registerJiraProjectMetadataHandlers } from './jira-project-metadata'
+1 -1
View File
@@ -69,7 +69,7 @@ vi.mock('../linear/teams', () => ({
getTeamMembers: vi.fn()
}))
vi.mock('./preflight', () => ({
vi.mock('../preflight/agent-detection', () => ({
_resetPreflightCache: vi.fn()
}))
+1 -1
View File
@@ -1,6 +1,6 @@
import { ipcMain } from 'electron'
import { connect, disconnect, getStatus, selectWorkspace, testConnection } from '../linear/client'
import { _resetPreflightCache } from './preflight'
import { _resetPreflightCache } from '../preflight/agent-detection'
import { normalizeWorkspaceId, normalizeWorkspaceSelection } from './linear-ipc-args'
import { registerLinearIssueHandlers } from './linear-issue-handlers'
import { registerLinearProjectHandlers } from './linear-project-handlers'
@@ -6,7 +6,10 @@ vi.mock('node:path', async (importOriginal) => {
return { ...actual, extname: actual.win32.extname }
})
import { isMarkdownDocumentName, markdownDocumentFromRelativePath } from './markdown-documents'
import {
isMarkdownDocumentName,
markdownDocumentFromRelativePath
} from '../../shared/markdown-document-paths'
describe('remote Markdown filenames on a Windows client', () => {
it('keeps the local filename helper on Windows semantics', () => {
+1 -1
View File
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest'
import {
markdownDocumentFromFilePath,
markdownDocumentFromRelativePath
} from './markdown-documents'
} from '../../shared/markdown-document-paths'
describe('markdownDocumentFromFilePath', () => {
it.skipIf(process.platform === 'win32')('preserves local literal backslash names', () => {
-1
View File
@@ -6,7 +6,6 @@ import {
MARKDOWN_DOCUMENT_LISTING_ARGS
} from '../../shared/node-markdown-document-listing'
import type { MarkdownDocument } from '../../shared/filesystem-entry-types'
export * from '../../shared/markdown-document-paths'
export async function listMarkdownDocuments(
rootPath: string,
@@ -63,7 +63,7 @@ vi.mock('../pty/windows-environment-path', () => ({
mergePersistedWindowsPath: mergePersistedWindowsPathMock
}))
import { _resetPreflightCache, detectInstalledAgents } from './preflight'
import { _resetPreflightCache, detectInstalledAgents } from '../preflight/agent-detection'
import {
getTuiAgentDetectionProbeCommands,
KNOWN_TUI_AGENT_DETECTION_COMMANDS
@@ -89,9 +89,9 @@ vi.mock('../gitea/client', () => ({
import {
detectInstalledAgents,
detectInstalledAgentsWithShellPathHydration,
registerPreflightHandlers
} from './preflight'
detectInstalledAgentsWithShellPathHydration
} from '../preflight/agent-detection'
import { registerPreflightHandlers } from './preflight'
import { resetPreflightMocks, type HandlerMap } from './preflight-test-harness'
describe('preflight', () => {
@@ -101,7 +101,8 @@ vi.mock('../gitea/client', () => ({
getGiteaAuthStatus: getGiteaAuthStatusMock
}))
import { _resetPreflightCache, registerPreflightHandlers, runPreflightCheck } from './preflight'
import { _resetPreflightCache, runPreflightCheck } from '../preflight/agent-detection'
import { registerPreflightHandlers } from './preflight'
import {
defaultAzureDevOpsStatus,
defaultBitbucketStatus,
+1 -1
View File
@@ -1,6 +1,6 @@
import path from 'node:path'
import type { Mock } from 'vitest'
import { _resetPreflightCache } from './preflight'
import { _resetPreflightCache } from '../preflight/agent-detection'
export type HandlerMap = Record<string, (_event?: unknown, args?: unknown) => Promise<unknown>>
-4
View File
@@ -10,10 +10,6 @@ import type {
RemoteWindowsTerminalCapabilities
} from '../preflight/agent-detection'
// Why this file is thin: everything above the handler layer moved to
// ../preflight/agent-detection so the runtime can call it without ipcMain.
// Re-exported here so existing importers of `ipc/preflight` keep working.
export * from '../preflight/agent-detection'
import { readZCodeInteractiveCapability } from '../zcode/interactive-capability'
export function registerPreflightHandlers(): void {
@@ -1,5 +1,5 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import * as filesystemAuth from './filesystem-auth'
import * as scopedRootsInvalidation from './registered-worktree-roots-scoped-invalidation'
import * as authorizedRootsCache from './registered-worktree-roots-cache'
import * as localWorktreeFilesystem from '../local-worktree-filesystem'
import { lstat, mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'
@@ -126,7 +126,7 @@ describe('registerWorktreeHandlers', () => {
beforeEach(() => {
runtimeStub = setupWorktreeHandlers()
vi.spyOn(filesystemAuth, 'invalidateAuthorizedRootsCacheForRepo').mockClear()
vi.spyOn(scopedRootsInvalidation, 'invalidateAuthorizedRootsCacheForRepo').mockClear()
vi.spyOn(authorizedRootsCache, 'invalidateAuthorizedRootsCache').mockClear()
})
@@ -160,8 +160,8 @@ describe('registerWorktreeHandlers', () => {
true
)
expect(filesystemAuth.invalidateAuthorizedRootsCacheForRepo).toHaveBeenCalledOnce()
expect(filesystemAuth.invalidateAuthorizedRootsCacheForRepo).toHaveBeenCalledWith(
expect(scopedRootsInvalidation.invalidateAuthorizedRootsCacheForRepo).toHaveBeenCalledOnce()
expect(scopedRootsInvalidation.invalidateAuthorizedRootsCacheForRepo).toHaveBeenCalledWith(
store,
'repo-1'
)
@@ -188,8 +188,8 @@ describe('registerWorktreeHandlers', () => {
await handlers['worktrees:remove'](null, { worktreeId: 'repo-1::/workspace/feature-wt' })
expect(filesystemAuth.invalidateAuthorizedRootsCacheForRepo).toHaveBeenCalledOnce()
expect(filesystemAuth.invalidateAuthorizedRootsCacheForRepo).toHaveBeenCalledWith(
expect(scopedRootsInvalidation.invalidateAuthorizedRootsCacheForRepo).toHaveBeenCalledOnce()
expect(scopedRootsInvalidation.invalidateAuthorizedRootsCacheForRepo).toHaveBeenCalledWith(
store,
'repo-1'
)
@@ -344,8 +344,8 @@ describe('registerWorktreeHandlers', () => {
worktreeId: 'repo-1::/workspace/feature-wt'
})
expect(filesystemAuth.invalidateAuthorizedRootsCacheForRepo).toHaveBeenCalledOnce()
expect(filesystemAuth.invalidateAuthorizedRootsCacheForRepo).toHaveBeenCalledWith(
expect(scopedRootsInvalidation.invalidateAuthorizedRootsCacheForRepo).toHaveBeenCalledOnce()
expect(scopedRootsInvalidation.invalidateAuthorizedRootsCacheForRepo).toHaveBeenCalledWith(
store,
'repo-1'
)
@@ -1,5 +1,5 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import * as filesystemAuth from './filesystem-auth'
import * as scopedRootsInvalidation from './registered-worktree-roots-scoped-invalidation'
import * as authorizedRootsCache from './registered-worktree-roots-cache'
import {
removeWorktreeLinkedPathsMock,
@@ -101,7 +101,7 @@ describe('registerWorktreeHandlers', () => {
beforeEach(() => {
runtimeStub = setupWorktreeHandlers()
vi.spyOn(filesystemAuth, 'invalidateAuthorizedRootsCacheForRepo').mockClear()
vi.spyOn(scopedRootsInvalidation, 'invalidateAuthorizedRootsCacheForRepo').mockClear()
vi.spyOn(authorizedRootsCache, 'invalidateAuthorizedRootsCache').mockClear()
})
@@ -138,7 +138,7 @@ describe('registerWorktreeHandlers', () => {
expect(removeWorktreeLinkedPathsMock).not.toHaveBeenCalled()
expect(killAllProcessesForWorktreeMock).not.toHaveBeenCalled()
expect(removeWorktreeMock).not.toHaveBeenCalled()
expect(filesystemAuth.invalidateAuthorizedRootsCacheForRepo).not.toHaveBeenCalled()
expect(scopedRootsInvalidation.invalidateAuthorizedRootsCacheForRepo).not.toHaveBeenCalled()
expect(authorizedRootsCache.invalidateAuthorizedRootsCache).not.toHaveBeenCalled()
})
@@ -201,7 +201,7 @@ describe('registerWorktreeHandlers', () => {
expect(removeWorktreeLinkedPathsMock).not.toHaveBeenCalled()
expect(killAllProcessesForWorktreeMock).not.toHaveBeenCalled()
expect(removeWorktreeMock).not.toHaveBeenCalled()
expect(filesystemAuth.invalidateAuthorizedRootsCacheForRepo).not.toHaveBeenCalled()
expect(scopedRootsInvalidation.invalidateAuthorizedRootsCacheForRepo).not.toHaveBeenCalled()
expect(authorizedRootsCache.invalidateAuthorizedRootsCache).not.toHaveBeenCalled()
})
@@ -22,7 +22,7 @@ import {
findExistingWorktreeSymlinkPaths,
removeWorktreeLinkedPaths
} from '../../worktree-symlinks'
import { invalidateAuthorizedRootsCacheForRepo } from '../../filesystem-auth'
import { invalidateAuthorizedRootsCacheForRepo } from '../../registered-worktree-roots-scoped-invalidation'
import { runWorktreeChangeInvalidators } from '../../worktree-change-invalidators'
import {
formatWorktreeRemovalError,
@@ -37,8 +37,10 @@ vi.mock('./runtime-local-worktree-setup', () => ({
didStartInProcessSetupHook: false
}))
}))
vi.mock('../ipc/filesystem-auth', () => ({
invalidateAuthorizedRootsCache: vi.fn(),
vi.mock('../ipc/registered-worktree-roots-cache', () => ({
invalidateAuthorizedRootsCache: vi.fn()
}))
vi.mock('../ipc/registered-worktree-roots-scoped-invalidation', () => ({
invalidateAuthorizedRootsCacheForRepo: vi.fn()
}))
@@ -36,8 +36,10 @@ vi.mock('./runtime-local-worktree-setup', () => ({
didStartInProcessSetupHook: false
}))
}))
vi.mock('../ipc/filesystem-auth', () => ({
invalidateAuthorizedRootsCache: vi.fn(),
vi.mock('../ipc/registered-worktree-roots-cache', () => ({
invalidateAuthorizedRootsCache: vi.fn()
}))
vi.mock('../ipc/registered-worktree-roots-scoped-invalidation', () => ({
invalidateAuthorizedRootsCacheForRepo: vi.fn()
}))
@@ -359,15 +359,14 @@ vi.mock('../../ipc/worktree-logic', async (importOriginal) => {
})
vi.mock('../../ipc/filesystem-auth', () => ({
resolveAuthorizedPath: vi.fn(async (pathValue: string) => pathValue),
invalidateAuthorizedRootsCache: invalidateAuthorizedRootsCacheMock,
invalidateAuthorizedRootsCacheForRepo: invalidateAuthorizedRootsCacheMock,
isENOENT: (error: unknown) =>
Boolean(error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT')
resolveAuthorizedPath: vi.fn(async (pathValue: string) => pathValue)
}))
vi.mock('../../ipc/registered-worktree-roots-cache', () => ({
invalidateAuthorizedRootsCache: invalidateAuthorizedRootsCacheMock,
invalidateAuthorizedRootsCache: invalidateAuthorizedRootsCacheMock
}))
vi.mock('../../ipc/registered-worktree-roots-scoped-invalidation', () => ({
invalidateAuthorizedRootsCacheForRepo: invalidateAuthorizedRootsCacheMock
}))
@@ -33,8 +33,10 @@ vi.mock('./runtime-local-worktree-setup', () => ({
}))
}))
vi.mock('../ipc/filesystem-auth', () => ({
invalidateAuthorizedRootsCache: vi.fn(),
vi.mock('../ipc/registered-worktree-roots-cache', () => ({
invalidateAuthorizedRootsCache: vi.fn()
}))
vi.mock('../ipc/registered-worktree-roots-scoped-invalidation', () => ({
invalidateAuthorizedRootsCacheForRepo: vi.fn()
}))
@@ -21,7 +21,7 @@ import {
} from '../../shared/execution-host'
import { getProjectIdForProviderIdentity } from '../../shared/project-host-setup-projection'
import { getProjectHostSetupForRepo } from '../../shared/project-host-setup-lookup'
import { invalidateAuthorizedRootsCache } from '../ipc/filesystem-auth'
import { invalidateAuthorizedRootsCache } from '../ipc/registered-worktree-roots-cache'
import {
SshHostNotServedError,
sshTargetNotConnectedMessage
@@ -18,7 +18,7 @@ import {
import { gitSpawnAfterWindowsEnvironmentReady, promptGuardGitEnv } from '../git/runner'
import { reuseSavedCloneTarget } from '../git/saved-clone-target'
import { runWithGitReadCacheInvalidation } from '../git/status'
import { invalidateAuthorizedRootsCache } from '../ipc/filesystem-auth'
import { invalidateAuthorizedRootsCache } from '../ipc/registered-worktree-roots-cache'
import { detectRepoIconAndUpstream } from '../repo-icon-autodetect'
import { getRepoName } from '../git/repo'
import { prepareLocalWorktreeRootForRepo } from '../worktree-root-preparation'
@@ -7,7 +7,7 @@ import {
getDefaultTabCommandTrustContent,
getEffectiveSetupRunPolicy
} from '../effective-hook-config'
import { isENOENT } from '../ipc/filesystem-auth'
import { isENOENT } from '../ipc/filesystem-path-containment'
import { isFolderRepo } from '../../shared/repo-kind'
import { inspectSetupScriptImportCandidates } from '../../shared/setup-script-imports'
import { joinWorktreeRelativePath } from './runtime-relative-paths'
@@ -11,7 +11,8 @@ import {
import type { Repo } from '../../shared/repo-types'
import { gitExecFileAsync, awaitWindowsHostGitEnvironmentReady } from '../git/runner'
import { getRepoName, inspectGitRepoForRegistrationAsync } from '../git/repo'
import { invalidateAuthorizedRootsCache, isENOENT } from '../ipc/filesystem-auth'
import { invalidateAuthorizedRootsCache } from '../ipc/registered-worktree-roots-cache'
import { isENOENT } from '../ipc/filesystem-path-containment'
import { findProjectAtSameRealPath } from '../project-realpath-identity'
import { detectRepoIconAndUpstream } from '../repo-icon-autodetect'
import { prepareLocalWorktreeRootForRepo } from '../worktree-root-preparation'
@@ -3,7 +3,7 @@ import { isFolderRepo } from '../../shared/repo-kind'
import { commitProvenRepoKindChange } from '../folder-repo-git-conversion'
import type { Repo } from '../../shared/repo-types'
import type { GhAccountBinding } from '../../shared/github/account-binding'
import { invalidateAuthorizedRootsCache } from '../ipc/filesystem-auth'
import { invalidateAuthorizedRootsCache } from '../ipc/registered-worktree-roots-cache'
import { prepareLocalWorktreeRootForRepo } from '../worktree-root-preparation'
import type { RuntimeStore } from './runtime-store-contract'
import { assertWslMoveRepoWritable } from '../persistence/moving-wsl-projects/wsl-move-scope-guard'
@@ -3,7 +3,7 @@ import { stat } from 'node:fs/promises'
import { FOLDER_WORKSPACE_INSTANCE_SEPARATOR } from '../../shared/worktree/id'
import type { Repo } from '../../shared/repo-types'
import type { Worktree } from '../../shared/worktree/types'
import { isENOENT } from '../ipc/filesystem-auth'
import { isENOENT } from '../ipc/filesystem-path-containment'
import {
getLocalWorktreePathAccess,
toLocalWorktreeRuntimePath
@@ -15,7 +15,7 @@ import { createRuntimeFolderWorktree } from '../runtime-folder-worktree-create'
import { createRuntimeLocalManagedWorktree } from '../runtime-local-worktree-create'
import type { PreparationRearmHolder } from '../../worktree-create-preparation'
import { prepareRuntimeLocalWorktreeSetup } from '../runtime-local-worktree-setup'
import { invalidateAuthorizedRootsCacheForRepo } from '../../ipc/filesystem-auth'
import { invalidateAuthorizedRootsCacheForRepo } from '../../ipc/registered-worktree-roots-scoped-invalidation'
import { startRuntimeLocalWorktreeTerminals } from '../runtime-local-worktree-terminal-startup'
import { trackRuntimeWorkspaceCreate } from '../../workspace-create-telemetry'
import { assertOpenCodeModelLaunchPreferencesAbsent } from '../../opencode/opencode-model-startup-plan'
@@ -6,7 +6,7 @@ import type { ExecutionHostId } from '../../../shared/execution-host'
import type { WorktreeTeardownRuntime } from '../worktree-teardown'
import { splitWorktreeId, splitWorktreeIdForFilesystem } from '../../../shared/worktree/id'
import { parseExecutionHostId } from '../../../shared/execution-host'
import { invalidateAuthorizedRootsCache } from '../../ipc/filesystem-auth'
import { invalidateAuthorizedRootsCache } from '../../ipc/registered-worktree-roots-cache'
import { isFolderRepo } from '../../../shared/repo-kind'
import { getRuntimeFolderWorkspaceRootId } from '../runtime-folder-workspace'
import { killAllProcessesForWorktree } from '../worktree-teardown'
@@ -25,7 +25,7 @@ import {
parseExecutionHostId,
type ExecutionHostId
} from '../../../shared/execution-host'
import { invalidateAuthorizedRootsCacheForRepo } from '../../ipc/filesystem-auth'
import { invalidateAuthorizedRootsCacheForRepo } from '../../ipc/registered-worktree-roots-scoped-invalidation'
import {
resumeInterruptedWorktreeRemovals,
retryFailedWorktreeRemoval,
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest'
import { isMarkdownDocumentName } from '../ipc/markdown-documents'
import { isMarkdownDocumentName } from '../../shared/markdown-document-paths'
import { documentPathsFromArguments } from './os-opened-documents'
describe('documentPathsFromArguments', () => {
+4 -1
View File
@@ -3,7 +3,10 @@ import path from 'node:path'
import { fileURLToPath } from 'node:url'
import type { FileDocument } from '../../shared/filesystem-entry-types'
import { ensureDefaultFloatingWorkspacePath } from '../ipc/floating-workspace-directory'
import { fileDocumentFromFilePath, isMarkdownDocumentName } from '../ipc/markdown-documents'
import {
fileDocumentFromFilePath,
isMarkdownDocumentName
} from '../../shared/markdown-document-paths'
export function isOsOpenedDocumentName(name: string): boolean {
const extension = path.extname(name).toLowerCase()