From 12b2b87cf473e4b11e27da64b4c27d9f2db8d7e6 Mon Sep 17 00:00:00 2001 From: Toru Nagashima Date: Sat, 31 Dec 2016 23:24:24 +0900 Subject: [PATCH] Breaking: use NPM_EXECPATH to run tasks And add --npm-path option. --- bin/common/parse-cli-args.js | 9 +++++++-- bin/npm-run-all/help.js | 5 +++++ bin/npm-run-all/main.js | 1 + bin/run-p/help.js | 5 +++++ bin/run-p/main.js | 1 + bin/run-s/help.js | 5 +++++ bin/run-s/main.js | 1 + docs/node-api.md | 3 +++ docs/npm-run-all.md | 5 +++++ docs/run-p.md | 5 +++++ docs/run-s.md | 5 +++++ lib/index.js | 8 ++++++++ lib/run-task.js | 31 +++++++++++++++++++++++++------ test-workspace/package.json | 5 ++++- test/lib/util.js | 18 ++++++++++++++++++ 15 files changed, 98 insertions(+), 9 deletions(-) diff --git a/bin/common/parse-cli-args.js b/bin/common/parse-cli-args.js index 34f9fec..b3013dd 100644 --- a/bin/common/parse-cli-args.js +++ b/bin/common/parse-cli-args.js @@ -77,17 +77,18 @@ class ArgumentSet { * @param {object} options - A key-value map for the options. */ constructor(initialValues, options) { + this.config = {} this.continueOnError = false this.groups = [] this.maxParallel = 0 + this.npmPath = null + this.packageConfig = createPackageConfig() this.printLabel = false this.printName = false this.race = false this.rest = [] this.silent = process.env.npm_config_loglevel === "silent" this.singleMode = Boolean(options && options.singleMode) - this.packageConfig = createPackageConfig() - this.config = {} addGroup(this.groups, initialValues) } @@ -181,6 +182,10 @@ function parseCLIArgsCore(set, args) { // eslint-disable-line complexity addGroup(set.groups, {parallel: true}) break + case "--npm-path": + set.npmPath = args[++i] || null + break + default: { let matched = null if ((matched = OVERWRITE_OPTION.exec(arg))) { diff --git a/bin/npm-run-all/help.js b/bin/npm-run-all/help.js index 742999b..781109c 100644 --- a/bin/npm-run-all/help.js +++ b/bin/npm-run-all/help.js @@ -33,6 +33,11 @@ Options: non-zero code if one or more tasks threw error(s) --max-parallel - Set the maximum number of parallelism. Default is unlimited. + --npm-path - - - Set the path to npm. Default is the value of + environment variable NPM_EXECPATH. + If the variable is not defined, then it's "npm." + In this case, the "npm" command must be found in + environment variable PATH. -l, --print-label - - - - Set the flag to print the task name as a prefix on each line of output. Tools in tasks may stop coloring their output if this option was given. diff --git a/bin/npm-run-all/main.js b/bin/npm-run-all/main.js index 3db9c5f..4e79aff 100644 --- a/bin/npm-run-all/main.js +++ b/bin/npm-run-all/main.js @@ -51,6 +51,7 @@ module.exports = function npmRunAll(args, stdout, stderr) { silent: argv.silent, arguments: argv.rest, race: argv.race, + npmPath: argv.npmPath, } )) }, diff --git a/bin/run-p/help.js b/bin/run-p/help.js index 023766f..503c677 100644 --- a/bin/run-p/help.js +++ b/bin/run-p/help.js @@ -33,6 +33,11 @@ Options: threw error(s). --max-parallel - Set the maximum number of parallelism. Default is unlimited. + --npm-path - - - Set the path to npm. Default is the value of + environment variable NPM_EXECPATH. + If the variable is not defined, then it's "npm." + In this case, the "npm" command must be found in + environment variable PATH. -l, --print-label - - - - Set the flag to print the task name as a prefix on each line of output. Tools in tasks may stop coloring their output if this option was given. diff --git a/bin/run-p/main.js b/bin/run-p/main.js index 71b6544..46b6f18 100644 --- a/bin/run-p/main.js +++ b/bin/run-p/main.js @@ -51,6 +51,7 @@ module.exports = function npmRunAll(args, stdout, stderr) { silent: argv.silent, arguments: argv.rest, race: argv.race, + npmPath: argv.npmPath, } ) diff --git a/bin/run-s/help.js b/bin/run-s/help.js index 7c00f08..96faac5 100644 --- a/bin/run-s/help.js +++ b/bin/run-s/help.js @@ -31,6 +31,11 @@ Options: tasks even if a task threw an error. 'run-s' itself will exit with non-zero code if one or more tasks threw error(s). + --npm-path - - - Set the path to npm. Default is the value of + environment variable NPM_EXECPATH. + If the variable is not defined, then it's "npm." + In this case, the "npm" command must be found in + environment variable PATH. -l, --print-label - - - - Set the flag to print the task name as a prefix on each line of output. Tools in tasks may stop coloring their output if this option was given. diff --git a/bin/run-s/main.js b/bin/run-s/main.js index 4efbaa7..7c5faae 100644 --- a/bin/run-s/main.js +++ b/bin/run-s/main.js @@ -49,6 +49,7 @@ module.exports = function npmRunAll(args, stdout, stderr) { packageConfig: argv.packageConfig, silent: argv.silent, arguments: argv.rest, + npmPath: argv.npmPath, } ) diff --git a/docs/node-api.md b/docs/node-api.md index a9de490..68c1ead 100644 --- a/docs/node-api.md +++ b/docs/node-api.md @@ -48,6 +48,9 @@ Run npm-scripts. - **options.maxParallel** `number` -- The maximum number of parallelism. Default is `Number.POSITIVE_INFINITY`. + - **options.npmPath** `string` -- + The path to npm. + Default is `process.env.NPM_EXECPATH` or `"npm"`. - **options.packageConfig** `object|null` -- The map-like object to overwrite package configs. Keys are package names. diff --git a/docs/npm-run-all.md b/docs/npm-run-all.md index 4118eec..9379c9d 100644 --- a/docs/npm-run-all.md +++ b/docs/npm-run-all.md @@ -38,6 +38,11 @@ Options: non-zero code if one or more tasks threw error(s) --max-parallel - Set the maximum number of parallelism. Default is unlimited. + --npm-path - - - Set the path to npm. Default is the value of + environment variable NPM_EXECPATH. + If the variable is not defined, then it's "npm." + In this case, the "npm" command must be found in + environment variable PATH. -l, --print-label - - - - Set the flag to print the task name as a prefix on each line of output. Tools in tasks may stop coloring their output if this option was given. diff --git a/docs/run-p.md b/docs/run-p.md index d74dbe7..6fb99fe 100644 --- a/docs/run-p.md +++ b/docs/run-p.md @@ -37,6 +37,11 @@ Options: threw error(s). --max-parallel - Set the maximum number of parallelism. Default is unlimited. + --npm-path - - - Set the path to npm. Default is the value of + environment variable NPM_EXECPATH. + If the variable is not defined, then it's "npm." + In this case, the "npm" command must be found in + environment variable PATH. -l, --print-label - - - - Set the flag to print the task name as a prefix on each line of output. Tools in tasks may stop coloring their output if this option was given. diff --git a/docs/run-s.md b/docs/run-s.md index db95f9c..2e394a8 100644 --- a/docs/run-s.md +++ b/docs/run-s.md @@ -35,6 +35,11 @@ Options: tasks even if a task threw an error. 'run-s' itself will exit with non-zero code if one or more tasks threw error(s). + --npm-path - - - Set the path to npm. Default is the value of + environment variable NPM_EXECPATH. + If the variable is not defined, then it's "npm." + In this case, the "npm" command must be found in + environment variable PATH. -l, --print-label - - - - Set the flag to print the task name as a prefix on each line of output. Tools in tasks may stop coloring their output if this option was given. diff --git a/lib/index.js b/lib/index.js index 9b7e1df..c56ef67 100644 --- a/lib/index.js +++ b/lib/index.js @@ -199,6 +199,12 @@ function maxLength(length, name) { * @param {boolean} options.printName - * The flag to print task names before running each task. * Default is `false`. + * @param {number} options.maxParallel - + * The maximum number of parallelism. + * Default is unlimited. + * @param {string} options.npmPath - + * The path to npm. + * Default is `process.env.NPM_EXECPATH`. * @returns {Promise} * A promise object which becomes fullfilled when all npm-scripts are completed. */ @@ -217,6 +223,7 @@ module.exports = function npmRunAll(patternOrPatterns, options) { const printName = Boolean(options && options.printName) const race = Boolean(options && options.race) const maxParallel = parallel ? ((options && options.maxParallel) || 0) : 1 + const npmPath = options && options.npmPath try { const patterns = parsePatterns(patternOrPatterns, args) if (patterns.length === 0) { @@ -265,6 +272,7 @@ module.exports = function npmRunAll(patternOrPatterns, options) { packageInfo: x.packageInfo, race, maxParallel, + npmPath, }) }) } diff --git a/lib/run-task.js b/lib/run-task.js index bd95a31..e240f6d 100644 --- a/lib/run-task.js +++ b/lib/run-task.js @@ -10,6 +10,7 @@ // Requirements //------------------------------------------------------------------------------ +const path = require("path") const chalk = require("chalk") const parseArgs = require("shell-quote").parse const padEnd = require("string.prototype.padend") @@ -123,6 +124,7 @@ module.exports = function runTask(task, options) { const stdinKind = detectStreamKind(stdin, process.stdin) const stdoutKind = detectStreamKind(stdout, process.stdout) const stderrKind = detectStreamKind(stderr, process.stderr) + const spawnOptions = {stdio: [stdinKind, stdoutKind, stderrKind]} // Print task name. if (options.printName && stdout != null) { @@ -133,12 +135,29 @@ module.exports = function runTask(task, options) { )) } - // Execute. - cp = spawn( - "npm", - ["run"].concat(options.prefixOptions, parseArgs(task)), - {stdio: [stdinKind, stdoutKind, stderrKind]} - ) + if (path.extname(options.npmPath || "a.js") === ".js") { + const npmPath = options.npmPath || process.env.NPM_EXECPATH //eslint-disable-line no-process-env + const execPath = npmPath ? process.execPath : "npm" + const spawnArgs = [].concat( + npmPath ? [npmPath, "run"] : ["run"], + options.prefixOptions, + parseArgs(task) + ) + + // Execute. + cp = spawn(execPath, spawnArgs, spawnOptions) + } + else { + const execPath = options.npmPath + const spawnArgs = [].concat( + ["run"], + options.prefixOptions, + parseArgs(task) + ) + + // Execute. + cp = spawn(execPath, spawnArgs, spawnOptions) + } // Piping stdio. if (stdinKind === "pipe") { diff --git a/test-workspace/package.json b/test-workspace/package.json index 5686a3e..0ef009d 100644 --- a/test-workspace/package.json +++ b/test-workspace/package.json @@ -33,7 +33,10 @@ "test-task:issue14:win32": "..\\node_modules\\.bin\\rimraf build && mkdir %npm_package_config_DEST% && cd build", "test-task:issue14:posix": "../node_modules/.bin/rimraf build && mkdir $npm_package_config_DEST && cd build", "test-task:echo": "node tasks/echo.js", - "test-task:dump": "node tasks/dump.js" + "test-task:dump": "node tasks/dump.js", + "test-task:nest-append:npm-run-all": "node ../bin/npm-run-all/index.js test-task:append", + "test-task:nest-append:run-s": "node ../bin/run-s/index.js test-task:append", + "test-task:nest-append:run-p": "node ../bin/run-p/index.js test-task:append" }, "repository": { "type": "git", diff --git a/test/lib/util.js b/test/lib/util.js index 8794600..c1cee1d 100644 --- a/test/lib/util.js +++ b/test/lib/util.js @@ -22,6 +22,7 @@ const FILE_NAME = "test.txt" const NPM_RUN_ALL = path.resolve(__dirname, "../../bin/npm-run-all/index.js") const RUN_P = path.resolve(__dirname, "../../bin/run-p/index.js") const RUN_S = path.resolve(__dirname, "../../bin/run-s/index.js") +const YARN = path.resolve(__dirname, "../../node_modules/yarn/bin/yarn.js") /** * Spawns the given script with the given arguments. @@ -40,6 +41,7 @@ function spawn(filePath, args, stdout, stderr) { [filePath].concat(args), {stdio: "pipe"} ) + const out = new BufferStream() const error = new BufferStream() if (stdout != null) { @@ -51,6 +53,7 @@ function spawn(filePath, args, stdout, stderr) { else { child.stderr.pipe(error) } + child.stdout.pipe(out) child.on("close", (exitCode) => { if (exitCode) { reject(new Error(error.value || "Exited with non-zero code.")) @@ -161,3 +164,18 @@ module.exports.runPar = function runPar(args, stdout, stderr) { module.exports.runSeq = function runSeq(args, stdout, stderr) { return spawn(RUN_S, args, stdout, stderr) } + +/** + * Executes `yarn run` with the given arguments. + * + * @param {string[]} args - The arguments to execute. + * @param {Writable} [stdout] - The writable stream to receive stdout. + * @param {Writable} [stderr] - The writable stream to receive stderr. + * @returns {Promise} The promise which becomes fulfilled if the child + * process finished. + */ +module.exports.runWithYarn = function runWithYarn(args, stdout, stderr) { + return spawn(YARN, ["run"].concat(args), stdout, stderr) +} + +module.exports.YARN_PATH = YARN