Skip to content

Commit

Permalink
fix(env): use hard links instead of symlinks on Windows (#6405)
Browse files Browse the repository at this point in the history
close #4315
  • Loading branch information
zkochan committed Apr 16, 2023
1 parent 8e7a86d commit 49b15ac
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 13 deletions.
6 changes: 6 additions & 0 deletions .changeset/late-laws-approve.md
@@ -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 changes: 3 additions & 0 deletions env/plugin-commands-env/package.json
Expand Up @@ -41,16 +41,19 @@
"@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",
"devDependencies": {
"@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",
Expand Down
16 changes: 14 additions & 2 deletions env/plugin-commands-env/src/envUse.ts
Expand Up @@ -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) {
Expand All @@ -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') {
Expand All @@ -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 changes: 7 additions & 4 deletions env/plugin-commands-env/src/utils.ts
@@ -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) {
Expand Down
22 changes: 15 additions & 7 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 49b15ac

Please sign in to comment.