export interface WslDistro { readonly name: string; readonly isDefault: boolean; readonly version: 1 | 2; } export interface WslConfig { readonly distro: string | null; } // Literal space — \s would also match \n/\t/\r and corrupt UNC paths like \\wsl.localhost\\... // Trailing char must also be \w so hand-edited config like "Ubuntu " / "Ubuntu-" / "Ubuntu." rejects. export const DISTRO_NAME_PATTERN = /^\w(?:[\w \-.]*\w)?$/; export function parseWslDistroList(stdout: Buffer): readonly WslDistro[] { const hasUtf16Bom = stdout.length >= 2 && stdout[0] === 0xff && stdout[1] === 0xfe; const likelyUtf16Le = hasUtf16Bom || Array.from(stdout.subarray(0, Math.min(stdout.length, 80))).filter( (byte, index) => index % 2 === 1 && byte === 0, ).length > 10; let text = stdout.toString(likelyUtf16Le ? "utf16le" : "utf8"); if (text.charCodeAt(0) === 0xfeff) text = text.slice(1); const lines = text.split(/\r?\n/).filter((line) => line.trim().length > 0); const distros: WslDistro[] = []; for (let i = 1; i < lines.length; i++) { const line = lines[i]!; const isDefault = line.startsWith("*"); const cleaned = isDefault ? line.slice(1).trim() : line.trim(); const fields = cleaned.split(/\s{2,}/); if (fields.length < 3) continue; const name = fields[0]!.trim(); const versionNum = parseInt(fields[2]!, 10); if (!name || (versionNum !== 1 && versionNum !== 2)) continue; distros.push({ name, isDefault, version: versionNum as 1 | 2 }); } return distros; } // Recognizes \\wsl.localhost\\... and the legacy \\wsl$\\... so // `wslpath` can be invoked inside the distro that actually owns the path, // rather than whichever distro is configured for the desktop backend. export function extractDistroFromUncPath(windowsPath: string): string | null { const match = /^\\\\(?:wsl\.localhost|wsl\$)\\([^\\]+)/i.exec(windowsPath); if (!match) return null; const candidate = match[1]!; return DISTRO_NAME_PATTERN.test(candidate) ? candidate : null; } export function wslUncPathToLinuxPath(windowsPath: string): string | null { const match = /^\\\\(?:wsl\.localhost|wsl\$)\\([^\\]+)(?:\\(.*))?$/i.exec(windowsPath.trim()); if (!match) return null; const distro = match[1]!; if (!DISTRO_NAME_PATTERN.test(distro)) return null; const rest = match[2] ?? ""; if (rest.length === 0) return "/"; return `/${rest.split("\\").filter(Boolean).join("/")}`; } export function resolveWslHomeUncPath( config: WslConfig, distros: readonly WslDistro[], ): string | null { const distroName = config.distro ?? distros.find((distro) => distro.isDefault)?.name ?? null; return distroName ? `\\\\wsl.localhost\\${distroName}\\home` : null; } export function resolveWslPickFolderDefaultPath( rawOptions: unknown, config: WslConfig, distros: readonly WslDistro[], // Absolute Linux path of the user's home dir inside the chosen distro // (e.g. "/home/josh"). When known, `~` and `~/...` expand against this so // we don't open the picker at a non-existent `/home/`. When null we // fall back to the `/home` parent — wrong directory but at least it exists. userHome: string | null = null, ): string | null { const homePath = resolveWslHomeUncPath(config, distros); if (typeof rawOptions !== "object" || rawOptions === null) { return homePath; } const { initialPath } = rawOptions as { initialPath?: unknown }; if (typeof initialPath !== "string") { return homePath; } const trimmedPath = initialPath.trim(); if (trimmedPath.length === 0) { return homePath; } if (trimmedPath.startsWith("\\\\")) { return trimmedPath; } const distroName = config.distro ?? distros.find((distro) => distro.isDefault)?.name ?? null; if (!distroName) { return homePath; } const toUncPath = (linuxPath: string) => `\\\\wsl.localhost\\${distroName}${linuxPath.replaceAll("/", "\\")}`; const normalizedUserHome = userHome && userHome.startsWith("/") ? userHome : null; if (trimmedPath === "~") { return normalizedUserHome ? toUncPath(normalizedUserHome) : homePath; } if (trimmedPath.startsWith("~/")) { const remainder = trimmedPath.slice(2); if (normalizedUserHome) { return toUncPath(`${normalizedUserHome}/${remainder}`); } return homePath ? `${homePath}\\${remainder.replaceAll("/", "\\")}` : null; } if (trimmedPath.startsWith("/")) { return toUncPath(trimmedPath); } return homePath; } export function isValidDistroName(value: string): boolean { return DISTRO_NAME_PATTERN.test(value); }