summaryrefslogtreecommitdiff
path: root/deps/npm/node_modules/libnpx/node_modules/yargs/node_modules/os-locale/node_modules/execa/node_modules/cross-spawn/lib/parse.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/node_modules/libnpx/node_modules/yargs/node_modules/os-locale/node_modules/execa/node_modules/cross-spawn/lib/parse.js')
-rw-r--r--deps/npm/node_modules/libnpx/node_modules/yargs/node_modules/os-locale/node_modules/execa/node_modules/cross-spawn/lib/parse.js169
1 files changed, 71 insertions, 98 deletions
diff --git a/deps/npm/node_modules/libnpx/node_modules/yargs/node_modules/os-locale/node_modules/execa/node_modules/cross-spawn/lib/parse.js b/deps/npm/node_modules/libnpx/node_modules/yargs/node_modules/os-locale/node_modules/execa/node_modules/cross-spawn/lib/parse.js
index 77cbb83d2d..10a013625b 100644
--- a/deps/npm/node_modules/libnpx/node_modules/yargs/node_modules/os-locale/node_modules/execa/node_modules/cross-spawn/lib/parse.js
+++ b/deps/npm/node_modules/libnpx/node_modules/yargs/node_modules/os-locale/node_modules/execa/node_modules/cross-spawn/lib/parse.js
@@ -1,90 +1,92 @@
'use strict';
-var fs = require('fs');
-var LRU = require('lru-cache');
-var resolveCommand = require('./resolveCommand');
-var hasBrokenSpawn = require('./hasBrokenSpawn');
+var resolveCommand = require('./util/resolveCommand');
+var hasEmptyArgumentBug = require('./util/hasEmptyArgumentBug');
+var escapeArgument = require('./util/escapeArgument');
+var escapeCommand = require('./util/escapeCommand');
+var readShebang = require('./util/readShebang');
var isWin = process.platform === 'win32';
-var shebangCache = new LRU({ max: 50, maxAge: 30 * 1000 }); // Cache just for 30sec
+var skipShellRegExp = /\.(?:com|exe)$/i;
-function readShebang(command) {
- var buffer;
- var fd;
- var match;
+// Supported in Node >= 6 and >= 4.8
+var supportsShellOption = parseInt(process.version.substr(1).split('.')[0], 10) >= 6 ||
+ parseInt(process.version.substr(1).split('.')[0], 10) === 4 && parseInt(process.version.substr(1).split('.')[1], 10) >= 8;
+
+function parseNonShell(parsed) {
var shebang;
+ var needsShell;
+ var applyQuotes;
- // Check if it is in the cache first
- if (shebangCache.has(command)) {
- return shebangCache.get(command);
+ if (!isWin) {
+ return parsed;
}
- // Read the first 150 bytes from the file
- buffer = new Buffer(150);
-
- try {
- fd = fs.openSync(command, 'r');
- fs.readSync(fd, buffer, 0, 150, 0);
- fs.closeSync(fd);
- } catch (e) { /* empty */ }
-
- // Check if it is a shebang
- match = buffer.toString().trim().match(/#!(.+)/i);
+ // Detect & add support for shebangs
+ parsed.file = resolveCommand(parsed.command);
+ parsed.file = parsed.file || resolveCommand(parsed.command, true);
+ shebang = parsed.file && readShebang(parsed.file);
- if (match) {
- shebang = match[1].replace(/\/usr\/bin\/env\s+/i, ''); // Remove /usr/bin/env
+ if (shebang) {
+ parsed.args.unshift(parsed.file);
+ parsed.command = shebang;
+ needsShell = hasEmptyArgumentBug || !skipShellRegExp.test(resolveCommand(shebang) || resolveCommand(shebang, true));
+ } else {
+ needsShell = hasEmptyArgumentBug || !skipShellRegExp.test(parsed.file);
}
- // Store the shebang in the cache
- shebangCache.set(command, shebang);
+ // If a shell is required, use cmd.exe and take care of escaping everything correctly
+ if (needsShell) {
+ // Escape command & arguments
+ applyQuotes = (parsed.command !== 'echo'); // Do not quote arguments for the special "echo" command
+ parsed.command = escapeCommand(parsed.command);
+ parsed.args = parsed.args.map(function (arg) {
+ return escapeArgument(arg, applyQuotes);
+ });
+
+ // Make use of cmd.exe
+ parsed.args = ['/d', '/s', '/c', '"' + parsed.command + (parsed.args.length ? ' ' + parsed.args.join(' ') : '') + '"'];
+ parsed.command = process.env.comspec || 'cmd.exe';
+ parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped
+ }
- return shebang;
+ return parsed;
}
-function escapeArg(arg, quote) {
- // Convert to string
- arg = '' + arg;
+function parseShell(parsed) {
+ var shellCommand;
- // If we are not going to quote the argument,
- // escape shell metacharacters, including double and single quotes:
- if (!quote) {
- arg = arg.replace(/([\(\)%!\^<>&|;,"'\s])/g, '^$1');
- } else {
- // Sequence of backslashes followed by a double quote:
- // double up all the backslashes and escape the double quote
- arg = arg.replace(/(\\*)"/g, '$1$1\\"');
+ // If node supports the shell option, there's no need to mimic its behavior
+ if (supportsShellOption) {
+ return parsed;
+ }
- // Sequence of backslashes followed by the end of the string
- // (which will become a double quote later):
- // double up all the backslashes
- arg = arg.replace(/(\\*)$/, '$1$1');
+ // Mimic node shell option, see: https://github.com/nodejs/node/blob/b9f6a2dc059a1062776133f3d4fd848c4da7d150/lib/child_process.js#L335
+ shellCommand = [parsed.command].concat(parsed.args).join(' ');
- // All other backslashes occur literally
+ if (isWin) {
+ parsed.command = typeof parsed.options.shell === 'string' ? parsed.options.shell : process.env.comspec || 'cmd.exe';
+ parsed.args = ['/d', '/s', '/c', '"' + shellCommand + '"'];
+ parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped
+ } else {
+ if (typeof parsed.options.shell === 'string') {
+ parsed.command = parsed.options.shell;
+ } else if (process.platform === 'android') {
+ parsed.command = '/system/bin/sh';
+ } else {
+ parsed.command = '/bin/sh';
+ }
- // Quote the whole thing:
- arg = '"' + arg + '"';
+ parsed.args = ['-c', shellCommand];
}
- return arg;
+ return parsed;
}
-function escapeCommand(command) {
- // Do not escape if this command is not dangerous..
- // We do this so that commands like "echo" or "ifconfig" work
- // Quoting them, will make them unaccessible
- return /^[a-z0-9_-]+$/i.test(command) ? command : escapeArg(command, true);
-}
-
-function requiresShell(command) {
- return !/\.(?:com|exe)$/i.test(command);
-}
+// ------------------------------------------------
function parse(command, args, options) {
- var shebang;
- var applyQuotes;
- var file;
- var original;
- var shell;
+ var parsed;
// Normalize arguments, similar to nodejs
if (args && !Array.isArray(args)) {
@@ -94,47 +96,18 @@ function parse(command, args, options) {
args = args ? args.slice(0) : []; // Clone array to avoid changing the original
options = options || {};
- original = command;
-
- if (isWin) {
- // Detect & add support for shebangs
- file = resolveCommand(command);
- file = file || resolveCommand(command, true);
- shebang = file && readShebang(file);
- shell = options.shell || hasBrokenSpawn;
-
- if (shebang) {
- args.unshift(file);
- command = shebang;
- shell = shell || requiresShell(resolveCommand(shebang) || resolveCommand(shebang, true));
- } else {
- shell = shell || requiresShell(file);
- }
- if (shell) {
- // Escape command & arguments
- applyQuotes = (command !== 'echo'); // Do not quote arguments for the special "echo" command
- command = escapeCommand(command);
- args = args.map(function (arg) {
- return escapeArg(arg, applyQuotes);
- });
-
- // Use cmd.exe
- args = ['/s', '/c', '"' + command + (args.length ? ' ' + args.join(' ') : '') + '"'];
- command = process.env.comspec || 'cmd.exe';
-
- // Tell node's spawn that the arguments are already escaped
- options.windowsVerbatimArguments = true;
- }
- }
-
- return {
+ // Build our parsed object
+ parsed = {
command: command,
args: args,
options: options,
- file: file,
- original: original,
+ file: undefined,
+ original: command,
};
+
+ // Delegate further parsing to shell or non-shell
+ return options.shell ? parseShell(parsed) : parseNonShell(parsed);
}
module.exports = parse;