mirror of
https://github.com/pnpm/pnpm.git
synced 2026-07-25 15:07:06 -04:00
fix(env): use hard links instead of symlinks on Windows (#6405)
close #4315
This commit is contained in:
6
.changeset/late-laws-approve.md
Normal file
6
.changeset/late-laws-approve.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-env": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Use hard links to link the node executable on Windows machines [#4315](https://github.com/pnpm/pnpm/issues/4315).
|
||||
3
env/plugin-commands-env/package.json
vendored
3
env/plugin-commands-env/package.json
vendored
@@ -41,9 +41,11 @@
|
||||
"@pnpm/store-path": "workspace:*",
|
||||
"@zkochan/cmd-shim": "^6.0.0",
|
||||
"@zkochan/rimraf": "^2.1.2",
|
||||
"is-windows": "^1.0.2",
|
||||
"load-json-file": "^6.2.0",
|
||||
"render-help": "^1.0.3",
|
||||
"semver": "^7.4.0",
|
||||
"symlink-dir": "^5.1.1",
|
||||
"write-json-file": "^4.3.0"
|
||||
},
|
||||
"funding": "https://opencollective.com/pnpm",
|
||||
@@ -51,6 +53,7 @@
|
||||
"@pnpm/plugin-commands-env": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@types/adm-zip": "^0.5.0",
|
||||
"@types/is-windows": "^1.0.0",
|
||||
"@types/semver": "7.3.13",
|
||||
"adm-zip": "^0.5.10",
|
||||
"execa": "npm:safe-execa@0.1.2",
|
||||
|
||||
16
env/plugin-commands-env/src/envUse.ts
vendored
16
env/plugin-commands-env/src/envUse.ts
vendored
@@ -4,10 +4,12 @@ import { PnpmError } from '@pnpm/error'
|
||||
import { createFetchFromRegistry } from '@pnpm/fetch'
|
||||
import { resolveNodeVersion } from '@pnpm/node.resolver'
|
||||
import cmdShim from '@zkochan/cmd-shim'
|
||||
import isWindows from 'is-windows'
|
||||
import symlinkDir from 'symlink-dir'
|
||||
import { getNodeDir, type NvmNodeCommandOptions } from './node'
|
||||
import { getNodeMirror } from './getNodeMirror'
|
||||
import { parseNodeEditionSpecifier } from './parseNodeEditionSpecifier'
|
||||
import { getNodeExecPathInBinDir, getNodeExecPathInNodeDir } from './utils'
|
||||
import { CURRENT_NODE_DIRNAME, getNodeExecPathInBinDir, getNodeExecPathInNodeDir } from './utils'
|
||||
|
||||
export async function envUse (opts: NvmNodeCommandOptions, params: string[]) {
|
||||
if (!opts.global) {
|
||||
@@ -27,10 +29,11 @@ export async function envUse (opts: NvmNodeCommandOptions, params: string[]) {
|
||||
})
|
||||
const src = getNodeExecPathInNodeDir(nodeDir)
|
||||
const dest = getNodeExecPathInBinDir(opts.bin)
|
||||
await symlinkDir(nodeDir, path.join(opts.pnpmHomeDir, CURRENT_NODE_DIRNAME))
|
||||
try {
|
||||
await fs.unlink(dest)
|
||||
} catch (err) {}
|
||||
await fs.symlink(src, dest, 'file')
|
||||
await symlinkOrHardLink(src, dest)
|
||||
try {
|
||||
let npmDir = nodeDir
|
||||
if (process.platform !== 'win32') {
|
||||
@@ -52,3 +55,12 @@ export async function envUse (opts: NvmNodeCommandOptions, params: string[]) {
|
||||
return `Node.js ${nodeVersion as string} is activated
|
||||
${dest} -> ${src}`
|
||||
}
|
||||
|
||||
// On Windows, symlinks only work with developer mode enabled
|
||||
// or with admin permissions. So it is better to use hard links on Windows.
|
||||
async function symlinkOrHardLink (existingPath: string, newPath: string) {
|
||||
if (isWindows()) {
|
||||
return fs.link(existingPath, newPath)
|
||||
}
|
||||
return fs.symlink(existingPath, newPath, 'file')
|
||||
}
|
||||
|
||||
11
env/plugin-commands-env/src/utils.ts
vendored
11
env/plugin-commands-env/src/utils.ts
vendored
@@ -1,15 +1,18 @@
|
||||
import { promises as fs } from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
export const CURRENT_NODE_DIRNAME = 'nodejs_current'
|
||||
|
||||
export async function getNodeExecPathAndTargetDir (pnpmHomeDir: string) {
|
||||
const nodePath = getNodeExecPathInBinDir(pnpmHomeDir)
|
||||
let nodeLink: string | undefined
|
||||
const nodeCurrentDirLink = path.join(pnpmHomeDir, CURRENT_NODE_DIRNAME)
|
||||
let nodeCurrentDir: string | undefined
|
||||
try {
|
||||
nodeLink = await fs.readlink(nodePath)
|
||||
nodeCurrentDir = await fs.readlink(nodeCurrentDirLink)
|
||||
} catch (err) {
|
||||
nodeLink = undefined
|
||||
nodeCurrentDir = undefined
|
||||
}
|
||||
return { nodePath, nodeLink }
|
||||
return { nodePath, nodeLink: nodeCurrentDir ? getNodeExecPathInNodeDir(nodeCurrentDir) : undefined }
|
||||
}
|
||||
|
||||
export function getNodeExecPathInBinDir (pnpmHomeDir: string) {
|
||||
|
||||
22
pnpm-lock.yaml
generated
22
pnpm-lock.yaml
generated
@@ -855,6 +855,9 @@ importers:
|
||||
'@zkochan/rimraf':
|
||||
specifier: ^2.1.2
|
||||
version: 2.1.2
|
||||
is-windows:
|
||||
specifier: ^1.0.2
|
||||
version: 1.0.2
|
||||
load-json-file:
|
||||
specifier: ^6.2.0
|
||||
version: 6.2.0
|
||||
@@ -864,6 +867,9 @@ importers:
|
||||
semver:
|
||||
specifier: ^7.4.0
|
||||
version: 7.4.0
|
||||
symlink-dir:
|
||||
specifier: ^5.1.1
|
||||
version: 5.1.1
|
||||
write-json-file:
|
||||
specifier: ^4.3.0
|
||||
version: 4.3.0
|
||||
@@ -877,6 +883,9 @@ importers:
|
||||
'@types/adm-zip':
|
||||
specifier: ^0.5.0
|
||||
version: 0.5.0
|
||||
'@types/is-windows':
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0
|
||||
'@types/semver':
|
||||
specifier: 7.3.13
|
||||
version: 7.3.13
|
||||
@@ -8804,7 +8813,7 @@ packages:
|
||||
/@types/byline@4.2.33:
|
||||
resolution: {integrity: sha512-LJYez7wrWcJQQDknqZtrZuExMGP0IXmPl1rOOGDqLbu+H7UNNRfKNuSxCBcQMLH1EfjeWidLedC/hCc5dDfBog==}
|
||||
dependencies:
|
||||
'@types/node': 18.15.11
|
||||
'@types/node': 14.18.42
|
||||
dev: true
|
||||
|
||||
/@types/cacheable-request@6.0.3:
|
||||
@@ -8812,7 +8821,7 @@ packages:
|
||||
dependencies:
|
||||
'@types/http-cache-semantics': 4.0.1
|
||||
'@types/keyv': 3.1.4
|
||||
'@types/node': 18.15.11
|
||||
'@types/node': 14.18.42
|
||||
'@types/responselike': 1.0.0
|
||||
|
||||
/@types/concat-stream@2.0.0:
|
||||
@@ -8840,7 +8849,7 @@ packages:
|
||||
resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==}
|
||||
dependencies:
|
||||
'@types/minimatch': 5.1.2
|
||||
'@types/node': 18.15.11
|
||||
'@types/node': 14.18.42
|
||||
dev: true
|
||||
|
||||
/@types/graceful-fs@4.1.6:
|
||||
@@ -8914,7 +8923,7 @@ packages:
|
||||
/@types/keyv@3.1.4:
|
||||
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
|
||||
dependencies:
|
||||
'@types/node': 18.15.11
|
||||
'@types/node': 14.18.42
|
||||
|
||||
/@types/lodash@4.14.181:
|
||||
resolution: {integrity: sha512-n3tyKthHJbkiWhDZs3DkhkCzt2MexYHXlX0td5iMplyfwketaOeKboEVBqzceH7juqvEg3q5oUoBFxSLu7zFag==}
|
||||
@@ -8957,7 +8966,6 @@ packages:
|
||||
|
||||
/@types/node@14.18.42:
|
||||
resolution: {integrity: sha512-xefu+RBie4xWlK8hwAzGh3npDz/4VhF6icY/shU+zv/1fNn+ZVG7T7CRwe9LId9sAYRPxI+59QBPuKL3WpyGRg==}
|
||||
dev: true
|
||||
|
||||
/@types/node@18.15.11:
|
||||
resolution: {integrity: sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==}
|
||||
@@ -8994,7 +9002,7 @@ packages:
|
||||
/@types/responselike@1.0.0:
|
||||
resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==}
|
||||
dependencies:
|
||||
'@types/node': 18.15.11
|
||||
'@types/node': 14.18.42
|
||||
|
||||
/@types/retry@0.12.2:
|
||||
resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==}
|
||||
@@ -13501,7 +13509,7 @@ packages:
|
||||
jws: 3.2.2
|
||||
lodash: 4.17.21
|
||||
ms: 2.1.3
|
||||
semver: 7.3.8
|
||||
semver: 7.4.0
|
||||
|
||||
/jsprim@1.4.2:
|
||||
resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==}
|
||||
|
||||
Reference in New Issue
Block a user