aboutsummaryrefslogtreecommitdiff
path: root/node_modules/cross-spawn/lib
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/cross-spawn/lib')
-rw-r--r--node_modules/cross-spawn/lib/enoent.js73
-rw-r--r--node_modules/cross-spawn/lib/parse.js113
-rw-r--r--node_modules/cross-spawn/lib/util/escapeArgument.js30
-rw-r--r--node_modules/cross-spawn/lib/util/escapeCommand.js12
-rw-r--r--node_modules/cross-spawn/lib/util/hasEmptyArgumentBug.js18
-rw-r--r--node_modules/cross-spawn/lib/util/readShebang.js37
-rw-r--r--node_modules/cross-spawn/lib/util/resolveCommand.js31
7 files changed, 314 insertions, 0 deletions
diff --git a/node_modules/cross-spawn/lib/enoent.js b/node_modules/cross-spawn/lib/enoent.js
new file mode 100644
index 0000000..d0a193a
--- /dev/null
+++ b/node_modules/cross-spawn/lib/enoent.js
@@ -0,0 +1,73 @@
+'use strict';
+
+var isWin = process.platform === 'win32';
+var resolveCommand = require('./util/resolveCommand');
+
+var isNode10 = process.version.indexOf('v0.10.') === 0;
+
+function notFoundError(command, syscall) {
+ var err;
+
+ err = new Error(syscall + ' ' + command + ' ENOENT');
+ err.code = err.errno = 'ENOENT';
+ err.syscall = syscall + ' ' + command;
+
+ return err;
+}
+
+function hookChildProcess(cp, parsed) {
+ var originalEmit;
+
+ if (!isWin) {
+ return;
+ }
+
+ originalEmit = cp.emit;
+ cp.emit = function (name, arg1) {
+ var err;
+
+ // If emitting "exit" event and exit code is 1, we need to check if
+ // the command exists and emit an "error" instead
+ // See: https://github.com/IndigoUnited/node-cross-spawn/issues/16
+ if (name === 'exit') {
+ err = verifyENOENT(arg1, parsed, 'spawn');
+
+ if (err) {
+ return originalEmit.call(cp, 'error', err);
+ }
+ }
+
+ return originalEmit.apply(cp, arguments);
+ };
+}
+
+function verifyENOENT(status, parsed) {
+ if (isWin && status === 1 && !parsed.file) {
+ return notFoundError(parsed.original, 'spawn');
+ }
+
+ return null;
+}
+
+function verifyENOENTSync(status, parsed) {
+ if (isWin && status === 1 && !parsed.file) {
+ return notFoundError(parsed.original, 'spawnSync');
+ }
+
+ // If we are in node 10, then we are using spawn-sync; if it exited
+ // with -1 it probably means that the command does not exist
+ if (isNode10 && status === -1) {
+ parsed.file = isWin ? parsed.file : resolveCommand(parsed.original);
+
+ if (!parsed.file) {
+ return notFoundError(parsed.original, 'spawnSync');
+ }
+ }
+
+ return null;
+}
+
+module.exports.hookChildProcess = hookChildProcess;
+module.exports.verifyENOENT = verifyENOENT;
+module.exports.verifyENOENTSync = verifyENOENTSync;
+module.exports.notFoundError = notFoundError;
diff --git a/node_modules/cross-spawn/lib/parse.js b/node_modules/cross-spawn/lib/parse.js
new file mode 100644
index 0000000..10a0136
--- /dev/null
+++ b/node_modules/cross-spawn/lib/parse.js
@@ -0,0 +1,113 @@
+'use strict';
+
+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 skipShellRegExp = /\.(?:com|exe)$/i;
+
+// 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;
+
+ if (!isWin) {
+ return parsed;
+ }
+
+ // 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 (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);
+ }
+
+ // 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 parsed;
+}
+
+function parseShell(parsed) {
+ var shellCommand;
+
+ // If node supports the shell option, there's no need to mimic its behavior
+ if (supportsShellOption) {
+ return parsed;
+ }
+
+ // Mimic node shell option, see: https://github.com/nodejs/node/blob/b9f6a2dc059a1062776133f3d4fd848c4da7d150/lib/child_process.js#L335
+ shellCommand = [parsed.command].concat(parsed.args).join(' ');
+
+ 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';
+ }
+
+ parsed.args = ['-c', shellCommand];
+ }
+
+ return parsed;
+}
+
+// ------------------------------------------------
+
+function parse(command, args, options) {
+ var parsed;
+
+ // Normalize arguments, similar to nodejs
+ if (args && !Array.isArray(args)) {
+ options = args;
+ args = null;
+ }
+
+ args = args ? args.slice(0) : []; // Clone array to avoid changing the original
+ options = options || {};
+
+ // Build our parsed object
+ parsed = {
+ command: command,
+ args: args,
+ options: options,
+ file: undefined,
+ original: command,
+ };
+
+ // Delegate further parsing to shell or non-shell
+ return options.shell ? parseShell(parsed) : parseNonShell(parsed);
+}
+
+module.exports = parse;
diff --git a/node_modules/cross-spawn/lib/util/escapeArgument.js b/node_modules/cross-spawn/lib/util/escapeArgument.js
new file mode 100644
index 0000000..367263f
--- /dev/null
+++ b/node_modules/cross-spawn/lib/util/escapeArgument.js
@@ -0,0 +1,30 @@
+'use strict';
+
+function escapeArgument(arg, quote) {
+ // Convert to string
+ arg = '' + arg;
+
+ // 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\\"');
+
+ // 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');
+
+ // All other backslashes occur literally
+
+ // Quote the whole thing:
+ arg = '"' + arg + '"';
+ }
+
+ return arg;
+}
+
+module.exports = escapeArgument;
diff --git a/node_modules/cross-spawn/lib/util/escapeCommand.js b/node_modules/cross-spawn/lib/util/escapeCommand.js
new file mode 100644
index 0000000..d9c25b2
--- /dev/null
+++ b/node_modules/cross-spawn/lib/util/escapeCommand.js
@@ -0,0 +1,12 @@
+'use strict';
+
+var escapeArgument = require('./escapeArgument');
+
+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 : escapeArgument(command, true);
+}
+
+module.exports = escapeCommand;
diff --git a/node_modules/cross-spawn/lib/util/hasEmptyArgumentBug.js b/node_modules/cross-spawn/lib/util/hasEmptyArgumentBug.js
new file mode 100644
index 0000000..9f2eba6
--- /dev/null
+++ b/node_modules/cross-spawn/lib/util/hasEmptyArgumentBug.js
@@ -0,0 +1,18 @@
+'use strict';
+
+// See: https://github.com/IndigoUnited/node-cross-spawn/pull/34#issuecomment-221623455
+function hasEmptyArgumentBug() {
+ var nodeVer;
+
+ if (process.platform !== 'win32') {
+ return false;
+ }
+
+ nodeVer = process.version.substr(1).split('.').map(function (num) {
+ return parseInt(num, 10);
+ });
+
+ return (nodeVer[0] === 0 && nodeVer[1] < 12);
+}
+
+module.exports = hasEmptyArgumentBug();
diff --git a/node_modules/cross-spawn/lib/util/readShebang.js b/node_modules/cross-spawn/lib/util/readShebang.js
new file mode 100644
index 0000000..2cf3541
--- /dev/null
+++ b/node_modules/cross-spawn/lib/util/readShebang.js
@@ -0,0 +1,37 @@
+'use strict';
+
+var fs = require('fs');
+var LRU = require('lru-cache');
+var shebangCommand = require('shebang-command');
+
+var shebangCache = new LRU({ max: 50, maxAge: 30 * 1000 }); // Cache just for 30sec
+
+function readShebang(command) {
+ var buffer;
+ var fd;
+ var shebang;
+
+ // Check if it is in the cache first
+ if (shebangCache.has(command)) {
+ return shebangCache.get(command);
+ }
+
+ // 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 */ }
+
+ // Attempt to extract shebang (null is returned if not a shebang)
+ shebang = shebangCommand(buffer.toString());
+
+ // Store the shebang in the cache
+ shebangCache.set(command, shebang);
+
+ return shebang;
+}
+
+module.exports = readShebang;
diff --git a/node_modules/cross-spawn/lib/util/resolveCommand.js b/node_modules/cross-spawn/lib/util/resolveCommand.js
new file mode 100644
index 0000000..b7a9490
--- /dev/null
+++ b/node_modules/cross-spawn/lib/util/resolveCommand.js
@@ -0,0 +1,31 @@
+'use strict';
+
+var path = require('path');
+var which = require('which');
+var LRU = require('lru-cache');
+
+var commandCache = new LRU({ max: 50, maxAge: 30 * 1000 }); // Cache just for 30sec
+
+function resolveCommand(command, noExtension) {
+ var resolved;
+
+ noExtension = !!noExtension;
+ resolved = commandCache.get(command + '!' + noExtension);
+
+ // Check if its resolved in the cache
+ if (commandCache.has(command)) {
+ return commandCache.get(command);
+ }
+
+ try {
+ resolved = !noExtension ?
+ which.sync(command) :
+ which.sync(command, { pathExt: path.delimiter + (process.env.PATHEXT || '') });
+ } catch (e) { /* empty */ }
+
+ commandCache.set(command + '!' + noExtension, resolved);
+
+ return resolved;
+}
+
+module.exports = resolveCommand;