mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
fix: normalize Windows drive roots (#979)
This commit is contained in:
@@ -18,7 +18,7 @@ vi.mock('../modules/common/opencodeModels', () => ({
|
||||
listOpencodeModelsForCwd: listOpencodeModelsForCwdMock
|
||||
}))
|
||||
|
||||
import { ApiMachineClient } from './apiMachine'
|
||||
import { ApiMachineClient, normalizeWindowsDriveRoot } from './apiMachine'
|
||||
import type { Machine } from './types'
|
||||
|
||||
function makeMachine(id: string): Machine {
|
||||
@@ -37,6 +37,18 @@ function makeMachine(id: string): Machine {
|
||||
}
|
||||
}
|
||||
|
||||
describe('normalizeWindowsDriveRoot', () => {
|
||||
it('restores the trailing separator when Windows realpath returns a bare drive', () => {
|
||||
expect(normalizeWindowsDriveRoot('C:')).toBe('C:\\')
|
||||
expect(normalizeWindowsDriveRoot('D:')).toBe('D:\\')
|
||||
})
|
||||
|
||||
it('leaves non-drive-root paths unchanged', () => {
|
||||
expect(normalizeWindowsDriveRoot('C:\\Users')).toBe('C:\\Users')
|
||||
expect(normalizeWindowsDriveRoot('/tmp/workspace')).toBe('/tmp/workspace')
|
||||
})
|
||||
})
|
||||
|
||||
async function callListOpencodeModels(client: ApiMachineClient, machineId: string, cwd: string): Promise<unknown> {
|
||||
// Reach into the private rpc handler manager to dispatch a request.
|
||||
// Mirrors how the on-socket 'rpc-request' listener invokes handleRequest.
|
||||
@@ -137,7 +149,7 @@ describe('ApiMachineClient listOpencodeModelsForCwd handler', () => {
|
||||
})
|
||||
// The handler realpaths the cwd (security: prevents symlink escape),
|
||||
// so on macOS /var/folders/... resolves to /private/var/folders/...
|
||||
expect(listOpencodeModelsForCwdMock).toHaveBeenCalledWith(realpathSync(secondWorkspaceRoot))
|
||||
expect(listOpencodeModelsForCwdMock).toHaveBeenCalledWith(realpathSync.native(secondWorkspaceRoot))
|
||||
} finally {
|
||||
rmSync(secondWorkspaceRoot, { recursive: true, force: true })
|
||||
client.shutdown()
|
||||
|
||||
@@ -41,6 +41,14 @@ interface ListMachineDirectoryRequest {
|
||||
path: string
|
||||
}
|
||||
|
||||
export function normalizeWindowsDriveRoot(path: string): string {
|
||||
return /^[A-Za-z]:$/.test(path) ? `${path}\\` : path
|
||||
}
|
||||
|
||||
function canonicalRealpathSync(path: string): string {
|
||||
return normalizeWindowsDriveRoot(realpathSync.native(path))
|
||||
}
|
||||
|
||||
function normalizeWorkspaceRoots(paths?: string[]): string[] | undefined {
|
||||
if (!paths?.length) {
|
||||
return undefined
|
||||
@@ -48,9 +56,9 @@ function normalizeWorkspaceRoots(paths?: string[]): string[] | undefined {
|
||||
|
||||
const normalized = Array.from(new Set(paths.map((path) => {
|
||||
try {
|
||||
return realpathSync(path)
|
||||
return canonicalRealpathSync(path)
|
||||
} catch {
|
||||
return resolvePath(path)
|
||||
return normalizeWindowsDriveRoot(resolvePath(path))
|
||||
}
|
||||
})))
|
||||
|
||||
@@ -232,7 +240,7 @@ export class ApiMachineClient {
|
||||
private async resolveForWorkspaceCheck(path: string): Promise<string> {
|
||||
const absolute = resolvePath(path)
|
||||
try {
|
||||
return await realpath(absolute)
|
||||
return normalizeWindowsDriveRoot(await realpath(absolute))
|
||||
} catch {
|
||||
const missing: string[] = []
|
||||
let cursor = absolute
|
||||
@@ -240,12 +248,12 @@ export class ApiMachineClient {
|
||||
missing.unshift(basename(cursor))
|
||||
cursor = dirname(cursor)
|
||||
try {
|
||||
return join(await realpath(cursor), ...missing)
|
||||
return join(normalizeWindowsDriveRoot(await realpath(cursor)), ...missing)
|
||||
} catch {
|
||||
// keep walking to the nearest existing parent
|
||||
}
|
||||
}
|
||||
return absolute
|
||||
return normalizeWindowsDriveRoot(absolute)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user