diff options
Diffstat (limited to 'node_modules/cross-spawn')
-rw-r--r-- | node_modules/cross-spawn/CHANGELOG.md | 6 | ||||
-rw-r--r-- | node_modules/cross-spawn/LICENSE | 19 | ||||
-rw-r--r-- | node_modules/cross-spawn/README.md | 85 | ||||
-rw-r--r-- | node_modules/cross-spawn/index.js | 59 | ||||
-rw-r--r-- | node_modules/cross-spawn/lib/enoent.js | 73 | ||||
-rw-r--r-- | node_modules/cross-spawn/lib/parse.js | 113 | ||||
-rw-r--r-- | node_modules/cross-spawn/lib/util/escapeArgument.js | 30 | ||||
-rw-r--r-- | node_modules/cross-spawn/lib/util/escapeCommand.js | 12 | ||||
-rw-r--r-- | node_modules/cross-spawn/lib/util/hasEmptyArgumentBug.js | 18 | ||||
-rw-r--r-- | node_modules/cross-spawn/lib/util/readShebang.js | 37 | ||||
-rw-r--r-- | node_modules/cross-spawn/lib/util/resolveCommand.js | 31 | ||||
-rw-r--r-- | node_modules/cross-spawn/package.json | 87 |
12 files changed, 570 insertions, 0 deletions
diff --git a/node_modules/cross-spawn/CHANGELOG.md b/node_modules/cross-spawn/CHANGELOG.md new file mode 100644 index 0000000..f1298a8 --- /dev/null +++ b/node_modules/cross-spawn/CHANGELOG.md @@ -0,0 +1,6 @@ +## 5.0.0 - 2016-10-30 + +- Add support for `options.shell` +- Improve parsing of shebangs by using [`shebang-command`](https://github.com/kevva/shebang-command) module +- Refactor some code to make it more clear +- Update README caveats diff --git a/node_modules/cross-spawn/LICENSE b/node_modules/cross-spawn/LICENSE new file mode 100644 index 0000000..db5e914 --- /dev/null +++ b/node_modules/cross-spawn/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 IndigoUnited + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/cross-spawn/README.md b/node_modules/cross-spawn/README.md new file mode 100644 index 0000000..dde730d --- /dev/null +++ b/node_modules/cross-spawn/README.md @@ -0,0 +1,85 @@ +# cross-spawn + +[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Build status][appveyor-image]][appveyor-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url] + +[npm-url]:https://npmjs.org/package/cross-spawn +[downloads-image]:http://img.shields.io/npm/dm/cross-spawn.svg +[npm-image]:http://img.shields.io/npm/v/cross-spawn.svg +[travis-url]:https://travis-ci.org/IndigoUnited/node-cross-spawn +[travis-image]:http://img.shields.io/travis/IndigoUnited/node-cross-spawn/master.svg +[appveyor-url]:https://ci.appveyor.com/project/satazor/node-cross-spawn +[appveyor-image]:https://img.shields.io/appveyor/ci/satazor/node-cross-spawn/master.svg +[david-dm-url]:https://david-dm.org/IndigoUnited/node-cross-spawn +[david-dm-image]:https://img.shields.io/david/IndigoUnited/node-cross-spawn.svg +[david-dm-dev-url]:https://david-dm.org/IndigoUnited/node-cross-spawn#info=devDependencies +[david-dm-dev-image]:https://img.shields.io/david/dev/IndigoUnited/node-cross-spawn.svg + +A cross platform solution to node's spawn and spawnSync. + + +## Installation + +`$ npm install cross-spawn` + +If you are using `spawnSync` on node 0.10 or older, you will also need to install `spawn-sync`: + +`$ npm install spawn-sync` + + +## Why + +Node has issues when using spawn on Windows: + +- It ignores [PATHEXT](https://github.com/joyent/node/issues/2318) +- It does not support [shebangs](http://pt.wikipedia.org/wiki/Shebang) +- No `options.shell` support on node < v6 +- It does not allow you to run `del` or `dir` + +All these issues are handled correctly by `cross-spawn`. +There are some known modules, such as [win-spawn](https://github.com/ForbesLindesay/win-spawn), that try to solve this but they are either broken or provide faulty escaping of shell arguments. + + +## Usage + +Exactly the same way as node's [`spawn`](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) or [`spawnSync`](https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options), so it's a drop in replacement. + + +```js +var spawn = require('cross-spawn'); + +// Spawn NPM asynchronously +var child = spawn('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' }); + +// Spawn NPM synchronously +var results = spawn.sync('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' }); +``` + + +## Caveats + +#### `options.shell` as an alternative to `cross-spawn` + +Starting from node v6, `spawn` has a `shell` option that allows you run commands from within a shell. This new option solves most of the problems that `cross-spawn` attempts to solve, but: + +- It's not supported in node < v6 +- It has no support for shebangs on Windows +- You must manually escape the command and arguments which is very error prone, specially when passing user input + +If you are using the `shell` option to spawn a command in a cross platform way, consider using `cross-spawn` instead. You have been warned. + + +#### Shebangs + +While `cross-spawn` handles shebangs on Windows, its support is limited: e.g.: it doesn't handle arguments after the path, e.g.: `#!/bin/bash -e`. + +Remember to always test your code on Windows! + + +## Tests + +`$ npm test` + + +## License + +Released under the [MIT License](http://www.opensource.org/licenses/mit-license.php). diff --git a/node_modules/cross-spawn/index.js b/node_modules/cross-spawn/index.js new file mode 100644 index 0000000..7814a96 --- /dev/null +++ b/node_modules/cross-spawn/index.js @@ -0,0 +1,59 @@ +'use strict'; + +var cp = require('child_process'); +var parse = require('./lib/parse'); +var enoent = require('./lib/enoent'); + +var cpSpawnSync = cp.spawnSync; + +function spawn(command, args, options) { + var parsed; + var spawned; + + // Parse the arguments + parsed = parse(command, args, options); + + // Spawn the child process + spawned = cp.spawn(parsed.command, parsed.args, parsed.options); + + // Hook into child process "exit" event to emit an error if the command + // does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 + enoent.hookChildProcess(spawned, parsed); + + return spawned; +} + +function spawnSync(command, args, options) { + var parsed; + var result; + + if (!cpSpawnSync) { + try { + cpSpawnSync = require('spawn-sync'); // eslint-disable-line global-require + } catch (ex) { + throw new Error( + 'In order to use spawnSync on node 0.10 or older, you must ' + + 'install spawn-sync:\n\n' + + ' npm install spawn-sync --save' + ); + } + } + + // Parse the arguments + parsed = parse(command, args, options); + + // Spawn the child process + result = cpSpawnSync(parsed.command, parsed.args, parsed.options); + + // Analyze if the command does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 + result.error = result.error || enoent.verifyENOENTSync(result.status, parsed); + + return result; +} + +module.exports = spawn; +module.exports.spawn = spawn; +module.exports.sync = spawnSync; + +module.exports._parse = parse; +module.exports._enoent = enoent; 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; diff --git a/node_modules/cross-spawn/package.json b/node_modules/cross-spawn/package.json new file mode 100644 index 0000000..eaf13b5 --- /dev/null +++ b/node_modules/cross-spawn/package.json @@ -0,0 +1,87 @@ +{ + "_args": [ + [ + "[email protected]", + "/home/dstaesse/git/website" + ] + ], + "_development": true, + "_from": "[email protected]", + "_id": "[email protected]", + "_inBundle": false, + "_integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "_location": "/cross-spawn", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "[email protected]", + "name": "cross-spawn", + "escapedName": "cross-spawn", + "rawSpec": "5.1.0", + "saveSpec": null, + "fetchSpec": "5.1.0" + }, + "_requiredBy": [ + "/execa" + ], + "_resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "_spec": "5.1.0", + "_where": "/home/dstaesse/git/website", + "author": { + "name": "IndigoUnited", + "email": "[email protected]", + "url": "http://indigounited.com" + }, + "bugs": { + "url": "https://github.com/IndigoUnited/node-cross-spawn/issues/" + }, + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "description": "Cross platform child_process#spawn and child_process#spawnSync", + "devDependencies": { + "@satazor/eslint-config": "^3.0.0", + "eslint": "^3.0.0", + "expect.js": "^0.3.0", + "glob": "^7.0.0", + "mkdirp": "^0.5.1", + "mocha": "^3.0.2", + "once": "^1.4.0", + "rimraf": "^2.5.0" + }, + "files": [ + "index.js", + "lib" + ], + "homepage": "https://github.com/IndigoUnited/node-cross-spawn#readme", + "keywords": [ + "spawn", + "spawnSync", + "windows", + "cross", + "platform", + "path", + "ext", + "path-ext", + "path_ext", + "shebang", + "hashbang", + "cmd", + "execute" + ], + "license": "MIT", + "main": "index.js", + "name": "cross-spawn", + "repository": { + "type": "git", + "url": "git://github.com/IndigoUnited/node-cross-spawn.git" + }, + "scripts": { + "lint": "eslint '{*.js,lib/**/*.js,test/**/*.js}'", + "test": "node test/prepare && mocha --bail test/test" + }, + "version": "5.1.0" +} |