@pnpm/bins.linker 1100.0.13 → 1100.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +46 -2
- package/package.json +11 -11
package/lib/index.js
CHANGED
|
@@ -231,7 +231,7 @@ async function linkBin(cmd, binsDir, opts) {
|
|
|
231
231
|
if (opts?.preferSymlinkedExecutables && !IS_WINDOWS && cmd.nodeExecPath == null) {
|
|
232
232
|
try {
|
|
233
233
|
await symlinkDir(cmd.path, externalBinPath);
|
|
234
|
-
await
|
|
234
|
+
await ensureExecutable(cmd.path, 0o755);
|
|
235
235
|
}
|
|
236
236
|
catch (err) { // eslint-disable-line
|
|
237
237
|
if (err.code !== 'ENOENT' && err.code !== 'EISDIR') {
|
|
@@ -280,7 +280,51 @@ async function linkBin(cmd, binsDir, opts) {
|
|
|
280
280
|
// ensure that bin are executable and not containing
|
|
281
281
|
// windows line-endings(CRLF) on the hashbang line
|
|
282
282
|
if (EXECUTABLE_SHEBANG_SUPPORTED) {
|
|
283
|
-
await
|
|
283
|
+
await ensureExecutable(cmd.path, 0o755);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// `fixBin` chmods the bin's source file (which lives inside the store) to make
|
|
287
|
+
// it executable and rewrites a Windows CRLF shebang to LF. Under the global
|
|
288
|
+
// virtual store that source is `{storeDir}/links/...`, so on a read-only store
|
|
289
|
+
// (e.g. `frozenStore`) the chmod is refused — with EPERM/EACCES when the file is
|
|
290
|
+
// owned but permissions forbid it, or EROFS on a genuinely read-only filesystem
|
|
291
|
+
// (Nix store, RO bind mount, OCI layer). A complete seed already ships its bins
|
|
292
|
+
// executable and shebang-normalized by the writable seed-build, so that work is
|
|
293
|
+
// redundant: treat an already-correct target as a no-op, keeping bin-linking
|
|
294
|
+
// write-free (see building/during-install: "Bin-linking reuses existing symlinks
|
|
295
|
+
// write-free"). A non-executable bin — or one still carrying a CRLF shebang that
|
|
296
|
+
// `fixBin` could not rewrite here — still throws, because that means the seed is
|
|
297
|
+
// broken and the bin would not run.
|
|
298
|
+
async function ensureExecutable(file, mode) {
|
|
299
|
+
try {
|
|
300
|
+
await fixBin(file, mode);
|
|
301
|
+
}
|
|
302
|
+
catch (err) { // eslint-disable-line
|
|
303
|
+
if (err.code === 'EPERM' || err.code === 'EACCES' || err.code === 'EROFS') {
|
|
304
|
+
const stat = await fs.stat(file).catch(() => undefined);
|
|
305
|
+
if (stat != null && (stat.mode & 0o111) !== 0 && !(await hasWindowsShebang(file)))
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
throw err;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// Detects a `#!`-shebang line terminated by CRLF, which fails to execute on
|
|
312
|
+
// POSIX. Mirrors bin-links' own fix-bin detection so a chmod failure on a
|
|
313
|
+
// read-only store is only swallowed when the bin is genuinely already correct.
|
|
314
|
+
async function hasWindowsShebang(file) {
|
|
315
|
+
const fh = await fs.open(file, 'r').catch(() => undefined);
|
|
316
|
+
if (fh == null)
|
|
317
|
+
return false;
|
|
318
|
+
try {
|
|
319
|
+
const buf = Buffer.alloc(2048);
|
|
320
|
+
await fh.read(buf, 0, 2048, 0);
|
|
321
|
+
return buf[0] === 0x23 /* # */ && buf[1] === 0x21 /* ! */ && /^#![^\n]+\r\n/.test(buf.toString());
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
finally {
|
|
327
|
+
await fh.close().catch(() => { });
|
|
284
328
|
}
|
|
285
329
|
}
|
|
286
330
|
function getExeExtension() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/bins.linker",
|
|
3
|
-
"version": "1100.0.
|
|
3
|
+
"version": "1100.0.14",
|
|
4
4
|
"description": "Link bins to node_modules/.bin",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -28,28 +28,28 @@
|
|
|
28
28
|
"!*.map"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@zkochan/cmd-shim": "^9.0.
|
|
31
|
+
"@zkochan/cmd-shim": "^9.0.6",
|
|
32
32
|
"@zkochan/rimraf": "^4.0.0",
|
|
33
33
|
"bin-links": "^6.0.2",
|
|
34
34
|
"is-subdir": "^2.0.0",
|
|
35
35
|
"is-windows": "^1.0.2",
|
|
36
36
|
"normalize-path": "^3.0.0",
|
|
37
37
|
"ramda": "npm:@pnpm/ramda@0.28.1",
|
|
38
|
-
"semver": "^7.8.
|
|
38
|
+
"semver": "^7.8.4",
|
|
39
39
|
"symlink-dir": "^10.0.1",
|
|
40
|
-
"@pnpm/bins.resolver": "1100.0.
|
|
41
|
-
"@pnpm/pkg-manifest.
|
|
40
|
+
"@pnpm/bins.resolver": "1100.0.8",
|
|
41
|
+
"@pnpm/pkg-manifest.utils": "1100.2.5",
|
|
42
42
|
"@pnpm/error": "1100.0.0",
|
|
43
43
|
"@pnpm/fs.read-modules-dir": "1100.0.1",
|
|
44
|
-
"@pnpm/
|
|
45
|
-
"@pnpm/
|
|
46
|
-
"@pnpm/workspace.project-manifest-reader": "1100.0.
|
|
44
|
+
"@pnpm/types": "1101.3.2",
|
|
45
|
+
"@pnpm/pkg-manifest.reader": "1100.0.8",
|
|
46
|
+
"@pnpm/workspace.project-manifest-reader": "1100.0.13"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"@pnpm/logger": "^
|
|
49
|
+
"@pnpm/logger": "^1100.0.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@jest/globals": "30.
|
|
52
|
+
"@jest/globals": "30.4.1",
|
|
53
53
|
"@types/is-windows": "^1.0.2",
|
|
54
54
|
"@types/node": "^22.19.19",
|
|
55
55
|
"@types/normalize-path": "^3.0.2",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@types/semver": "7.7.1",
|
|
58
58
|
"cmd-extension": "^2.0.0",
|
|
59
59
|
"tempy": "3.0.0",
|
|
60
|
-
"@pnpm/bins.linker": "1100.0.
|
|
60
|
+
"@pnpm/bins.linker": "1100.0.14",
|
|
61
61
|
"@pnpm/logger": "1100.0.0",
|
|
62
62
|
"@pnpm/test-fixtures": "1100.0.0"
|
|
63
63
|
},
|