[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