diff --git a/scripts/ci-cli.js b/scripts/ci-cli.js old mode 100644 new mode 100755 diff --git a/src/vfs/promises.ts b/src/vfs/promises.ts index da3516b2..d3e8a5d4 100644 --- a/src/vfs/promises.ts +++ b/src/vfs/promises.ts @@ -1020,6 +1020,28 @@ export async function realpath( path = normalizePath(path); const ctx_path = (this?.root || '') + path; if (cache.paths.hasAsync(ctx_path)) return cache.paths.getAsync(ctx_path)!; + + /* Try to resolve it directly. If this works, + that means we don't need to perform any resolution for parent directories. */ + try { + const { fs, path: resolvedPath } = resolveMount(path, this); + // Stat it to make sure it exists + const stats = await fs.stat(resolvedPath); + + let real = path.toString(); + + if (stats.isSymbolicLink()) { + const target = resolve(dirname(resolvedPath), (await readlink.call(this, resolvedPath, options)).toString()); + real = cache.paths.get((this?.root || '') + target) || (await realpath.call(this, target)); + cache.paths.set(ctx_path, real); + } + + cache.paths.set(path.toString(), real); + return real; + } catch { + // Go the long way + } + const { base, dir } = parse(path); const realDir = dir == '/' ? '/' : await (cache.paths.getAsync((this?.root || '') + dir) || realpath.call(this, dir)); const lpath = join(realDir, base); diff --git a/src/vfs/sync.ts b/src/vfs/sync.ts index 4821e53e..1bcaddf5 100644 --- a/src/vfs/sync.ts +++ b/src/vfs/sync.ts @@ -710,6 +710,28 @@ export function realpathSync(this: V_Context, path: fs.PathLike, options?: fs.En path = normalizePath(path); const ctx_path = (this?.root || '') + path; if (cache.paths.has(ctx_path)) return cache.paths.get(ctx_path)!; + + /* Try to resolve it directly. If this works, + that means we don't need to perform any resolution for parent directories. */ + try { + const { fs, path: resolvedPath } = resolveMount(path, this); + // Stat it to make sure it exists + const stats = fs.statSync(resolvedPath); + + let real = path; + + if (stats.isSymbolicLink()) { + const target = resolve(dirname(resolvedPath), readlinkSync.call(this, resolvedPath, options).toString()); + real = cache.paths.get((this?.root || '') + target) || realpathSync.call(this, target); + cache.paths.set(ctx_path, real); + } + + cache.paths.set(path, real); + return real; + } catch { + // Go the long way + } + const { base, dir } = parse(path); const realDir = dir == '/' ? '/' : cache.paths.get((this?.root || '') + dir) || realpathSync.call(this, dir); const lpath = join(realDir, base);