[Pkg-javascript-commits] [node-cross-spawn] 01/09: Imported Upstream version 0.2.6
Ross Gammon
ross-guest at moszumanska.debian.org
Wed Mar 11 22:56:25 UTC 2015
This is an automated email from the git hooks/post-receive script.
ross-guest pushed a commit to branch master
in repository node-cross-spawn.
commit 4ce19902231a7cb6f227b2983fceba1dd79142c6
Author: Ross Gammon <rossgammon at mail.dk>
Date: Wed Mar 11 21:09:18 2015 +0100
Imported Upstream version 0.2.6
---
.editorconfig | 12 +++
.gitignore | 2 +
.jshintrc | 62 ++++++++++++++
.npmignore | 3 +
.travis.yml | 4 +
LICENSE | 19 +++++
README.md | 35 ++++++++
index.js | 115 ++++++++++++++++++++++++++
package.json | 39 +++++++++
test/fixtures/()%!^&|;, | 3 +
test/fixtures/()%!^&|;, .bat | 2 +
test/fixtures/bar space | 3 +
test/fixtures/bar space.bat | 2 +
test/fixtures/echo.js | 5 ++
test/fixtures/exit.js | 1 +
test/fixtures/foo | 3 +
test/fixtures/foo.bat | 2 +
test/fixtures/shebang | 3 +
test/test.js | 192 +++++++++++++++++++++++++++++++++++++++++++
test/util/buffered.js | 30 +++++++
20 files changed, 537 insertions(+)
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..779f99a
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,12 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c755054
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules/
+npm-debug.*
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..2d3e748
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,62 @@
+{
+ "predef": [
+ "console",
+ "describe",
+ "it",
+ "after",
+ "afterEach",
+ "before",
+ "beforeEach"
+ ],
+
+ "indent": 4,
+ "node": true,
+ "devel": true,
+
+ "bitwise": false,
+ "curly": false,
+ "eqeqeq": true,
+ "forin": false,
+ "immed": true,
+ "latedef": false,
+ "newcap": true,
+ "noarg": true,
+ "noempty": false,
+ "nonew": true,
+ "plusplus": false,
+ "regexp": false,
+ "undef": true,
+ "unused": "vars",
+ "quotmark": "single",
+ "strict": false,
+ "trailing": true,
+ "camelcase": true,
+
+ "asi": false,
+ "boss": true,
+ "debug": false,
+ "eqnull": true,
+ "es5": false,
+ "esnext": false,
+ "evil": false,
+ "expr": false,
+ "funcscope": false,
+ "globalstrict": false,
+ "iterator": false,
+ "lastsemic": false,
+ "laxbreak": true,
+ "laxcomma": false,
+ "loopfunc": true,
+ "multistr": false,
+ "onecase": true,
+ "regexdash": false,
+ "scripturl": false,
+ "smarttabs": false,
+ "shadow": false,
+ "sub": false,
+ "supernew": true,
+ "validthis": false,
+
+ "nomen": false,
+ "white": true
+}
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..93f2f73
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,3 @@
+node_modules/
+npm-debug.*
+test/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..4feb925
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+ - '0.10'
+ - '0.12'
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..db5e914
--- /dev/null
+++ b/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/README.md b/README.md
new file mode 100644
index 0000000..55c0b1f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,35 @@
+# cross-spawn [![Build Status](https://travis-ci.org/IndigoUnited/node-cross-spawn.svg?branch=master)](https://travis-ci.org/IndigoUnited/node-cross-spawn)
+
+A cross platform solution to node's spawn.
+
+
+## Installation
+
+`$ npm install cross-spawn`
+
+
+## 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)
+- 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, so it's a drop in replacement.
+
+
+## Tests
+
+`$ npm test`
+
+
+## License
+
+Released under the [MIT License](http://www.opensource.org/licenses/mit-license.php).
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..cfadaee
--- /dev/null
+++ b/index.js
@@ -0,0 +1,115 @@
+var fs = require('fs');
+var path = require('path');
+var cp = require('child_process');
+var LRU = require('lru-cache');
+
+var isWin = process.platform === 'win32';
+var shebangCache = LRU({ max: 50, maxAge: 30 * 1000 });
+
+function readShebang(command) {
+ var buffer;
+ var fd;
+ var match;
+ var shebang;
+
+ // Resolve command to an absolute path if it contains /
+ if (command.indexOf(path.sep) !== -1) {
+ command = path.resolve(command);
+ }
+
+ // Check if its resolved in the cache
+ shebang = shebangCache.get(command);
+ if (shebang) {
+ return shebang;
+ }
+
+ // 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);
+ } catch (e) {}
+
+ // Check if it is a shebang
+ match = buffer.toString().trim().match(/\#\!\/usr\/bin\/env ([^\r\n]+)/i);
+ shebang = match && match[1];
+
+ // Store the shebang in the cache
+ shebangCache.set(command, shebang);
+
+ return shebang;
+}
+
+function escapeArg(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(/([\(\)%!\^<>&|;,"' ])/g, '^$1');
+ } else {
+ // Sequence of backslashes followed by a double quote:
+ // double up all the backslashes and escape the double quote
+ arg = arg.replace(/(\\*)"/gi, '$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;
+}
+
+function escapeCommand(command) {
+ // Escape shell metacharacters:
+ command = command.replace(/([\(\)%!\^<>&|;, ])/g, '^$1');
+
+ return command;
+}
+
+function spawn(command, args, options) {
+ var applyQuotes;
+ var shebang;
+
+ args = args || [];
+ options = options || {};
+
+ // Use node's spawn if not on windows
+ if (!isWin) {
+ return cp.spawn(command, args, options);
+ }
+
+ // Detect & add support for shebangs
+ shebang = readShebang(command);
+ if (shebang) {
+ args.unshift(command);
+ command = shebang;
+ }
+
+ // 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 cp.spawn(command, args, options);
+}
+
+module.exports = spawn;
+module.exports.spawn = spawn;
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..ff17098
--- /dev/null
+++ b/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "cross-spawn",
+ "version": "0.2.6",
+ "description": "Cross platform child_process#spawn",
+ "main": "index.js",
+ "scripts": {
+ "test": "mocha --bail -R spec"
+ },
+ "bugs": {
+ "url": "https://github.com/IndigoUnited/node-cross-spawn/issues/"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/IndigoUnited/node-cross-spawn.git"
+ },
+ "keywords": [
+ "spawn",
+ "windows",
+ "cross",
+ "platform",
+ "path",
+ "ext",
+ "path-ext",
+ "path_ext",
+ "shebang",
+ "hashbang",
+ "cmd",
+ "execute"
+ ],
+ "author": "IndigoUnited <hello at indigounited.com> (http://indigounited.com)",
+ "license": "MIT",
+ "dependencies": {
+ "lru-cache": "^2.5.0"
+ },
+ "devDependencies": {
+ "expect.js": "^0.3.0",
+ "mocha": "^1.20.1"
+ }
+}
diff --git a/test/fixtures/()%!^&|;, b/test/fixtures/()%!^&|;,
new file mode 100755
index 0000000..051009c
--- /dev/null
+++ b/test/fixtures/()%!^&|;,
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+echo special
diff --git a/test/fixtures/()%!^&|;, .bat b/test/fixtures/()%!^&|;, .bat
new file mode 100644
index 0000000..f248e1f
--- /dev/null
+++ b/test/fixtures/()%!^&|;, .bat
@@ -0,0 +1,2 @@
+ at echo off
+echo special
diff --git a/test/fixtures/bar space b/test/fixtures/bar space
new file mode 100755
index 0000000..b492ccc
--- /dev/null
+++ b/test/fixtures/bar space
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+echo bar
diff --git a/test/fixtures/bar space.bat b/test/fixtures/bar space.bat
new file mode 100644
index 0000000..96332af
--- /dev/null
+++ b/test/fixtures/bar space.bat
@@ -0,0 +1,2 @@
+ at echo off
+echo bar
diff --git a/test/fixtures/echo.js b/test/fixtures/echo.js
new file mode 100644
index 0000000..430da7a
--- /dev/null
+++ b/test/fixtures/echo.js
@@ -0,0 +1,5 @@
+var args = process.argv.slice(2);
+
+args.forEach(function (arg, index) {
+ process.stdout.write(arg + (index < args.length - 1 ? '\n' : ''));
+});
diff --git a/test/fixtures/exit.js b/test/fixtures/exit.js
new file mode 100644
index 0000000..ea1a66f
--- /dev/null
+++ b/test/fixtures/exit.js
@@ -0,0 +1 @@
+process.exit(25);
diff --git a/test/fixtures/foo b/test/fixtures/foo
new file mode 100755
index 0000000..17f236c
--- /dev/null
+++ b/test/fixtures/foo
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+echo foo
diff --git a/test/fixtures/foo.bat b/test/fixtures/foo.bat
new file mode 100644
index 0000000..1d98135
--- /dev/null
+++ b/test/fixtures/foo.bat
@@ -0,0 +1,2 @@
+ at echo off
+echo foo
diff --git a/test/fixtures/shebang b/test/fixtures/shebang
new file mode 100755
index 0000000..5650cbd
--- /dev/null
+++ b/test/fixtures/shebang
@@ -0,0 +1,3 @@
+#!/usr/bin/env node
+
+process.stdout.write('shebang works!');
diff --git a/test/test.js b/test/test.js
new file mode 100644
index 0000000..b8260b7
--- /dev/null
+++ b/test/test.js
@@ -0,0 +1,192 @@
+'use strict';
+
+var buffered = require('./util/buffered');
+var expect = require('expect.js');
+
+describe('cross-spawn', function () {
+ it('should support shebang in executables', function (next) {
+ buffered(__dirname + '/fixtures/shebang', function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data).to.equal('shebang works!');
+
+ next();
+ });
+ });
+
+ it('should expand using PATHEXT properly', function (next) {
+ buffered(__dirname + '/fixtures/foo', function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data.trim()).to.equal('foo');
+
+ next();
+ });
+ });
+
+ it('should handle commands with spaces', function (next) {
+ buffered(__dirname + '/fixtures/bar space', function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data.trim()).to.equal('bar');
+
+ next();
+ });
+ });
+
+ it('should handle commands with special shell chars', function (next) {
+ buffered(__dirname + '/fixtures/()%!^&|;, ', function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data.trim()).to.equal('special');
+
+ next();
+ });
+ });
+
+ it('should handle empty arguments', function (next) {
+ buffered('node', [
+ __dirname + '/fixtures/echo',
+ 'foo',
+ '',
+ 'bar'
+ ], function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data).to.equal('foo\n\nbar');
+
+ buffered('echo', [
+ 'foo',
+ '',
+ 'bar'
+ ], function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data.trim()).to.equal('foo bar');
+
+ next();
+ });
+ });
+ });
+
+ it('should handle non-string arguments', function (next) {
+ buffered('node', [
+ __dirname + '/fixtures/echo',
+ 1234
+ ], function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data).to.equal('1234');
+
+ next();
+ });
+ });
+
+ it('should handle arguments with spaces', function (next) {
+ buffered('node', [
+ __dirname + '/fixtures/echo',
+ 'I am',
+ 'André Cruz'
+ ], function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data).to.equal('I am\nAndré Cruz');
+
+ next();
+ });
+ });
+
+ it('should handle arguments with \\"', function (next) {
+ buffered('node', [
+ __dirname + '/fixtures/echo',
+ 'foo',
+ '\\"',
+ 'bar'
+ ], function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data).to.equal('foo\n\\"\nbar');
+
+ next();
+ });
+ });
+
+ it('should handle arguments that end with \\', function (next) {
+ buffered('node', [
+ __dirname + '/fixtures/echo',
+ 'foo',
+ 'bar\\',
+ 'baz'
+ ], function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data).to.equal('foo\nbar\\\nbaz');
+
+ next();
+ });
+ });
+
+ it('should handle arguments that contain shell special chars', function (next) {
+ buffered('node', [
+ __dirname + '/fixtures/echo',
+ 'foo',
+ '()',
+ 'foo',
+ '%!',
+ 'foo',
+ '^<',
+ 'foo',
+ '>&',
+ 'foo',
+ '|;',
+ 'foo',
+ ', ',
+ 'foo'
+ ], function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data).to.equal('foo\n()\nfoo\n%!\nfoo\n^<\nfoo\n>&\nfoo\n|;\nfoo\n, \nfoo');
+
+ next();
+ });
+ });
+
+ it('should handle special arguments when using echo', function (next) {
+ buffered('echo', ['foo\\"foo\\foo&bar"foo\'bar'], function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data.trim()).to.equal('foo\\"foo\\foo&bar"foo\'bar');
+
+ buffered('echo', [
+ 'foo',
+ '()',
+ 'foo',
+ '%!',
+ 'foo',
+ '^<',
+ 'foo',
+ '>&',
+ 'foo',
+ '|;',
+ 'foo',
+ ', ',
+ 'foo'
+ ], function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data.trim()).to.equal('foo () foo %! foo ^< foo >& foo |; foo , foo');
+
+ next();
+ });
+ });
+ });
+
+ it('should give correct exit code', function (next) {
+ buffered('node', [ __dirname + '/fixtures/exit'], function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(25);
+
+ next();
+ });
+ });
+});
diff --git a/test/util/buffered.js b/test/util/buffered.js
new file mode 100644
index 0000000..4659849
--- /dev/null
+++ b/test/util/buffered.js
@@ -0,0 +1,30 @@
+'use strict';
+
+var spawn = require('../../index');
+
+function buffered(command, args, options, callback) {
+ if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+
+ if (typeof args === 'function') {
+ callback = args;
+ args = options = null;
+ }
+
+ var cp = spawn(command, args, options);
+ var data = '';
+
+ cp.stdout.on('data', function (buffer) {
+ data += buffer.toString();
+ });
+
+ cp.on('error', callback);
+
+ cp.on('close', function (code) {
+ callback(null, data, code);
+ });
+}
+
+module.exports = buffered;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-cross-spawn.git
More information about the Pkg-javascript-commits
mailing list