Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGar <gar+gh@danger.computer>2022-08-10 20:39:17 +0300
committerGar <gar+gh@danger.computer>2022-08-11 17:28:47 +0300
commitb32be094b0048324a070717f2a819b7eee702a83 (patch)
treec68903d84954e1d23a440bed4086c0351189580c
parent9dc69830a5d78aa4042746d54e2a6b0d2af70caa (diff)
fix: don't prompt on `npm exec [directory]`gar/exec-directory
Local directories have to be "installed" so that their bins are linked and set up and callable, the user shouldn't need to be prompted to do that. Note that this does NOT affect anything passed via the `--package` param, because that may also contain non-directory specs so the existing behavior needs to be preserved. This is a small QOL improvement for the isolated use case of "npm exec [directory]" This also updates the hashing method used to come up with the `.npx` directory to resolve the paths to packages first, so that `npm exec .` in different directories don't share the same `.npx` directory.
-rw-r--r--workspaces/libnpmexec/lib/index.js29
-rw-r--r--workspaces/libnpmexec/test/index.js11
2 files changed, 37 insertions, 3 deletions
diff --git a/workspaces/libnpmexec/lib/index.js b/workspaces/libnpmexec/lib/index.js
index 15d5ba4ee..45c75d471 100644
--- a/workspaces/libnpmexec/lib/index.js
+++ b/workspaces/libnpmexec/lib/index.js
@@ -63,6 +63,9 @@ const missingFromTree = async ({ spec, tree, flatOptions }) => {
// non-registry spec, or a specific tag. Look up manifest and check
// resolved to see if it's in the tree.
const manifest = await getManifest(spec, flatOptions)
+ if (spec.type === 'directory') {
+ return { manifest }
+ }
const nodesByManifest = tree.inventory.query('packageName', manifest.name)
for (const node of nodesByManifest) {
if (node.package.resolved === manifest._resolved) {
@@ -89,10 +92,10 @@ const exec = async (opts) => {
path = '.',
runPath = '.',
scriptShell = isWindows ? process.env.ComSpec || 'cmd' : 'sh',
- yes = undefined,
...flatOptions
} = opts
+ let yes = opts.yes
const run = () => runScript({
args,
call,
@@ -129,6 +132,16 @@ const exec = async (opts) => {
packages.push(args[0])
}
+ // Resolve any directory specs so that the npx directory is unique to the
+ // resolved directory, not the potentially relative one (i.e. "npx .")
+ for (const i in packages) {
+ const pkg = packages[i]
+ const spec = npa(pkg)
+ if (spec.type === 'directory') {
+ packages[i] = spec.fetchSpec
+ }
+ }
+
const localArb = new Arborist({ ...flatOptions, path })
const localTree = await localArb.loadActual()
@@ -153,6 +166,10 @@ const exec = async (opts) => {
if (needPackageCommandSwap) {
const spec = npa(args[0])
+ if (spec.type === 'directory') {
+ yes = true
+ }
+
args[0] = getBinFromManifest(commandManifest)
if (needInstall.length > 0 && globalPath) {
@@ -176,7 +193,15 @@ const exec = async (opts) => {
throw new Error('Must provide a valid npxCache path')
}
const hash = crypto.createHash('sha512')
- .update(packages.sort((a, b) => a.localeCompare(b, 'en')).join('\n'))
+ .update(packages.map(p => {
+ // Keeps the npx directory unique to the resolved directory, not the
+ // potentially relative one (i.e. "npx .")
+ const spec = npa(p)
+ if (spec.type === 'directory') {
+ return spec.fetchSpec
+ }
+ return p
+ }).sort((a, b) => a.localeCompare(b, 'en')).join('\n'))
.digest('hex')
.slice(0, 16)
const installDir = resolve(npxCache, hash)
diff --git a/workspaces/libnpmexec/test/index.js b/workspaces/libnpmexec/test/index.js
index 3e218b75c..8d3411829 100644
--- a/workspaces/libnpmexec/test/index.js
+++ b/workspaces/libnpmexec/test/index.js
@@ -482,7 +482,16 @@ require('fs').writeFileSync(process.argv.slice(2)[0], 'LOCAL PKG')`,
const executable = resolve(path, 'a/index.js')
fs.chmodSync(executable, 0o775)
- await libexec({
+ const mockexec = t.mock('../lib/index.js', {
+ '@npmcli/ci-detect': () => true,
+ 'proc-log': {
+ warn (title, msg) {
+ t.fail('should not warn about local file package install')
+ },
+ },
+ })
+
+ await mockexec({
...baseOpts,
args: [`file:${resolve(path, 'a')}`, 'resfile'],
cache,