refactor(shared): dedupe the local-default connection-to-host conversion and the trim helpers (#27797)

Co-authored-by: m4air <m4air@Mac.localdomain>
This commit is contained in:
OrcaWin
2026-10-11 23:40:18 -07:00
committed by GitHub
co-authored by m4air
parent d327cc9418
commit 8a1c63b381
9 changed files with 49 additions and 36 deletions
@@ -33,6 +33,8 @@ describe('getLocalPathOpenOwnerForRoute', () => {
expect(getLocalPathOpenOwnerForRoute({})).toBe('local')
expect(getLocalPathOpenOwnerForRoute({ runtimeEnvironmentId: ' env-2 ' })).toBe('runtime:env-2')
expect(getLocalPathOpenOwnerForRoute({ connectionId: 'ssh-1' })).toBe('ssh:ssh-1')
expect(getLocalPathOpenOwnerForRoute({ connectionId: ' ssh-1 ' })).toBe('ssh:ssh-1')
expect(getLocalPathOpenOwnerForRoute({ connectionId: ' ' })).toBe('local')
expect(
getLocalPathOpenOwnerForRoute({ runtimeEnvironmentId: null, ownerUnresolved: true })
).toBe('unresolved')
@@ -1,8 +1,8 @@
import { toast } from 'sonner'
import {
getConnectionExecutionHostId,
parseRoutableExecutionHostId,
toRuntimeExecutionHostId,
toSshExecutionHostId,
type ExecutionHostId
} from '../../../shared/execution-host'
import type { ExecutionHostOwnerMatch } from '../../../shared/worktree-execution-host-resolution'
@@ -34,8 +34,7 @@ export function getLocalPathOpenOwnerForRoute(route: {
if (runtimeEnvironmentId) {
return toRuntimeExecutionHostId(runtimeEnvironmentId)
}
const connectionId = route.connectionId?.trim()
return connectionId ? toSshExecutionHostId(connectionId) : 'local'
return getConnectionExecutionHostId(route.connectionId?.trim())
}
/** The inverse of {@link getLocalPathOpenOwnerForRoute}, for callers that still take a route. */
@@ -47,6 +47,21 @@ describe('getResolvedExecutionHostIdForWorktree', () => {
)
})
it('falls back from the repo host stamp to its connection id, then local', () => {
const state = (repo: { connectionId: string | null; executionHostId?: ExecutionHostId }) => ({
repos: [{ id: 'repo', ...repo }],
worktreesByRepo: { repo: [{ id: 'repo::wt', repoId: 'repo' }] }
})
const resolve = (repo: { connectionId: string | null; executionHostId?: ExecutionHostId }) =>
getResolvedExecutionHostIdForWorktree(state(repo), 'repo::wt')
expect(resolve({ connectionId: 'target-1', executionHostId: 'runtime:env-1' })).toBe(
'runtime:env-1'
)
expect(resolve({ connectionId: null, executionHostId: 'ssh:target-2' })).toBe('ssh:target-2')
expect(resolve({ connectionId: 'target-1' })).toBe('ssh:target-1')
expect(resolve({ connectionId: ' ' })).toBe('local')
})
it('keeps missing folder catalogs unresolved but honors restored runtime ownership', () => {
expect(getResolvedExecutionHostIdForWorktree({}, 'folder:missing')).toBeNull()
expect(
@@ -1,5 +1,6 @@
import {
LOCAL_EXECUTION_HOST_ID,
getRepoExecutionHostId,
parseExecutionHostId,
toSshExecutionHostId,
type ExecutionHostId
@@ -91,13 +92,7 @@ export function getResolvedExecutionHostIdForWorktree(
if (!repo) {
return null
}
const explicitRepoHost = parseExecutionHostId(repo.executionHostId)
if (explicitRepoHost) {
return explicitRepoHost.id
}
return repo.connectionId?.trim()
? toSshExecutionHostId(repo.connectionId)
: LOCAL_EXECUTION_HOST_ID
return getRepoExecutionHostId(repo)
}
/**
@@ -1,6 +1,23 @@
import { describe, expect, it } from 'vitest'
import type { FolderWorkspace } from '../../../../../../shared/folder-workspace-types'
import type { DetectedWorktreeListResult } from '../../../../../../shared/worktree/types'
import { applyDetectedWorktreeUpdates } from './detected-worktree-meta'
import { applyDetectedWorktreeUpdates, folderWorkspaceMatchesHost } from './detected-worktree-meta'
describe('folderWorkspaceMatchesHost', () => {
it('prefers the host stamp, then the connection id, then local', () => {
type Row = Pick<FolderWorkspace, 'connectionId' | 'executionHostId'>
const ssh: Row = { executionHostId: 'ssh:target-1', connectionId: null }
expect(folderWorkspaceMatchesHost(ssh, 'ssh:target-1')).toBe(true)
expect(folderWorkspaceMatchesHost(ssh, 'local')).toBe(false)
const stamped: Row = { executionHostId: 'runtime:env-1', connectionId: 'target-1' }
expect(folderWorkspaceMatchesHost(stamped, 'runtime:env-1')).toBe(true)
expect(folderWorkspaceMatchesHost(stamped, 'ssh:target-1')).toBe(false)
const legacy: Row = { executionHostId: undefined, connectionId: 'target-1' }
expect(folderWorkspaceMatchesHost(legacy, 'ssh:target-1')).toBe(true)
expect(folderWorkspaceMatchesHost({ connectionId: ' ' }, 'local')).toBe(true)
expect(folderWorkspaceMatchesHost({ connectionId: null }, 'local')).toBe(true)
})
})
describe('applyDetectedWorktreeUpdates display-name provenance', () => {
it('projects pinning changes into detected rows', () => {
@@ -6,8 +6,7 @@ import type { DetectedWorktreeListResult, Worktree } from '../../../../../../sha
import type { ExecutionHostId } from '../../../../../../shared/execution-host'
import {
LOCAL_EXECUTION_HOST_ID,
parseExecutionHostId,
toSshExecutionHostId
getRepoExecutionHostId
} from '../../../../../../shared/execution-host'
import { parseWorkspaceKey } from '../../../../../../shared/workspace-scope'
import { folderWorkspaceToWorktree } from '../../../../../../shared/folder-workspace-worktree'
@@ -70,12 +69,7 @@ export function folderWorkspaceMatchesHost(
workspace: Pick<FolderWorkspace, 'connectionId' | 'executionHostId'>,
executionHostId: ExecutionHostId
): boolean {
return (
(parseExecutionHostId(workspace.executionHostId)?.id ??
(workspace.connectionId?.trim()
? toSshExecutionHostId(workspace.connectionId)
: LOCAL_EXECUTION_HOST_ID)) === executionHostId
)
return getRepoExecutionHostId(workspace) === executionHostId
}
/** Stable synthetic row per folder workspace object, so selectors keep referential equality. */
+1 -5
View File
@@ -6,6 +6,7 @@ import {
getSettingsFocusedExecutionHostId,
getSshTargetIdForExecutionHost,
isRuntimeOwnedSshTargetId,
normalizeHostPart,
parseExecutionHostId,
toRuntimeExecutionHostId,
toSshExecutionHostId,
@@ -55,11 +56,6 @@ type RuntimeStatusByEnvironmentId = ReadonlyMap<string, RuntimeEnvironmentStatus
export type ExecutionHostSource = 'configured-only' | 'include-references'
function normalizeHostPart(value: string | null | undefined): string | null {
const trimmed = value?.trim()
return trimmed ? trimmed : null
}
function runtimeCompatibility(
status: RuntimeStatus | null | undefined
): RuntimeCompatVerdict | null {
+3 -3
View File
@@ -53,9 +53,9 @@ export function getLocalExecutionHostLabel(platform: NodeJS.Platform | null = nu
return 'This computer'
}
function normalizeHostPart(value: string | null | undefined): string | null {
const trimmed = value?.trim()
return trimmed ? trimmed : null
/** Trims a stored id; blank is absent, since no write path normalizes it. */
export function normalizeHostPart(value: string | null | undefined): string | null {
return value?.trim() || null
}
export function toSshExecutionHostId(targetId: string): `ssh:${string}` {
@@ -17,7 +17,7 @@ import type { ProjectGroup } from './project-group-types'
import type { Repo } from './repo-types'
import { isPathInsideOrEqual } from './cross-platform-path'
import { getProjectGroupSubtreeIds } from './project-groups'
import { getRepoExecutionHostId, parseExecutionHostId } from './execution-host'
import { getRepoExecutionHostId, normalizeHostPart, parseExecutionHostId } from './execution-host'
export type FolderWorkspaceHostState = {
folderWorkspaces: readonly FolderWorkspace[]
@@ -33,11 +33,6 @@ export type FolderWorkspaceHost =
| { kind: 'runtime'; environmentId: string; sshTargetId: string | null }
| { kind: 'ambiguous' }
/** Reads a stored connection id: blank is local, since no write path normalizes it. */
export function normalizeConnectionId(value: string | null | undefined): string | null {
return value?.trim() || null
}
/**
* The SSH target whose filesystem holds this repo's files, or `null` for anything else.
*
@@ -52,7 +47,7 @@ export function normalizeConnectionId(value: string | null | undefined): string
*/
function getRepoScopeConnectionId(repo: Repo): string | null {
const host = parseExecutionHostId(getRepoExecutionHostId(repo))
return host?.kind === 'ssh' ? host.targetId : normalizeConnectionId(repo.connectionId)
return host?.kind === 'ssh' ? host.targetId : normalizeHostPart(repo.connectionId)
}
function getFolderScopeCandidateRepos(args: {
@@ -105,7 +100,7 @@ export function findFolderWorkspaceCandidateRepos(
return getFolderScopeCandidateRepos({
folderPath: workspace.folderPath,
projectGroupId: workspace.projectGroupId,
connectionId: normalizeConnectionId(workspace.connectionId ?? group?.connectionId),
connectionId: normalizeHostPart(workspace.connectionId ?? group?.connectionId),
projectGroups: state.projectGroups,
repos: state.repos
})
@@ -120,7 +115,7 @@ export function resolveFolderWorkspaceHost(
return { kind: 'missing' }
}
const readScopeConnectionId = (): string | null =>
normalizeConnectionId(
normalizeHostPart(
workspace.connectionId ??
state.projectGroups.find((entry) => entry.id === workspace.projectGroupId)?.connectionId
)