diff --git a/doc/cli/npm-restart.md b/doc/cli/npm-restart.md index 4661d6b23ba..7b039a8f8f1 100644 --- a/doc/cli/npm-restart.md +++ b/doc/cli/npm-restart.md @@ -3,7 +3,7 @@ npm-restart(1) -- Start a package ## SYNOPSIS - npm restart + npm restart [-- ] ## DESCRIPTION diff --git a/doc/cli/npm-run-script.md b/doc/cli/npm-run-script.md index 835dbf5df7f..09a546b9a81 100644 --- a/doc/cli/npm-run-script.md +++ b/doc/cli/npm-run-script.md @@ -3,8 +3,8 @@ npm-run-script(1) -- Run arbitrary package scripts ## SYNOPSIS - npm run-script [] [command] - npm run [] [command] + npm run-script [command] [-- ] + npm run [command] [-- ] ## DESCRIPTION diff --git a/doc/cli/npm-start.md b/doc/cli/npm-start.md index 01347d2e469..759de221f38 100644 --- a/doc/cli/npm-start.md +++ b/doc/cli/npm-start.md @@ -3,7 +3,7 @@ npm-start(1) -- Start a package ## SYNOPSIS - npm start + npm start [-- ] ## DESCRIPTION diff --git a/doc/cli/npm-stop.md b/doc/cli/npm-stop.md index bda5cc8f47c..92b14b41796 100644 --- a/doc/cli/npm-stop.md +++ b/doc/cli/npm-stop.md @@ -3,7 +3,7 @@ npm-stop(1) -- Stop a package ## SYNOPSIS - npm stop + npm stop [-- ] ## DESCRIPTION diff --git a/doc/cli/npm-test.md b/doc/cli/npm-test.md index 800f3ae104e..c2267082dfb 100644 --- a/doc/cli/npm-test.md +++ b/doc/cli/npm-test.md @@ -3,8 +3,8 @@ npm-test(1) -- Test a package ## SYNOPSIS - npm test - npm tst + npm test [-- ] + npm tst [-- ] ## DESCRIPTION diff --git a/lib/run-script.js b/lib/run-script.js index 25e98f01d65..42d570f46a3 100644 --- a/lib/run-script.js +++ b/lib/run-script.js @@ -8,7 +8,7 @@ var lifecycle = require("./utils/lifecycle.js") , log = require("npmlog") , chain = require("slide").chain -runScript.usage = "npm run-script [] " +runScript.usage = "npm run-script [-- ]" runScript.completion = function (opts, cb) { @@ -69,13 +69,13 @@ runScript.completion = function (opts, cb) { function runScript (args, cb) { if (!args.length) return list(cb) - var pkgdir = args.length === 1 ? process.cwd() - : path.resolve(npm.dir, args[0]) - , cmd = args.pop() + + var pkgdir = process.cwd() + , cmd = args.shift() readJson(path.resolve(pkgdir, "package.json"), function (er, d) { if (er) return cb(er) - run(d, pkgdir, cmd, cb) + run(d, pkgdir, cmd, args, cb) }) } @@ -109,7 +109,7 @@ function list(cb) { }) } -function run (pkg, wd, cmd, cb) { +function run (pkg, wd, cmd, args, cb) { var cmds = [] if (!pkg.scripts) pkg.scripts = {} if (cmd === "restart") { @@ -124,6 +124,11 @@ function run (pkg, wd, cmd, cb) { } log.verbose("run-script", cmds) chain(cmds.map(function (c) { + // pass cli arguments after -- to script. + if (args.length && pkg.scripts[c]) { + pkg.scripts[c] = pkg.scripts[c] + " " + args.join(" ") + } + // when running scripts explicitly, assume that they're trusted. return [lifecycle, pkg, c, wd, true] }), cb) diff --git a/lib/utils/lifecycle.js b/lib/utils/lifecycle.js index af009cc2151..231d1283284 100644 --- a/lib/utils/lifecycle.js +++ b/lib/utils/lifecycle.js @@ -349,13 +349,9 @@ function makeEnv (data, prefix, env) { function cmd (stage) { function CMD (args, cb) { - if (args.length) { - chain(args.map(function (p) { - return [npm.commands, "run-script", [p, stage]] - }), cb) - } else npm.commands["run-script"]([stage], cb) + npm.commands["run-script"]([stage].concat(args), cb) } - CMD.usage = "npm "+stage+" " + CMD.usage = "npm "+stage+" [-- ]" var installedShallow = require("./completion/installed-shallow.js") CMD.completion = function (opts, cb) { installedShallow(opts, function (d) { diff --git a/test/run.js b/test/run.js index 008cfbac45a..a213afe7aa1 100644 --- a/test/run.js +++ b/test/run.js @@ -7,7 +7,7 @@ var path = require("path") , testdir = __dirname , fs = require("graceful-fs") , npmpkg = path.dirname(testdir) - , npmcli = path.join(__dirname, "bin", "npm-cli.js") + , npmcli = path.resolve(npmpkg, "bin", "npm-cli.js") var temp = process.env.TMPDIR || process.env.TMP @@ -63,7 +63,7 @@ function prefix (content, pref) { } var execCount = 0 -function exec (cmd, shouldFail, cb) { +function exec (cmd, cwd, shouldFail, cb) { if (typeof shouldFail === "function") { cb = shouldFail, shouldFail = false } @@ -81,7 +81,7 @@ function exec (cmd, shouldFail, cb) { cmd = cmd.replace(/^npm /, npmReplace + " ") cmd = cmd.replace(/^node /, nodeReplace + " ") - child_process.exec(cmd, {env: env}, function (er, stdout, stderr) { + child_process.exec(cmd, {cwd: cwd, env: env}, function (er, stdout, stderr) { if (stdout) { console.error(prefix(stdout, " 1> ")) } @@ -102,10 +102,8 @@ function exec (cmd, shouldFail, cb) { } function execChain (cmds, cb) { - chain(cmds.reduce(function (l, r) { - return l.concat(r) - }, []).map(function (cmd) { - return [exec, cmd] + chain(cmds.map(function (args) { + return [exec].concat(args) }), cb) } @@ -118,9 +116,8 @@ function flatten (arr) { function setup (cb) { cleanup(function (er) { if (er) return cb(er) - execChain([ "node \""+path.resolve(npmpkg, "bin", "npm-cli.js") - + "\" install \""+npmpkg+"\"" - , "npm config set package-config:foo boo" + execChain([ [ "node \""+npmcli+"\" install \""+npmpkg+"\"", root ], + [ "npm config set package-config:foo boo", root ] ], cb) }) } @@ -134,6 +131,7 @@ function main (cb) { failures = 0 process.chdir(testdir) + var base = path.resolve(root, path.join("lib", "node_modules")) // get the list of packages var packages = fs.readdirSync(path.resolve(testdir, "packages")) @@ -150,17 +148,17 @@ function main (cb) { packagesToRm.push("npm") } - chain - ( [ setup - , [ exec, "npm install "+npmpkg ] + chain( + [ setup + , [ exec, "npm install "+npmpkg, testdir ] , [ execChain, packages.map(function (p) { - return "npm install packages/"+p + return [ "npm install packages/"+p, testdir ] }) ] , [ execChain, packages.map(function (p) { - return "npm test "+p + return [ "npm test", path.resolve(base, p) ] }) ] , [ execChain, packagesToRm.map(function (p) { - return "npm rm " + p + return [ "npm rm "+p, root ] }) ] , installAndTestEach ] @@ -171,15 +169,15 @@ function main (cb) { function installAndTestEach (cb) { var thingsToChain = [ setup - , [ execChain, packages.map(function (p) { - return [ "npm install packages/"+p - , "npm test "+p - , "npm rm "+p ] - }) ] + , [ execChain, flatten(packages.map(function (p) { + return [ [ "npm install packages/"+p, testdir ] + , [ "npm test", path.resolve(base, p) ] + , [ "npm rm "+p, root ] ] + })) ] ] if (process.platform !== "win32") { // Windows can't handle npm rm npm due to file-in-use issues. - thingsToChain.push([exec, "npm rm npm"]) + thingsToChain.push([exec, "npm rm npm", testdir]) } chain(thingsToChain, cb) diff --git a/test/tap/run-script.js b/test/tap/run-script.js new file mode 100644 index 00000000000..019e2dd19ea --- /dev/null +++ b/test/tap/run-script.js @@ -0,0 +1,50 @@ +var common = require('../common-tap') + , test = require('tap').test + , path = require('path') + , spawn = require('child_process').spawn + , rimraf = require('rimraf') + , mkdirp = require('mkdirp') + , pkg = __dirname + '/run-script' + , cache = pkg + '/cache' + , tmp = pkg + '/tmp' + , node = process.execPath + , npm = path.resolve(__dirname, '../../cli.js') + , opts = { cwd: pkg } + +function testOutput (t, command, er, code, stdout, stderr) { + if (er) + throw er + + if (stderr) + throw new Error('npm ' + command + ' stderr: ' + stderr.toString()) + + stdout = stdout.trim().split('\n') + stdout = stdout[stdout.length - 1] + t.equal(stdout, command) + t.end() +} + +function cleanup () { + rimraf.sync(pkg + '/cache') + rimraf.sync(pkg + '/tmp') +} + +test('setup', function (t) { + cleanup() + mkdirp.sync(pkg + '/cache') + mkdirp.sync(pkg + '/tmp') + t.end() +}) + +test('npm run-script', function (t) { + common.npm(['run-script', 'start'], opts, testOutput.bind(null, t, "start")) +}) + +test('npm run-script with args', function (t) { + common.npm(["run-script", "start", "--", "-e 'console.log(\"stop\")'"], opts, testOutput.bind(null, t, "stop")) +}) + +test('cleanup', function (t) { + cleanup() + t.end() +}) diff --git a/test/tap/run-script/package.json b/test/tap/run-script/package.json new file mode 100644 index 00000000000..b7edbaf3c2f --- /dev/null +++ b/test/tap/run-script/package.json @@ -0,0 +1,6 @@ +{"name":"runscript" +,"version":"1.2.3" +,"scripts":{ + "start":"node -e 'console.log(\"start\")'" + } +}