orca/src/shared/wsl-paths.ts

48 lines
1.6 KiB
TypeScript

export type WslUncPathInfo = {
distro: string
linuxPath: string
}
export function parseWslUncPath(path: string): WslUncPathInfo | null {
const normalized = path.replace(/\\/g, '/')
const match = normalized.match(/^\/\/(wsl\.localhost|wsl\$)\/([^/]+)(\/.*)?$/i)
if (!match) {
return null
}
return {
distro: match[2],
linuxPath: match[3] || '/'
}
}
export function isWslUncPath(path: string): boolean {
return parseWslUncPath(path) !== null
}
/** Convert an absolute Linux path in a known WSL distro to its Windows form. */
export function toWindowsWslPath(linuxPath: string, distro: string): string {
const mntMatch = linuxPath.match(/^\/mnt\/([a-z])(\/.*)?$/)
if (mntMatch) {
const rest = (mntMatch[2] || '').replace(/\//g, '\\')
return `${mntMatch[1].toUpperCase()}:${rest || '\\'}`
}
return `\\\\wsl.localhost\\${distro}${linuxPath.replace(/\//g, '\\')}`
}
// Why: Windows folds the share (\\wsl$ aliases \\wsl.localhost), the distro, and
// drvfs /mnt/<drive> tails case-insensitively; the rest of the Linux path is not.
export function foldWslUncPathCaseInsensitiveParts(path: string): string | null {
const parsed = parseWslUncPath(path)
if (!parsed) {
return null
}
// Why: the drvfs automount is literally lowercase /mnt — a case-variant like
// /MNT is an ordinary case-sensitive Linux dir and must not be folded.
const linuxPath = /^\/mnt\/[a-zA-Z](?:\/|$)/.test(parsed.linuxPath)
? parsed.linuxPath.toLowerCase()
: parsed.linuxPath
return `//wsl.localhost/${parsed.distro.toLowerCase()}${linuxPath === '/' ? '' : linuxPath}`
}