mirror of
https://github.com/pnpm/pnpm.git
synced 2026-02-15 17:42:31 -05:00
feat: extend symlink error message (#8879)
--------- Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
6
.changeset/fluffy-plants-chew.md
Normal file
6
.changeset/fluffy-plants-chew.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/worker": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Print a hint, when installation fails due to an exFAT drive.
|
||||
29
pnpm-lock.yaml
generated
29
pnpm-lock.yaml
generated
@@ -144,6 +144,9 @@ catalogs:
|
||||
'@types/semver':
|
||||
specifier: 7.5.3
|
||||
version: 7.5.3
|
||||
'@types/shell-quote':
|
||||
specifier: ^1.7.5
|
||||
version: 1.7.5
|
||||
'@types/signal-exit':
|
||||
specifier: ^3.0.4
|
||||
version: 3.0.4
|
||||
@@ -561,6 +564,9 @@ catalogs:
|
||||
semver-utils:
|
||||
specifier: ^1.1.4
|
||||
version: 1.1.4
|
||||
shell-quote:
|
||||
specifier: ^1.8.2
|
||||
version: 1.8.2
|
||||
signal-exit:
|
||||
specifier: ^3.0.7
|
||||
version: 3.0.7
|
||||
@@ -7728,9 +7734,15 @@ importers:
|
||||
'@rushstack/worker-pool':
|
||||
specifier: 'catalog:'
|
||||
version: 0.4.9(@types/node@22.5.3)
|
||||
is-windows:
|
||||
specifier: 'catalog:'
|
||||
version: 1.0.2
|
||||
load-json-file:
|
||||
specifier: 'catalog:'
|
||||
version: 6.2.0
|
||||
shell-quote:
|
||||
specifier: 'catalog:'
|
||||
version: 1.8.2
|
||||
devDependencies:
|
||||
'@pnpm/logger':
|
||||
specifier: workspace:*
|
||||
@@ -7741,6 +7753,12 @@ importers:
|
||||
'@pnpm/worker':
|
||||
specifier: workspace:*
|
||||
version: 'link:'
|
||||
'@types/is-windows':
|
||||
specifier: 'catalog:'
|
||||
version: 1.0.2
|
||||
'@types/shell-quote':
|
||||
specifier: 'catalog:'
|
||||
version: 1.7.5
|
||||
|
||||
workspace/filter-packages-from-dir:
|
||||
dependencies:
|
||||
@@ -9387,6 +9405,9 @@ packages:
|
||||
'@types/semver@7.5.8':
|
||||
resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
|
||||
|
||||
'@types/shell-quote@1.7.5':
|
||||
resolution: {integrity: sha512-+UE8GAGRPbJVQDdxi16dgadcBfQ+KG2vgZhV1+3A1XmHbmwcdwhCUwIdy+d3pAGrbvgRoVSjeI9vOWyq376Yzw==}
|
||||
|
||||
'@types/signal-exit@3.0.4':
|
||||
resolution: {integrity: sha512-e7EUPfU9afHyWc5CXtlqbvVHEshrb05uPlDCenWIbMgtWoFrTuTDVYNLKk6o4X2/4oHTfNqrJX/vaJ3uBhtXTg==}
|
||||
|
||||
@@ -13511,6 +13532,10 @@ packages:
|
||||
shell-quote@1.8.1:
|
||||
resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==}
|
||||
|
||||
shell-quote@1.8.2:
|
||||
resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
shelljs@0.8.5:
|
||||
resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -16408,6 +16433,8 @@ snapshots:
|
||||
|
||||
'@types/semver@7.5.8': {}
|
||||
|
||||
'@types/shell-quote@1.7.5': {}
|
||||
|
||||
'@types/signal-exit@3.0.4': {}
|
||||
|
||||
'@types/sinon@10.0.20':
|
||||
@@ -21248,6 +21275,8 @@ snapshots:
|
||||
|
||||
shell-quote@1.8.1: {}
|
||||
|
||||
shell-quote@1.8.2: {}
|
||||
|
||||
shelljs@0.8.5:
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
|
||||
@@ -87,6 +87,7 @@ catalog:
|
||||
"@types/semver": 7.5.3
|
||||
"@types/signal-exit": ^3.0.4
|
||||
"@types/sinon": ^10.0.20
|
||||
"@types/shell-quote": ^1.7.5
|
||||
"@types/ssri": ^7.1.5
|
||||
"@types/tar": ^6.1.13
|
||||
"@types/tar-stream": ^2.2.3
|
||||
@@ -226,6 +227,7 @@ catalog:
|
||||
semver-range-intersect: ^0.3.1
|
||||
semver-utils: ^1.1.4
|
||||
semver: ^7.6.2
|
||||
shell-quote: ^1.8.2
|
||||
signal-exit: ^3.0.7
|
||||
sinon: ^16.1.3
|
||||
sort-keys: ^4.2.0
|
||||
|
||||
@@ -42,12 +42,16 @@
|
||||
"@pnpm/store.cafs": "workspace:*",
|
||||
"@pnpm/symlink-dependency": "workspace:*",
|
||||
"@rushstack/worker-pool": "catalog:",
|
||||
"load-json-file": "catalog:"
|
||||
"is-windows": "catalog:",
|
||||
"load-json-file": "catalog:",
|
||||
"shell-quote": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@pnpm/logger": "workspace:*",
|
||||
"@pnpm/types": "workspace:*",
|
||||
"@pnpm/worker": "workspace:*"
|
||||
"@pnpm/worker": "workspace:*",
|
||||
"@types/is-windows": "catalog:",
|
||||
"@types/shell-quote": "catalog:"
|
||||
},
|
||||
"funding": "https://opencollective.com/pnpm",
|
||||
"exports": {
|
||||
|
||||
@@ -3,8 +3,11 @@ import path from 'path'
|
||||
import os from 'os'
|
||||
import { WorkerPool } from '@rushstack/worker-pool/lib/WorkerPool'
|
||||
import { PnpmError } from '@pnpm/error'
|
||||
import { execSync } from 'child_process'
|
||||
import isWindows from 'is-windows'
|
||||
import { type PackageFilesIndex } from '@pnpm/store.cafs'
|
||||
import { type DependencyManifest } from '@pnpm/types'
|
||||
import { quote as shellQuote } from 'shell-quote'
|
||||
import {
|
||||
type TarballExtractMessage,
|
||||
type AddDirToStoreMessage,
|
||||
@@ -217,7 +220,8 @@ export async function symlinkAllModules (
|
||||
localWorker.once('message', ({ status, error, value }: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
workerPool!.checkinWorker(localWorker)
|
||||
if (status === 'error') {
|
||||
reject(new PnpmError(error.code ?? 'SYMLINK_FAILED', error.message as string))
|
||||
const hint = opts.deps?.[0]?.modules != null ? createErrorHint(error, opts.deps[0].modules) : undefined
|
||||
reject(new PnpmError(error.code ?? 'SYMLINK_FAILED', error.message as string, { hint }))
|
||||
return
|
||||
}
|
||||
resolve(value)
|
||||
@@ -229,6 +233,28 @@ export async function symlinkAllModules (
|
||||
})
|
||||
}
|
||||
|
||||
function createErrorHint (err: Error, checkedDir: string): string | undefined {
|
||||
if ('code' in err && err.code === 'EISDIR' && isWindows()) {
|
||||
const checkedDrive = `${checkedDir.split(':')[0]}:`
|
||||
if (isDriveExFat(checkedDrive)) {
|
||||
return `The "${checkedDrive}" drive is exFAT, which does not support symlinks. This will cause installation to fail. You can set the node-linker to "hoisted" to avoid this issue.`
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
// In Windows system exFAT drive, symlink will result in error.
|
||||
function isDriveExFat (drive: string): boolean {
|
||||
try {
|
||||
const output = execSync(`wmic logicaldisk where ${shellQuote([`DeviceID='${drive}'`])} get FileSystem`).toString()
|
||||
const lines = output.trim().split('\n')
|
||||
const name = lines.length > 1 ? lines[1].trim() : ''
|
||||
return name === 'exFAT'
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export async function hardLinkDir (src: string, destDirs: string[]): Promise<void> {
|
||||
if (!workerPool) {
|
||||
workerPool = createTarballWorkerPool()
|
||||
|
||||
Reference in New Issue
Block a user