diff --git a/node_modules/.gitignore b/node_modules/.gitignore index fba7383d33410..9ae4ee04339a1 100644 --- a/node_modules/.gitignore +++ b/node_modules/.gitignore @@ -18,6 +18,11 @@ !/@npmcli/agent !/@npmcli/fs !/@npmcli/git +!/@npmcli/git/node_modules/ +/@npmcli/git/node_modules/* +!/@npmcli/git/node_modules/@npmcli/ +/@npmcli/git/node_modules/@npmcli/* +!/@npmcli/git/node_modules/@npmcli/promise-spawn !/@npmcli/installed-package-contents !/@npmcli/map-workspaces !/@npmcli/map-workspaces/node_modules/ @@ -34,7 +39,6 @@ !/@npmcli/package-json/node_modules/@npmcli/ /@npmcli/package-json/node_modules/@npmcli/* !/@npmcli/package-json/node_modules/@npmcli/git -!/@npmcli/package-json/node_modules/@npmcli/promise-spawn !/@npmcli/package-json/node_modules/hosted-git-info !/@npmcli/package-json/node_modules/ini !/@npmcli/package-json/node_modules/isexe @@ -48,6 +52,10 @@ !/@npmcli/package-json/node_modules/validate-npm-package-name !/@npmcli/package-json/node_modules/which !/@npmcli/promise-spawn +!/@npmcli/promise-spawn/node_modules/ +/@npmcli/promise-spawn/node_modules/* +!/@npmcli/promise-spawn/node_modules/isexe +!/@npmcli/promise-spawn/node_modules/which !/@npmcli/query !/@npmcli/redact !/@npmcli/run-script @@ -56,6 +64,7 @@ !/@npmcli/run-script/node_modules/@npmcli/ /@npmcli/run-script/node_modules/@npmcli/* !/@npmcli/run-script/node_modules/@npmcli/package-json +!/@npmcli/run-script/node_modules/@npmcli/promise-spawn !/@pkgjs/ /@pkgjs/* !/@pkgjs/parseargs @@ -194,6 +203,7 @@ !/pacote/node_modules/@npmcli/ /pacote/node_modules/@npmcli/* !/pacote/node_modules/@npmcli/package-json +!/pacote/node_modules/@npmcli/promise-spawn !/parse-conflict-json !/path-key !/path-scurry diff --git a/node_modules/@npmcli/package-json/node_modules/@npmcli/promise-spawn/LICENSE b/node_modules/@npmcli/git/node_modules/@npmcli/promise-spawn/LICENSE similarity index 100% rename from node_modules/@npmcli/package-json/node_modules/@npmcli/promise-spawn/LICENSE rename to node_modules/@npmcli/git/node_modules/@npmcli/promise-spawn/LICENSE diff --git a/node_modules/@npmcli/package-json/node_modules/@npmcli/promise-spawn/lib/escape.js b/node_modules/@npmcli/git/node_modules/@npmcli/promise-spawn/lib/escape.js similarity index 100% rename from node_modules/@npmcli/package-json/node_modules/@npmcli/promise-spawn/lib/escape.js rename to node_modules/@npmcli/git/node_modules/@npmcli/promise-spawn/lib/escape.js diff --git a/node_modules/@npmcli/package-json/node_modules/@npmcli/promise-spawn/lib/index.js b/node_modules/@npmcli/git/node_modules/@npmcli/promise-spawn/lib/index.js similarity index 100% rename from node_modules/@npmcli/package-json/node_modules/@npmcli/promise-spawn/lib/index.js rename to node_modules/@npmcli/git/node_modules/@npmcli/promise-spawn/lib/index.js diff --git a/node_modules/@npmcli/git/node_modules/@npmcli/promise-spawn/package.json b/node_modules/@npmcli/git/node_modules/@npmcli/promise-spawn/package.json new file mode 100644 index 0000000000000..1b633f84596d2 --- /dev/null +++ b/node_modules/@npmcli/git/node_modules/@npmcli/promise-spawn/package.json @@ -0,0 +1,50 @@ +{ + "name": "@npmcli/promise-spawn", + "version": "7.0.2", + "files": [ + "bin/", + "lib/" + ], + "main": "./lib/index.js", + "description": "spawn processes the way the npm cli likes to do", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/promise-spawn.git" + }, + "author": "GitHub Inc.", + "license": "ISC", + "scripts": { + "test": "tap", + "snap": "tap", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", + "lintfix": "npm run lint -- --fix", + "posttest": "npm run lint", + "postsnap": "npm run lintfix --", + "postlint": "template-oss-check", + "template-oss-apply": "template-oss-apply --force" + }, + "tap": { + "check-coverage": true, + "nyc-arg": [ + "--exclude", + "tap-snapshots/**" + ] + }, + "devDependencies": { + "@npmcli/eslint-config": "^4.0.0", + "@npmcli/template-oss": "4.22.0", + "spawk": "^1.7.1", + "tap": "^16.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + }, + "templateOSS": { + "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", + "version": "4.22.0", + "publish": true + }, + "dependencies": { + "which": "^4.0.0" + } +} diff --git a/node_modules/@npmcli/promise-spawn/node_modules/isexe/LICENSE b/node_modules/@npmcli/promise-spawn/node_modules/isexe/LICENSE new file mode 100644 index 0000000000000..c925dbe826b67 --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/isexe/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) 2016-2022 Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/index.js b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/index.js new file mode 100644 index 0000000000000..cefcb66b5c543 --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/index.js @@ -0,0 +1,46 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sync = exports.isexe = exports.posix = exports.win32 = void 0; +const posix = __importStar(require("./posix.js")); +exports.posix = posix; +const win32 = __importStar(require("./win32.js")); +exports.win32 = win32; +__exportStar(require("./options.js"), exports); +const platform = process.env._ISEXE_TEST_PLATFORM_ || process.platform; +const impl = platform === 'win32' ? win32 : posix; +/** + * Determine whether a path is executable on the current platform. + */ +exports.isexe = impl.isexe; +/** + * Synchronously determine whether a path is executable on the + * current platform. + */ +exports.sync = impl.sync; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/options.js b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/options.js new file mode 100644 index 0000000000000..0dfad0762cc32 --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/options.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=options.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/package.json b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/package.json new file mode 100644 index 0000000000000..5bbefffbabee3 --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/posix.js b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/posix.js new file mode 100644 index 0000000000000..3bc5e79d7007e --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/posix.js @@ -0,0 +1,67 @@ +"use strict"; +/** + * This is the Posix implementation of isexe, which uses the file + * mode and uid/gid values. + * + * @module + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sync = exports.isexe = void 0; +const fs_1 = require("fs"); +const promises_1 = require("fs/promises"); +/** + * Determine whether a path is executable according to the mode and + * current (or specified) user and group IDs. + */ +const isexe = async (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat(await (0, promises_1.stat)(path), options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +exports.isexe = isexe; +/** + * Synchronously determine whether a path is executable according to + * the mode and current (or specified) user and group IDs. + */ +const sync = (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat((0, fs_1.statSync)(path), options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +exports.sync = sync; +const checkStat = (stat, options) => stat.isFile() && checkMode(stat, options); +const checkMode = (stat, options) => { + const myUid = options.uid ?? process.getuid?.(); + const myGroups = options.groups ?? process.getgroups?.() ?? []; + const myGid = options.gid ?? process.getgid?.() ?? myGroups[0]; + if (myUid === undefined || myGid === undefined) { + throw new Error('cannot get uid or gid'); + } + const groups = new Set([myGid, ...myGroups]); + const mod = stat.mode; + const uid = stat.uid; + const gid = stat.gid; + const u = parseInt('100', 8); + const g = parseInt('010', 8); + const o = parseInt('001', 8); + const ug = u | g; + return !!(mod & o || + (mod & g && groups.has(gid)) || + (mod & u && uid === myUid) || + (mod & ug && myUid === 0)); +}; +//# sourceMappingURL=posix.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/win32.js b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/win32.js new file mode 100644 index 0000000000000..fa7a4d2f7d240 --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/cjs/win32.js @@ -0,0 +1,62 @@ +"use strict"; +/** + * This is the Windows implementation of isexe, which uses the file + * extension and PATHEXT setting. + * + * @module + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sync = exports.isexe = void 0; +const fs_1 = require("fs"); +const promises_1 = require("fs/promises"); +/** + * Determine whether a path is executable based on the file extension + * and PATHEXT environment variable (or specified pathExt option) + */ +const isexe = async (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat(await (0, promises_1.stat)(path), path, options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +exports.isexe = isexe; +/** + * Synchronously determine whether a path is executable based on the file + * extension and PATHEXT environment variable (or specified pathExt option) + */ +const sync = (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat((0, fs_1.statSync)(path), path, options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +exports.sync = sync; +const checkPathExt = (path, options) => { + const { pathExt = process.env.PATHEXT || '' } = options; + const peSplit = pathExt.split(';'); + if (peSplit.indexOf('') !== -1) { + return true; + } + for (let i = 0; i < peSplit.length; i++) { + const p = peSplit[i].toLowerCase(); + const ext = path.substring(path.length - p.length).toLowerCase(); + if (p && ext === p) { + return true; + } + } + return false; +}; +const checkStat = (stat, path, options) => stat.isFile() && checkPathExt(path, options); +//# sourceMappingURL=win32.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/index.js b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/index.js new file mode 100644 index 0000000000000..1e309acd7355e --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/index.js @@ -0,0 +1,16 @@ +import * as posix from './posix.js'; +import * as win32 from './win32.js'; +export * from './options.js'; +export { win32, posix }; +const platform = process.env._ISEXE_TEST_PLATFORM_ || process.platform; +const impl = platform === 'win32' ? win32 : posix; +/** + * Determine whether a path is executable on the current platform. + */ +export const isexe = impl.isexe; +/** + * Synchronously determine whether a path is executable on the + * current platform. + */ +export const sync = impl.sync; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/options.js b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/options.js new file mode 100644 index 0000000000000..e9ded40bd5b2c --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/options.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=options.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/package.json b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/package.json new file mode 100644 index 0000000000000..3dbc1ca591c05 --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/posix.js b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/posix.js new file mode 100644 index 0000000000000..c453776c0452f --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/posix.js @@ -0,0 +1,62 @@ +/** + * This is the Posix implementation of isexe, which uses the file + * mode and uid/gid values. + * + * @module + */ +import { statSync } from 'fs'; +import { stat } from 'fs/promises'; +/** + * Determine whether a path is executable according to the mode and + * current (or specified) user and group IDs. + */ +export const isexe = async (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat(await stat(path), options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +/** + * Synchronously determine whether a path is executable according to + * the mode and current (or specified) user and group IDs. + */ +export const sync = (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat(statSync(path), options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +const checkStat = (stat, options) => stat.isFile() && checkMode(stat, options); +const checkMode = (stat, options) => { + const myUid = options.uid ?? process.getuid?.(); + const myGroups = options.groups ?? process.getgroups?.() ?? []; + const myGid = options.gid ?? process.getgid?.() ?? myGroups[0]; + if (myUid === undefined || myGid === undefined) { + throw new Error('cannot get uid or gid'); + } + const groups = new Set([myGid, ...myGroups]); + const mod = stat.mode; + const uid = stat.uid; + const gid = stat.gid; + const u = parseInt('100', 8); + const g = parseInt('010', 8); + const o = parseInt('001', 8); + const ug = u | g; + return !!(mod & o || + (mod & g && groups.has(gid)) || + (mod & u && uid === myUid) || + (mod & ug && myUid === 0)); +}; +//# sourceMappingURL=posix.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/win32.js b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/win32.js new file mode 100644 index 0000000000000..a354ee2a5115c --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/isexe/dist/mjs/win32.js @@ -0,0 +1,57 @@ +/** + * This is the Windows implementation of isexe, which uses the file + * extension and PATHEXT setting. + * + * @module + */ +import { statSync } from 'fs'; +import { stat } from 'fs/promises'; +/** + * Determine whether a path is executable based on the file extension + * and PATHEXT environment variable (or specified pathExt option) + */ +export const isexe = async (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat(await stat(path), path, options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +/** + * Synchronously determine whether a path is executable based on the file + * extension and PATHEXT environment variable (or specified pathExt option) + */ +export const sync = (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat(statSync(path), path, options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +const checkPathExt = (path, options) => { + const { pathExt = process.env.PATHEXT || '' } = options; + const peSplit = pathExt.split(';'); + if (peSplit.indexOf('') !== -1) { + return true; + } + for (let i = 0; i < peSplit.length; i++) { + const p = peSplit[i].toLowerCase(); + const ext = path.substring(path.length - p.length).toLowerCase(); + if (p && ext === p) { + return true; + } + } + return false; +}; +const checkStat = (stat, path, options) => stat.isFile() && checkPathExt(path, options); +//# sourceMappingURL=win32.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/promise-spawn/node_modules/isexe/package.json b/node_modules/@npmcli/promise-spawn/node_modules/isexe/package.json new file mode 100644 index 0000000000000..a0e2cd04bfdbf --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/isexe/package.json @@ -0,0 +1,96 @@ +{ + "name": "isexe", + "version": "3.1.1", + "description": "Minimal module to check if a file is executable.", + "main": "./dist/cjs/index.js", + "module": "./dist/mjs/index.js", + "types": "./dist/cjs/index.js", + "files": [ + "dist" + ], + "exports": { + ".": { + "import": { + "types": "./dist/mjs/index.d.ts", + "default": "./dist/mjs/index.js" + }, + "require": { + "types": "./dist/cjs/index.d.ts", + "default": "./dist/cjs/index.js" + } + }, + "./posix": { + "import": { + "types": "./dist/mjs/posix.d.ts", + "default": "./dist/mjs/posix.js" + }, + "require": { + "types": "./dist/cjs/posix.d.ts", + "default": "./dist/cjs/posix.js" + } + }, + "./win32": { + "import": { + "types": "./dist/mjs/win32.d.ts", + "default": "./dist/mjs/win32.js" + }, + "require": { + "types": "./dist/cjs/win32.d.ts", + "default": "./dist/cjs/win32.js" + } + }, + "./package.json": "./package.json" + }, + "devDependencies": { + "@types/node": "^20.4.5", + "@types/tap": "^15.0.8", + "c8": "^8.0.1", + "mkdirp": "^0.5.1", + "prettier": "^2.8.8", + "rimraf": "^2.5.0", + "sync-content": "^1.0.2", + "tap": "^16.3.8", + "ts-node": "^10.9.1", + "typedoc": "^0.24.8", + "typescript": "^5.1.6" + }, + "scripts": { + "preversion": "npm test", + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags", + "prepare": "tsc -p tsconfig/cjs.json && tsc -p tsconfig/esm.json && bash ./scripts/fixup.sh", + "pretest": "npm run prepare", + "presnap": "npm run prepare", + "test": "c8 tap", + "snap": "c8 tap", + "format": "prettier --write . --loglevel warn --ignore-path ../../.prettierignore --cache", + "typedoc": "typedoc --tsconfig tsconfig/esm.json ./src/*.ts" + }, + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "license": "ISC", + "tap": { + "coverage": false, + "node-arg": [ + "--enable-source-maps", + "--no-warnings", + "--loader", + "ts-node/esm" + ], + "ts": false + }, + "prettier": { + "semi": false, + "printWidth": 75, + "tabWidth": 2, + "useTabs": false, + "singleQuote": true, + "jsxSingleQuote": false, + "bracketSameLine": true, + "arrowParens": "avoid", + "endOfLine": "lf" + }, + "repository": "https://github.com/isaacs/isexe", + "engines": { + "node": ">=16" + } +} diff --git a/node_modules/@npmcli/promise-spawn/node_modules/which/LICENSE b/node_modules/@npmcli/promise-spawn/node_modules/which/LICENSE new file mode 100644 index 0000000000000..19129e315fe59 --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/which/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/@npmcli/promise-spawn/node_modules/which/bin/which.js b/node_modules/@npmcli/promise-spawn/node_modules/which/bin/which.js new file mode 100755 index 0000000000000..6df16f21acf93 --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/which/bin/which.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const which = require('../lib') +const argv = process.argv.slice(2) + +const usage = (err) => { + if (err) { + console.error(`which: ${err}`) + } + console.error('usage: which [-as] program ...') + process.exit(1) +} + +if (!argv.length) { + return usage() +} + +let dashdash = false +const [commands, flags] = argv.reduce((acc, arg) => { + if (dashdash || arg === '--') { + dashdash = true + return acc + } + + if (!/^-/.test(arg)) { + acc[0].push(arg) + return acc + } + + for (const flag of arg.slice(1).split('')) { + if (flag === 's') { + acc[1].silent = true + } else if (flag === 'a') { + acc[1].all = true + } else { + usage(`illegal option -- ${flag}`) + } + } + + return acc +}, [[], {}]) + +for (const command of commands) { + try { + const res = which.sync(command, { all: flags.all }) + if (!flags.silent) { + console.log([].concat(res).join('\n')) + } + } catch (err) { + process.exitCode = 1 + } +} diff --git a/node_modules/@npmcli/promise-spawn/node_modules/which/lib/index.js b/node_modules/@npmcli/promise-spawn/node_modules/which/lib/index.js new file mode 100644 index 0000000000000..2fd358baf888f --- /dev/null +++ b/node_modules/@npmcli/promise-spawn/node_modules/which/lib/index.js @@ -0,0 +1,111 @@ +const { isexe, sync: isexeSync } = require('isexe') +const { join, delimiter, sep, posix } = require('path') + +const isWindows = process.platform === 'win32' + +// used to check for slashed in commands passed in. always checks for the posix +// seperator on all platforms, and checks for the current separator when not on +// a posix platform. don't use the isWindows check for this since that is mocked +// in tests but we still need the code to actually work when called. that is also +// why it is ignored from coverage. +/* istanbul ignore next */ +const rSlash = new RegExp(`[${posix.sep}${sep === posix.sep ? '' : sep}]`.replace(/(\\)/g, '\\$1')) +const rRel = new RegExp(`^\\.${rSlash.source}`) + +const getNotFoundError = (cmd) => + Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' }) + +const getPathInfo = (cmd, { + path: optPath = process.env.PATH, + pathExt: optPathExt = process.env.PATHEXT, + delimiter: optDelimiter = delimiter, +}) => { + // If it has a slash, then we don't bother searching the pathenv. + // just check the file itself, and that's it. + const pathEnv = cmd.match(rSlash) ? [''] : [ + // windows always checks the cwd first + ...(isWindows ? [process.cwd()] : []), + ...(optPath || /* istanbul ignore next: very unusual */ '').split(optDelimiter), + ] + + if (isWindows) { + const pathExtExe = optPathExt || + ['.EXE', '.CMD', '.BAT', '.COM'].join(optDelimiter) + const pathExt = pathExtExe.split(optDelimiter).flatMap((item) => [item, item.toLowerCase()]) + if (cmd.includes('.') && pathExt[0] !== '') { + pathExt.unshift('') + } + return { pathEnv, pathExt, pathExtExe } + } + + return { pathEnv, pathExt: [''] } +} + +const getPathPart = (raw, cmd) => { + const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw + const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : '' + return prefix + join(pathPart, cmd) +} + +const which = async (cmd, opt = {}) => { + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + for (const envPart of pathEnv) { + const p = getPathPart(envPart, cmd) + + for (const ext of pathExt) { + const withExt = p + ext + const is = await isexe(withExt, { pathExt: pathExtExe, ignoreErrors: true }) + if (is) { + if (!opt.all) { + return withExt + } + found.push(withExt) + } + } + } + + if (opt.all && found.length) { + return found + } + + if (opt.nothrow) { + return null + } + + throw getNotFoundError(cmd) +} + +const whichSync = (cmd, opt = {}) => { + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + for (const pathEnvPart of pathEnv) { + const p = getPathPart(pathEnvPart, cmd) + + for (const ext of pathExt) { + const withExt = p + ext + const is = isexeSync(withExt, { pathExt: pathExtExe, ignoreErrors: true }) + if (is) { + if (!opt.all) { + return withExt + } + found.push(withExt) + } + } + } + + if (opt.all && found.length) { + return found + } + + if (opt.nothrow) { + return null + } + + throw getNotFoundError(cmd) +} + +module.exports = which +which.sync = whichSync diff --git a/node_modules/@npmcli/package-json/node_modules/@npmcli/promise-spawn/package.json b/node_modules/@npmcli/promise-spawn/node_modules/which/package.json similarity index 72% rename from node_modules/@npmcli/package-json/node_modules/@npmcli/promise-spawn/package.json rename to node_modules/@npmcli/promise-spawn/node_modules/which/package.json index 9914063f85156..94184233c61c4 100644 --- a/node_modules/@npmcli/package-json/node_modules/@npmcli/promise-spawn/package.json +++ b/node_modules/@npmcli/promise-spawn/node_modules/which/package.json @@ -1,29 +1,39 @@ { - "name": "@npmcli/promise-spawn", - "version": "8.0.1", - "files": [ - "bin/", - "lib/" - ], - "main": "./lib/index.js", - "description": "spawn processes the way the npm cli likes to do", + "author": "GitHub Inc.", + "name": "which", + "description": "Like which(1) unix command. Find the first instance of an executable in the PATH.", + "version": "5.0.0", "repository": { "type": "git", - "url": "git+https://github.com/npm/promise-spawn.git" + "url": "git+https://github.com/npm/node-which.git" + }, + "main": "lib/index.js", + "bin": { + "node-which": "./bin/which.js" }, - "author": "GitHub Inc.", "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "devDependencies": { + "@npmcli/eslint-config": "^5.0.0", + "@npmcli/template-oss": "4.23.3", + "tap": "^16.3.0" + }, "scripts": { "test": "tap", - "snap": "tap", "lint": "npm run eslint", - "lintfix": "npm run eslint -- --fix", - "posttest": "npm run lint", - "postsnap": "npm run lintfix --", "postlint": "template-oss-check", "template-oss-apply": "template-oss-apply --force", + "lintfix": "npm run eslint -- --fix", + "snap": "tap", + "posttest": "npm run lint", "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"" }, + "files": [ + "bin/", + "lib/" + ], "tap": { "check-coverage": true, "nyc-arg": [ @@ -31,21 +41,12 @@ "tap-snapshots/**" ] }, - "devDependencies": { - "@npmcli/eslint-config": "^5.0.0", - "@npmcli/template-oss": "4.23.3", - "spawk": "^1.7.1", - "tap": "^16.0.1" - }, "engines": { "node": "^18.17.0 || >=20.5.0" }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", "version": "4.23.3", - "publish": true - }, - "dependencies": { - "which": "^5.0.0" + "publish": "true" } } diff --git a/node_modules/@npmcli/promise-spawn/package.json b/node_modules/@npmcli/promise-spawn/package.json index 1b633f84596d2..9914063f85156 100644 --- a/node_modules/@npmcli/promise-spawn/package.json +++ b/node_modules/@npmcli/promise-spawn/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/promise-spawn", - "version": "7.0.2", + "version": "8.0.1", "files": [ "bin/", "lib/" @@ -16,12 +16,13 @@ "scripts": { "test": "tap", "snap": "tap", - "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", - "lintfix": "npm run lint -- --fix", + "lint": "npm run eslint", + "lintfix": "npm run eslint -- --fix", "posttest": "npm run lint", "postsnap": "npm run lintfix --", "postlint": "template-oss-check", - "template-oss-apply": "template-oss-apply --force" + "template-oss-apply": "template-oss-apply --force", + "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"" }, "tap": { "check-coverage": true, @@ -31,20 +32,20 @@ ] }, "devDependencies": { - "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.22.0", + "@npmcli/eslint-config": "^5.0.0", + "@npmcli/template-oss": "4.23.3", "spawk": "^1.7.1", "tap": "^16.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.22.0", + "version": "4.23.3", "publish": true }, "dependencies": { - "which": "^4.0.0" + "which": "^5.0.0" } } diff --git a/node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn/LICENSE b/node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn/LICENSE new file mode 100644 index 0000000000000..8f90f96f4c6c5 --- /dev/null +++ b/node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) npm, Inc. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE NPM DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE NPM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, +OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. diff --git a/node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn/lib/escape.js b/node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn/lib/escape.js new file mode 100644 index 0000000000000..9aca8bde70a6e --- /dev/null +++ b/node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn/lib/escape.js @@ -0,0 +1,68 @@ +'use strict' + +// eslint-disable-next-line max-len +// this code adapted from: https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ +const cmd = (input, doubleEscape) => { + if (!input.length) { + return '""' + } + + let result + if (!/[ \t\n\v"]/.test(input)) { + result = input + } else { + result = '"' + for (let i = 0; i <= input.length; ++i) { + let slashCount = 0 + while (input[i] === '\\') { + ++i + ++slashCount + } + + if (i === input.length) { + result += '\\'.repeat(slashCount * 2) + break + } + + if (input[i] === '"') { + result += '\\'.repeat(slashCount * 2 + 1) + result += input[i] + } else { + result += '\\'.repeat(slashCount) + result += input[i] + } + } + result += '"' + } + + // and finally, prefix shell meta chars with a ^ + result = result.replace(/[ !%^&()<>|"]/g, '^$&') + if (doubleEscape) { + result = result.replace(/[ !%^&()<>|"]/g, '^$&') + } + + return result +} + +const sh = (input) => { + if (!input.length) { + return `''` + } + + if (!/[\t\n\r "#$&'()*;<>?\\`|~]/.test(input)) { + return input + } + + // replace single quotes with '\'' and wrap the whole result in a fresh set of quotes + const result = `'${input.replace(/'/g, `'\\''`)}'` + // if the input string already had single quotes around it, clean those up + .replace(/^(?:'')+(?!$)/, '') + .replace(/\\'''/g, `\\'`) + + return result +} + +module.exports = { + cmd, + sh, +} diff --git a/node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn/lib/index.js b/node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn/lib/index.js new file mode 100644 index 0000000000000..e147cb8f9c746 --- /dev/null +++ b/node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn/lib/index.js @@ -0,0 +1,206 @@ +'use strict' + +const { spawn } = require('child_process') +const os = require('os') +const which = require('which') + +const escape = require('./escape.js') + +// 'extra' object is for decorating the error a bit more +const promiseSpawn = (cmd, args, opts = {}, extra = {}) => { + if (opts.shell) { + return spawnWithShell(cmd, args, opts, extra) + } + + let resolve, reject + const promise = new Promise((_resolve, _reject) => { + resolve = _resolve + reject = _reject + }) + + // Create error here so we have a more useful stack trace when rejecting + const closeError = new Error('command failed') + + const stdout = [] + const stderr = [] + + const getResult = (result) => ({ + cmd, + args, + ...result, + ...stdioResult(stdout, stderr, opts), + ...extra, + }) + const rejectWithOpts = (er, erOpts) => { + const resultError = getResult(erOpts) + reject(Object.assign(er, resultError)) + } + + const proc = spawn(cmd, args, opts) + promise.stdin = proc.stdin + promise.process = proc + + proc.on('error', rejectWithOpts) + + if (proc.stdout) { + proc.stdout.on('data', c => stdout.push(c)) + proc.stdout.on('error', rejectWithOpts) + } + + if (proc.stderr) { + proc.stderr.on('data', c => stderr.push(c)) + proc.stderr.on('error', rejectWithOpts) + } + + proc.on('close', (code, signal) => { + if (code || signal) { + rejectWithOpts(closeError, { code, signal }) + } else { + resolve(getResult({ code, signal })) + } + }) + + return promise +} + +const spawnWithShell = (cmd, args, opts, extra) => { + let command = opts.shell + // if shell is set to true, we use a platform default. we can't let the core + // spawn method decide this for us because we need to know what shell is in use + // ahead of time so that we can escape arguments properly. we don't need coverage here. + if (command === true) { + // istanbul ignore next + command = process.platform === 'win32' ? process.env.ComSpec : 'sh' + } + + const options = { ...opts, shell: false } + const realArgs = [] + let script = cmd + + // first, determine if we're in windows because if we are we need to know if we're + // running an .exe or a .cmd/.bat since the latter requires extra escaping + const isCmd = /(?:^|\\)cmd(?:\.exe)?$/i.test(command) + if (isCmd) { + let doubleEscape = false + + // find the actual command we're running + let initialCmd = '' + let insideQuotes = false + for (let i = 0; i < cmd.length; ++i) { + const char = cmd.charAt(i) + if (char === ' ' && !insideQuotes) { + break + } + + initialCmd += char + if (char === '"' || char === "'") { + insideQuotes = !insideQuotes + } + } + + let pathToInitial + try { + pathToInitial = which.sync(initialCmd, { + path: (options.env && findInObject(options.env, 'PATH')) || process.env.PATH, + pathext: (options.env && findInObject(options.env, 'PATHEXT')) || process.env.PATHEXT, + }).toLowerCase() + } catch (err) { + pathToInitial = initialCmd.toLowerCase() + } + + doubleEscape = pathToInitial.endsWith('.cmd') || pathToInitial.endsWith('.bat') + for (const arg of args) { + script += ` ${escape.cmd(arg, doubleEscape)}` + } + realArgs.push('/d', '/s', '/c', script) + options.windowsVerbatimArguments = true + } else { + for (const arg of args) { + script += ` ${escape.sh(arg)}` + } + realArgs.push('-c', script) + } + + return promiseSpawn(command, realArgs, options, extra) +} + +// open a file with the default application as defined by the user's OS +const open = (_args, opts = {}, extra = {}) => { + const options = { ...opts, shell: true } + const args = [].concat(_args) + + let platform = process.platform + // process.platform === 'linux' may actually indicate WSL, if that's the case + // we want to treat things as win32 anyway so the host can open the argument + if (platform === 'linux' && os.release().toLowerCase().includes('microsoft')) { + platform = 'win32' + } + + let command = options.command + if (!command) { + if (platform === 'win32') { + // spawnWithShell does not do the additional os.release() check, so we + // have to force the shell here to make sure we treat WSL as windows. + options.shell = process.env.ComSpec + // also, the start command accepts a title so to make sure that we don't + // accidentally interpret the first arg as the title, we stick an empty + // string immediately after the start command + command = 'start ""' + } else if (platform === 'darwin') { + command = 'open' + } else { + command = 'xdg-open' + } + } + + return spawnWithShell(command, args, options, extra) +} +promiseSpawn.open = open + +const isPipe = (stdio = 'pipe', fd) => { + if (stdio === 'pipe' || stdio === null) { + return true + } + + if (Array.isArray(stdio)) { + return isPipe(stdio[fd], fd) + } + + return false +} + +const stdioResult = (stdout, stderr, { stdioString = true, stdio }) => { + const result = { + stdout: null, + stderr: null, + } + + // stdio is [stdin, stdout, stderr] + if (isPipe(stdio, 1)) { + result.stdout = Buffer.concat(stdout) + if (stdioString) { + result.stdout = result.stdout.toString().trim() + } + } + + if (isPipe(stdio, 2)) { + result.stderr = Buffer.concat(stderr) + if (stdioString) { + result.stderr = result.stderr.toString().trim() + } + } + + return result +} + +// case insensitive lookup in an object +const findInObject = (obj, key) => { + key = key.toLowerCase() + for (const objKey of Object.keys(obj).sort()) { + if (objKey.toLowerCase() === key) { + return obj[objKey] + } + } +} + +module.exports = promiseSpawn diff --git a/node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn/package.json b/node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn/package.json new file mode 100644 index 0000000000000..1b633f84596d2 --- /dev/null +++ b/node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn/package.json @@ -0,0 +1,50 @@ +{ + "name": "@npmcli/promise-spawn", + "version": "7.0.2", + "files": [ + "bin/", + "lib/" + ], + "main": "./lib/index.js", + "description": "spawn processes the way the npm cli likes to do", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/promise-spawn.git" + }, + "author": "GitHub Inc.", + "license": "ISC", + "scripts": { + "test": "tap", + "snap": "tap", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", + "lintfix": "npm run lint -- --fix", + "posttest": "npm run lint", + "postsnap": "npm run lintfix --", + "postlint": "template-oss-check", + "template-oss-apply": "template-oss-apply --force" + }, + "tap": { + "check-coverage": true, + "nyc-arg": [ + "--exclude", + "tap-snapshots/**" + ] + }, + "devDependencies": { + "@npmcli/eslint-config": "^4.0.0", + "@npmcli/template-oss": "4.22.0", + "spawk": "^1.7.1", + "tap": "^16.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + }, + "templateOSS": { + "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", + "version": "4.22.0", + "publish": true + }, + "dependencies": { + "which": "^4.0.0" + } +} diff --git a/node_modules/pacote/node_modules/@npmcli/promise-spawn/LICENSE b/node_modules/pacote/node_modules/@npmcli/promise-spawn/LICENSE new file mode 100644 index 0000000000000..8f90f96f4c6c5 --- /dev/null +++ b/node_modules/pacote/node_modules/@npmcli/promise-spawn/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) npm, Inc. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE NPM DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE NPM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, +OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. diff --git a/node_modules/pacote/node_modules/@npmcli/promise-spawn/lib/escape.js b/node_modules/pacote/node_modules/@npmcli/promise-spawn/lib/escape.js new file mode 100644 index 0000000000000..9aca8bde70a6e --- /dev/null +++ b/node_modules/pacote/node_modules/@npmcli/promise-spawn/lib/escape.js @@ -0,0 +1,68 @@ +'use strict' + +// eslint-disable-next-line max-len +// this code adapted from: https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ +const cmd = (input, doubleEscape) => { + if (!input.length) { + return '""' + } + + let result + if (!/[ \t\n\v"]/.test(input)) { + result = input + } else { + result = '"' + for (let i = 0; i <= input.length; ++i) { + let slashCount = 0 + while (input[i] === '\\') { + ++i + ++slashCount + } + + if (i === input.length) { + result += '\\'.repeat(slashCount * 2) + break + } + + if (input[i] === '"') { + result += '\\'.repeat(slashCount * 2 + 1) + result += input[i] + } else { + result += '\\'.repeat(slashCount) + result += input[i] + } + } + result += '"' + } + + // and finally, prefix shell meta chars with a ^ + result = result.replace(/[ !%^&()<>|"]/g, '^$&') + if (doubleEscape) { + result = result.replace(/[ !%^&()<>|"]/g, '^$&') + } + + return result +} + +const sh = (input) => { + if (!input.length) { + return `''` + } + + if (!/[\t\n\r "#$&'()*;<>?\\`|~]/.test(input)) { + return input + } + + // replace single quotes with '\'' and wrap the whole result in a fresh set of quotes + const result = `'${input.replace(/'/g, `'\\''`)}'` + // if the input string already had single quotes around it, clean those up + .replace(/^(?:'')+(?!$)/, '') + .replace(/\\'''/g, `\\'`) + + return result +} + +module.exports = { + cmd, + sh, +} diff --git a/node_modules/pacote/node_modules/@npmcli/promise-spawn/lib/index.js b/node_modules/pacote/node_modules/@npmcli/promise-spawn/lib/index.js new file mode 100644 index 0000000000000..e147cb8f9c746 --- /dev/null +++ b/node_modules/pacote/node_modules/@npmcli/promise-spawn/lib/index.js @@ -0,0 +1,206 @@ +'use strict' + +const { spawn } = require('child_process') +const os = require('os') +const which = require('which') + +const escape = require('./escape.js') + +// 'extra' object is for decorating the error a bit more +const promiseSpawn = (cmd, args, opts = {}, extra = {}) => { + if (opts.shell) { + return spawnWithShell(cmd, args, opts, extra) + } + + let resolve, reject + const promise = new Promise((_resolve, _reject) => { + resolve = _resolve + reject = _reject + }) + + // Create error here so we have a more useful stack trace when rejecting + const closeError = new Error('command failed') + + const stdout = [] + const stderr = [] + + const getResult = (result) => ({ + cmd, + args, + ...result, + ...stdioResult(stdout, stderr, opts), + ...extra, + }) + const rejectWithOpts = (er, erOpts) => { + const resultError = getResult(erOpts) + reject(Object.assign(er, resultError)) + } + + const proc = spawn(cmd, args, opts) + promise.stdin = proc.stdin + promise.process = proc + + proc.on('error', rejectWithOpts) + + if (proc.stdout) { + proc.stdout.on('data', c => stdout.push(c)) + proc.stdout.on('error', rejectWithOpts) + } + + if (proc.stderr) { + proc.stderr.on('data', c => stderr.push(c)) + proc.stderr.on('error', rejectWithOpts) + } + + proc.on('close', (code, signal) => { + if (code || signal) { + rejectWithOpts(closeError, { code, signal }) + } else { + resolve(getResult({ code, signal })) + } + }) + + return promise +} + +const spawnWithShell = (cmd, args, opts, extra) => { + let command = opts.shell + // if shell is set to true, we use a platform default. we can't let the core + // spawn method decide this for us because we need to know what shell is in use + // ahead of time so that we can escape arguments properly. we don't need coverage here. + if (command === true) { + // istanbul ignore next + command = process.platform === 'win32' ? process.env.ComSpec : 'sh' + } + + const options = { ...opts, shell: false } + const realArgs = [] + let script = cmd + + // first, determine if we're in windows because if we are we need to know if we're + // running an .exe or a .cmd/.bat since the latter requires extra escaping + const isCmd = /(?:^|\\)cmd(?:\.exe)?$/i.test(command) + if (isCmd) { + let doubleEscape = false + + // find the actual command we're running + let initialCmd = '' + let insideQuotes = false + for (let i = 0; i < cmd.length; ++i) { + const char = cmd.charAt(i) + if (char === ' ' && !insideQuotes) { + break + } + + initialCmd += char + if (char === '"' || char === "'") { + insideQuotes = !insideQuotes + } + } + + let pathToInitial + try { + pathToInitial = which.sync(initialCmd, { + path: (options.env && findInObject(options.env, 'PATH')) || process.env.PATH, + pathext: (options.env && findInObject(options.env, 'PATHEXT')) || process.env.PATHEXT, + }).toLowerCase() + } catch (err) { + pathToInitial = initialCmd.toLowerCase() + } + + doubleEscape = pathToInitial.endsWith('.cmd') || pathToInitial.endsWith('.bat') + for (const arg of args) { + script += ` ${escape.cmd(arg, doubleEscape)}` + } + realArgs.push('/d', '/s', '/c', script) + options.windowsVerbatimArguments = true + } else { + for (const arg of args) { + script += ` ${escape.sh(arg)}` + } + realArgs.push('-c', script) + } + + return promiseSpawn(command, realArgs, options, extra) +} + +// open a file with the default application as defined by the user's OS +const open = (_args, opts = {}, extra = {}) => { + const options = { ...opts, shell: true } + const args = [].concat(_args) + + let platform = process.platform + // process.platform === 'linux' may actually indicate WSL, if that's the case + // we want to treat things as win32 anyway so the host can open the argument + if (platform === 'linux' && os.release().toLowerCase().includes('microsoft')) { + platform = 'win32' + } + + let command = options.command + if (!command) { + if (platform === 'win32') { + // spawnWithShell does not do the additional os.release() check, so we + // have to force the shell here to make sure we treat WSL as windows. + options.shell = process.env.ComSpec + // also, the start command accepts a title so to make sure that we don't + // accidentally interpret the first arg as the title, we stick an empty + // string immediately after the start command + command = 'start ""' + } else if (platform === 'darwin') { + command = 'open' + } else { + command = 'xdg-open' + } + } + + return spawnWithShell(command, args, options, extra) +} +promiseSpawn.open = open + +const isPipe = (stdio = 'pipe', fd) => { + if (stdio === 'pipe' || stdio === null) { + return true + } + + if (Array.isArray(stdio)) { + return isPipe(stdio[fd], fd) + } + + return false +} + +const stdioResult = (stdout, stderr, { stdioString = true, stdio }) => { + const result = { + stdout: null, + stderr: null, + } + + // stdio is [stdin, stdout, stderr] + if (isPipe(stdio, 1)) { + result.stdout = Buffer.concat(stdout) + if (stdioString) { + result.stdout = result.stdout.toString().trim() + } + } + + if (isPipe(stdio, 2)) { + result.stderr = Buffer.concat(stderr) + if (stdioString) { + result.stderr = result.stderr.toString().trim() + } + } + + return result +} + +// case insensitive lookup in an object +const findInObject = (obj, key) => { + key = key.toLowerCase() + for (const objKey of Object.keys(obj).sort()) { + if (objKey.toLowerCase() === key) { + return obj[objKey] + } + } +} + +module.exports = promiseSpawn diff --git a/node_modules/pacote/node_modules/@npmcli/promise-spawn/package.json b/node_modules/pacote/node_modules/@npmcli/promise-spawn/package.json new file mode 100644 index 0000000000000..1b633f84596d2 --- /dev/null +++ b/node_modules/pacote/node_modules/@npmcli/promise-spawn/package.json @@ -0,0 +1,50 @@ +{ + "name": "@npmcli/promise-spawn", + "version": "7.0.2", + "files": [ + "bin/", + "lib/" + ], + "main": "./lib/index.js", + "description": "spawn processes the way the npm cli likes to do", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/promise-spawn.git" + }, + "author": "GitHub Inc.", + "license": "ISC", + "scripts": { + "test": "tap", + "snap": "tap", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", + "lintfix": "npm run lint -- --fix", + "posttest": "npm run lint", + "postsnap": "npm run lintfix --", + "postlint": "template-oss-check", + "template-oss-apply": "template-oss-apply --force" + }, + "tap": { + "check-coverage": true, + "nyc-arg": [ + "--exclude", + "tap-snapshots/**" + ] + }, + "devDependencies": { + "@npmcli/eslint-config": "^4.0.0", + "@npmcli/template-oss": "4.22.0", + "spawk": "^1.7.1", + "tap": "^16.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + }, + "templateOSS": { + "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", + "version": "4.22.0", + "publish": true + }, + "dependencies": { + "which": "^4.0.0" + } +} diff --git a/package-lock.json b/package-lock.json index 9f87669198175..63256b17e7a8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -92,7 +92,7 @@ "@npmcli/fs": "^4.0.0", "@npmcli/map-workspaces": "^4.0.1", "@npmcli/package-json": "^6.0.1", - "@npmcli/promise-spawn": "^7.0.2", + "@npmcli/promise-spawn": "^8.0.1", "@npmcli/redact": "^2.0.1", "@npmcli/run-script": "^8.1.0", "@sigstore/tuf": "^2.3.4", @@ -1592,6 +1592,19 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/@npmcli/git/node_modules/@npmcli/promise-spawn": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz", + "integrity": "sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==", + "inBundle": true, + "license": "ISC", + "dependencies": { + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/@npmcli/installed-package-contents": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.1.0.tgz", @@ -1718,19 +1731,6 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@npmcli/package-json/node_modules/@npmcli/promise-spawn": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-8.0.1.tgz", - "integrity": "sha512-ZscqKtJqy7oj6MgXEJcHQ1om4utU0Q84QtC28UVuiO6ALSO9sDPanXdu6Wd1oYhItW8fx2u96zRFUE8BuPlAjA==", - "inBundle": true, - "license": "ISC", - "dependencies": { - "which": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, "node_modules/@npmcli/package-json/node_modules/hosted-git-info": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.0.0.tgz", @@ -1881,16 +1881,42 @@ } }, "node_modules/@npmcli/promise-spawn": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz", - "integrity": "sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-8.0.1.tgz", + "integrity": "sha512-ZscqKtJqy7oj6MgXEJcHQ1om4utU0Q84QtC28UVuiO6ALSO9sDPanXdu6Wd1oYhItW8fx2u96zRFUE8BuPlAjA==", "inBundle": true, "license": "ISC", "dependencies": { - "which": "^4.0.0" + "which": "^5.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/query": { @@ -1952,6 +1978,19 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz", + "integrity": "sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==", + "inBundle": true, + "license": "ISC", + "dependencies": { + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/@npmcli/smoke-tests": { "resolved": "smoke-tests", "link": true @@ -10464,6 +10503,19 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/pacote/node_modules/@npmcli/promise-spawn": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz", + "integrity": "sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==", + "inBundle": true, + "license": "ISC", + "dependencies": { + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -16037,7 +16089,7 @@ "devDependencies": { "@npmcli/eslint-config": "^4.0.0", "@npmcli/mock-registry": "^1.0.0", - "@npmcli/promise-spawn": "^7.0.2", + "@npmcli/promise-spawn": "^8.0.1", "@npmcli/template-oss": "4.23.3", "proxy": "^2.1.1", "semver": "^7.5.4", diff --git a/package.json b/package.json index 828fb8348232b..99423a86ade8f 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "@npmcli/fs": "^4.0.0", "@npmcli/map-workspaces": "^4.0.1", "@npmcli/package-json": "^6.0.1", - "@npmcli/promise-spawn": "^7.0.2", + "@npmcli/promise-spawn": "^8.0.1", "@npmcli/redact": "^2.0.1", "@npmcli/run-script": "^8.1.0", "@sigstore/tuf": "^2.3.4", diff --git a/smoke-tests/package.json b/smoke-tests/package.json index 73b576d551f7d..b8ba89bc26d4a 100644 --- a/smoke-tests/package.json +++ b/smoke-tests/package.json @@ -21,7 +21,7 @@ "devDependencies": { "@npmcli/eslint-config": "^4.0.0", "@npmcli/mock-registry": "^1.0.0", - "@npmcli/promise-spawn": "^7.0.2", + "@npmcli/promise-spawn": "^8.0.1", "@npmcli/template-oss": "4.23.3", "proxy": "^2.1.1", "semver": "^7.5.4",