Skip to content

Commit

Permalink
fix: resolve real path for case insensitive systems (#4935)
Browse files Browse the repository at this point in the history
close #4904
  • Loading branch information
mdogadailo authored and zkochan committed Jun 30, 2022
1 parent 3cc151a commit 1d3729d
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .changeset/quiet-icons-wait.md
@@ -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).
15 changes: 14 additions & 1 deletion packages/find-workspace-dir/src/index.ts
@@ -1,3 +1,4 @@
import fs from 'fs'
import path from 'path'
import PnpmError from '@pnpm/error'
import findUp from 'find-up'
Expand All @@ -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)
})
})
}
20 changes: 20 additions & 0 deletions packages/find-workspace-dir/test/index.ts
@@ -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
Expand Down

0 comments on commit 1d3729d

Please sign in to comment.