Skip to content

Commit

Permalink
fix: npm exec on folders missing package.json
Browse files Browse the repository at this point in the history
This fixes running `npm exec` in folders that does not have a
`package.json` file.

Fixes: npm#1975
  • Loading branch information
ruyadorno committed Oct 29, 2020
1 parent 84d7123 commit be6859e
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 47 deletions.
83 changes: 40 additions & 43 deletions lib/exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,41 @@ const PATH = require('./utils/path.js')

const cmd = (args, cb) => exec(args).then(() => cb()).catch(cb)

const run = async ({ args, call, pathArr }) => {
// turn list of args into command string
const script = call || args.map(escapeArg).join(' ').trim()

// do the fakey runScript dance
// still should work if no package.json in cwd
const realPkg = await readPackageJson(`${npm.localPrefix}/package.json`)
.catch(() => ({}))
const pkg = {
...realPkg,
scripts: {
...(realPkg.scripts || {}),
npx: script,
},
}

npm.log.disableProgress()
try {
return await runScript({
pkg,
banner: false,
// we always run in cwd, not --prefix
path: process.cwd(),
stdioString: true,
event: 'npx',
env: {
PATH: pathArr.join(delimiter),
},
stdio: 'inherit',
})
} finally {
npm.log.enableProgress()
}
}

const exec = async args => {
const { package: packages, call } = npm.flatOptions

Expand All @@ -89,17 +124,10 @@ const exec = async args => {
}

if (binExists) {
return await runScript({
cmd: [args[0], ...args.slice(1).map(escapeArg)].join(' ').trim(),
banner: false,
// we always run in cwd, not --prefix
path: process.cwd(),
stdioString: true,
event: 'npx',
env: {
PATH: pathArr.join(delimiter),
},
stdio: 'inherit',
return await run({
args,
call: [args[0], ...args.slice(1).map(escapeArg)].join(' ').trim(),
pathArr,
})
}

Expand Down Expand Up @@ -129,9 +157,6 @@ const exec = async args => {
if (needPackageCommandSwap)
args[0] = getBinFromManifest(manis[0])

// turn list of args into command string
const script = call || args.map(escapeArg).join(' ').trim()

// figure out whether we need to install stuff, or if local is fine
const localArb = new Arborist({
...npm.flatOptions,
Expand Down Expand Up @@ -180,35 +205,7 @@ const exec = async args => {
pathArr.unshift(resolve(installDir, 'node_modules/.bin'))
}

// do the fakey runScript dance
// still should work if no package.json in cwd
const realPkg = await readPackageJson(`${npm.localPrefix}/package.json`)
.catch(() => ({}))
const pkg = {
...realPkg,
scripts: {
...(realPkg.scripts || {}),
npx: script,
},
}

npm.log.disableProgress()
try {
return await runScript({
pkg,
banner: false,
// we always run in cwd, not --prefix
path: process.cwd(),
stdioString: true,
event: 'npx',
env: {
PATH: pathArr.join(delimiter),
},
stdio: 'inherit',
})
} finally {
npm.log.enableProgress()
}
return await run({ args, call, pathArr })
}

const manifestMissing = (tree, mani) => {
Expand Down
9 changes: 5 additions & 4 deletions test/lib/exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,16 @@ const PATH = require('../../lib/utils/path.js')

let CI_NAME = 'travis-ci'

const exec = requireInject('../../lib/exec.js', {
const mocks = {
'@npmcli/arborist': Arborist,
'@npmcli/run-script': runScript,
'@npmcli/ci-detect': () => CI_NAME,
'../../lib/npm.js': npm,
pacote,
read,
'mkdirp-infer-owner': mkdirp
})
}
const exec = requireInject('../../lib/exec.js', mocks)

t.afterEach(cb => {
MKDIRPS.length = 0
Expand Down Expand Up @@ -122,7 +123,7 @@ t.test('npx foo, bin already exists locally', async t => {
t.ifError(er, 'npm exec')
})
t.strictSame(RUN_SCRIPTS, [{
cmd: 'foo',
pkg: { scripts: { npx: 'foo' }},
banner: false,
path: process.cwd(),
stdioString: true,
Expand All @@ -146,7 +147,7 @@ t.test('npx foo, bin already exists globally', async t => {
t.ifError(er, 'npm exec')
})
t.strictSame(RUN_SCRIPTS, [{
cmd: 'foo',
pkg: { scripts: { npx: 'foo' }},
banner: false,
path: process.cwd(),
stdioString: true,
Expand Down

0 comments on commit be6859e

Please sign in to comment.