fix: resolve real path for case insensitive systems (#4935)

close #4904
This commit is contained in:
Maksym Dogadailo
2022-06-26 13:36:24 +02:00
committed by GitHub
parent 12aa1e2e19
commit 6434a82910
3 changed files with 40 additions and 1 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/find-workspace-dir": patch
"pnpm": patch
---
Resolve native workspace path for case-insensitive file systems [#4904](https://github.com/pnpm/pnpm/issues/4904).

View File

@@ -1,3 +1,4 @@
import fs from 'fs'
import path from 'path'
import PnpmError from '@pnpm/error'
import findUp from 'find-up'
@@ -9,9 +10,21 @@ export default async function findWorkspaceDir (cwd: string) {
const workspaceManifestDirEnvVar = process.env[WORKSPACE_DIR_ENV_VAR] ?? process.env[WORKSPACE_DIR_ENV_VAR.toLowerCase()]
const workspaceManifestLocation = workspaceManifestDirEnvVar
? path.join(workspaceManifestDirEnvVar, 'pnpm-workspace.yaml')
: await findUp([WORKSPACE_MANIFEST_FILENAME, 'pnpm-workspace.yml'], { cwd })
: await findUp([WORKSPACE_MANIFEST_FILENAME, 'pnpm-workspace.yml'], { cwd: await getRealPath(cwd) })
if (workspaceManifestLocation?.endsWith('.yml')) {
throw new PnpmError('BAD_WORKSPACE_MANIFEST_NAME', `The workspace manifest file should be named "pnpm-workspace.yaml". File found: ${workspaceManifestLocation}`)
}
return workspaceManifestLocation && path.dirname(workspaceManifestLocation)
}
async function getRealPath (path: string) {
return new Promise<string>((resolve) => {
// We need to resolve the real native path for case-insensitive file systems.
// For example, we can access file as C:\Code\Project as well as c:\code\projects
// Without this we can face a problem when try to install packages with -w flag,
// when root dir is using c:\code\projects but packages were found by C:\Code\Project
fs.realpath.native(path, function (err, resolvedPath) {
resolve(err !== null ? path : resolvedPath)
})
})
}

View File

@@ -1,16 +1,36 @@
/// <reference path="../../../typings/index.d.ts"/>
import path from 'path'
import fs from 'fs'
import findWorkspaceDir from '@pnpm/find-workspace-dir'
const NPM_CONFIG_WORKSPACE_DIR_ENV_VAR = 'NPM_CONFIG_WORKSPACE_DIR'
const FAKE_PATH = 'FAKE_PATH'
function isFileSystemCaseSensitive () {
try {
fs.realpathSync.native(process.cwd().toUpperCase())
return false
} catch (_) {
return true
}
}
// We don't need to validate case-sensitive systems
// because it is not possible to reach process.cwd() with wrong case there.
const testOnCaseInSensitiveSystems = isFileSystemCaseSensitive() ? test.skip : test
test('finds actual workspace dir', async () => {
const workspaceDir = await findWorkspaceDir(process.cwd())
expect(workspaceDir).toBe(path.resolve(__dirname, '..', '..', '..'))
})
testOnCaseInSensitiveSystems('finds workspace dir with wrong case from cwd', async () => {
const workspaceDir = await findWorkspaceDir(process.cwd().toUpperCase())
expect(workspaceDir).toBe(path.resolve(__dirname, '..', '..', '..'))
})
test('finds overriden workspace dir', async () => {
const oldValue = process.env[NPM_CONFIG_WORKSPACE_DIR_ENV_VAR]
process.env[NPM_CONFIG_WORKSPACE_DIR_ENV_VAR] = FAKE_PATH