Restore ENOTDIR semantic distinction in resolveLocalTarget on Windows
This commit is contained in:
@@ -145,8 +145,22 @@ export async function resolveLocalTarget(cwd: string, path: string): Promise<Loc
|
|||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
const realAncestor = await realpath(ancestor)
|
const realAncestor = await realpath(ancestor)
|
||||||
|
// On Windows, realpath of a regular file succeeds where POSIX returns
|
||||||
|
// ENOTDIR (the OS reports ENOENT for `regular-file/child`, not ENOTDIR).
|
||||||
|
// Stat the ancestor to restore the semantic distinction: a non-directory
|
||||||
|
// ancestor means the target passes through a file and can never be created.
|
||||||
|
/* v8 ignore start -- native Windows coverage exercises this repair; POSIX reports ENOTDIR before this point. */
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
const parentInfo = await stat(realAncestor)
|
||||||
|
if (!parentInfo.isDirectory()) {
|
||||||
|
throw new FsError(`cannot resolve "${displayPath}": a parent path segment is not a directory`, 'FS_NOT_FOUND')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* v8 ignore stop */
|
||||||
return { displayPath, targetKey: FsTargetKey(join(realAncestor, ...missing)) }
|
return { displayPath, targetKey: FsTargetKey(join(realAncestor, ...missing)) }
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
|
/* v8 ignore next -- native Windows coverage exercises the FsError raised by the repair above. */
|
||||||
|
if (error instanceof FsError) throw error
|
||||||
/* v8 ignore next -- a non-ENOENT realpath failure needs a permission/IO fault. */
|
/* v8 ignore next -- a non-ENOENT realpath failure needs a permission/IO fault. */
|
||||||
if (!isENOENT(error)) throw error
|
if (!isENOENT(error)) throw error
|
||||||
const parent = dirname(ancestor)
|
const parent = dirname(ancestor)
|
||||||
|
|||||||
Reference in New Issue
Block a user