diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index d1b3eb14cae7c8..81d7e22bad6cf8 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -1,6 +1,7 @@ import fs from 'node:fs' import os from 'node:os' import path from 'node:path' +import { exec } from 'node:child_process' import { createHash } from 'node:crypto' import { promisify } from 'node:util' import { URL, URLSearchParams } from 'node:url' @@ -597,10 +598,51 @@ export const renameDir = isWindows ? promisify(gracefulRename) : fs.renameSync // `fs.realpathSync.native` resolves differently in Windows network drive, // causing file read errors. skip for now. // https://github.com/nodejs/node/issues/37737 -export const safeRealpathSync = isWindows - ? fs.realpathSync +export let safeRealpathSync = isWindows + ? windowsSafeRealPathSync : fs.realpathSync.native +// Based on https://github.com/larrybahr/windows-network-drive +// MIT License, Copyright (c) 2017 Larry Bahr +const windowsNetworkMap = new Map() +function windowsMappedRealpathSync(path: string) { + const realPath = fs.realpathSync.native(path) + if (realPath.startsWith('\\\\')) { + for (const [network, volume] of windowsNetworkMap) { + if (realPath.startsWith(network)) return realPath.replace(network, volume) + } + } + return realPath +} +const parseNetUseRE = /^(\w+) +(\w:) +([^ ]+)\s/ +let firstSafeRealPathSyncRun = false + +function windowsSafeRealPathSync(path: string): string { + if (!firstSafeRealPathSyncRun) { + optimizeSafeRealPathSync() + firstSafeRealPathSyncRun = true + } + return fs.realpathSync(path) +} + +function optimizeSafeRealPathSync() { + exec('net use', (error, stdout) => { + if (error) return + const lines = stdout.split('\n') + // OK Y: \\NETWORKA\Foo Microsoft Windows Network + // OK Z: \\NETWORKA\Bar Microsoft Windows Network + for (const line of lines) { + const m = line.match(parseNetUseRE) + if (m) windowsNetworkMap.set(m[3], m[2]) + } + if (windowsNetworkMap.size === 0) { + safeRealpathSync = fs.realpathSync.native + } else { + safeRealpathSync = windowsMappedRealpathSync + } + }) +} + export function ensureWatchedFile( watcher: FSWatcher, file: string | null,