[Pkg-javascript-commits] [node-cross-spawn] 01/04: Imported Upstream version 2.0.0
Ross Gammon
ross-guest at moszumanska.debian.org
Sat Aug 15 20:18:24 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 416d88045f5813ccd8a9a7f3df4a94012744bed3
Author: Ross Gammon <rossgammon at mail.dk>
Date: Sat Aug 15 21:33:30 2015 +0200
Imported Upstream version 2.0.0
---
.editorconfig | 3 +
.gitignore | 1 +
.jshintrc | 2 +-
README.md | 19 +-
appveyor.yml | 28 ++
index.js | 130 ++----
package.json | 13 +-
test/fixtures/{()%!^&|;, .bat => ()%!^&;, .bat} | 0
test/fixtures/bar space.bat | 0
test/fixtures/echo.js | 0
test/fixtures/exit.js | 0
test/fixtures/{()%!^&|;, => exit1} | 2 +-
test/fixtures/exit1.bat | 1 +
test/fixtures/foo.bat | 0
test/fixtures/{()%!^&|;, => prepare_()%!^&;, .sh} | 0
test/fixtures/shebang_enoent | 3 +
test/prepare.js | 14 +
test/test.js | 519 ++++++++++++++-------
test/util/buffered.js | 31 +-
19 files changed, 486 insertions(+), 280 deletions(-)
diff --git a/.editorconfig b/.editorconfig
index 779f99a..fe988fc 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -8,5 +8,8 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
+[.gitignore]
+trim_trailing_whitespace = false
+
[*.md]
trim_trailing_whitespace = false
diff --git a/.gitignore b/.gitignore
index c755054..fc48699 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
node_modules/
npm-debug.*
+test/fixtures/(*
diff --git a/.jshintrc b/.jshintrc
index 2d3e748..5595ed2 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -39,7 +39,7 @@
"es5": false,
"esnext": false,
"evil": false,
- "expr": false,
+ "expr": true,
"funcscope": false,
"globalstrict": false,
"iterator": false,
diff --git a/README.md b/README.md
index 55c0b1f..f94b6a6 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,14 @@
-# cross-spawn [![Build Status](https://travis-ci.org/IndigoUnited/node-cross-spawn.svg?branch=master)](https://travis-ci.org/IndigoUnited/node-cross-spawn)
+# cross-spawn [![Build Status](https://travis-ci.org/IndigoUnited/node-cross-spawn.svg?branch=master)](https://travis-ci.org/IndigoUnited/node-cross-spawn) [![Build status](https://ci.appveyor.com/api/projects/status/ckt1qfvke6mc6pe5/branch/master?svg=true)](https://ci.appveyor.com/project/satazor/node-cross-spawn/branch/master)
-A cross platform solution to node's spawn.
+A cross platform solution to node's spawn and spawnSync.
## Installation
`$ npm install cross-spawn`
+If you're not using the `spawnSync`, you can use [cross-spawn-async](http://github.com/IndigoUnited/node-cross-spawn-async) which doesn't require a build toolchain, see [#18](https://github.com/IndigoUnited/node-cross-spawn/pull/18)
+
## Why
@@ -15,6 +17,7 @@ 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`
+- It does not properly escape arguments with spaces or special characters
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.
@@ -22,7 +25,17 @@ There are some known modules, such as [win-spawn](https://github.com/ForbesLinde
## Usage
-Exactly the same way as node's spawn, so it's a drop in replacement.
+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.
+
+```javascript
+var spawn = require('cross-spawn');
+
+// Spawn NPM asynchronously
+var process = spawn('npm', ['list', '-g', '-depth' '0'], { stdio: 'inherit' });
+
+// Spawn NPM synchronously
+var results = spawn.sync('npm', ['list', '-g', '-depth' '0'], { stdio: 'inherit' });
+```
## Tests
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..22c6f43
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,28 @@
+# appveyor file
+# http://www.appveyor.com/docs/appveyor-yml
+
+# build version format
+version: "{build}"
+
+# fix lineendings in Windows
+init:
+ - git config --global core.autocrlf input
+
+# what combinations to test
+environment:
+ matrix:
+ - nodejs_version: 0.10
+ - nodejs_version: 0.12
+
+# get the latest stable version of Node 0.STABLE.latest
+install:
+ - ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version)
+ - npm install
+
+build: off
+
+test_script:
+ - node --version
+ - npm --version
+ - ps: npm test --no-color # PowerShell
+ - cmd: npm test --no-color
diff --git a/index.js b/index.js
index cfadaee..07b1ba4 100644
--- a/index.js
+++ b/index.js
@@ -1,115 +1,55 @@
-var fs = require('fs');
-var path = require('path');
-var cp = require('child_process');
-var LRU = require('lru-cache');
+'use strict';
-var isWin = process.platform === 'win32';
-var shebangCache = LRU({ max: 50, maxAge: 30 * 1000 });
+var sync = require('spawn-sync');
+var crossSpawn = require('cross-spawn-async');
+var parse = require('cross-spawn-async/lib/parse');
+var enoent = require('cross-spawn-async/lib/enoent');
+var resolveCommand = require('cross-spawn-async/lib/resolveCommand');
-function readShebang(command) {
- var buffer;
- var fd;
- var match;
- var shebang;
+var isWin = process.platform === 'win32';
+var isNode10 = process.version.indexOf('v0.10.') === 0;
- // Resolve command to an absolute path if it contains /
- if (command.indexOf(path.sep) !== -1) {
- command = path.resolve(command);
- }
+function verifySyncENOENT(status, parsed) {
+ // First check against the standard enoent.verifyENOENT
+ var err = enoent.verifyENOENT(status, parsed, 'spawnSync');
- // Check if its resolved in the cache
- shebang = shebangCache.get(command);
- if (shebang) {
- return shebang;
+ if (err) {
+ return err;
}
- // 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');
+ // 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);
- // All other backslashes occur literally
-
- // Quote the whole thing:
- arg = '"' + arg + '"';
+ if (!parsed.file) {
+ err = enoent.notFoundError(parsed.original, 'spawnSync');
+ }
}
- return arg;
-}
-
-function escapeCommand(command) {
- // Escape shell metacharacters:
- command = command.replace(/([\(\)%!\^<>&|;, ])/g, '^$1');
-
- return command;
+ return err;
}
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);
- }
+ return crossSpawn.spawn(command, args, options);
+}
- // Detect & add support for shebangs
- shebang = readShebang(command);
- if (shebang) {
- args.unshift(command);
- command = shebang;
- }
+function spawnSync(command, args, options) {
+ var parsed;
+ var result;
- // 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);
- });
+ // Parse the arguments
+ parsed = parse(command, args, options);
- // Use cmd.exe
- args = ['/s', '/c', '"' + command + (args.length ? ' ' + args.join(' ') : '') + '"'];
- command = process.env.comspec || 'cmd.exe';
+ // Spawn the child process
+ result = sync(parsed.command, parsed.args, parsed.options);
- // Tell node's spawn that the arguments are already escaped
- options.windowsVerbatimArguments = true;
+ // Analyze if the command does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16
+ result.error = result.error || verifySyncENOENT(result.status, parsed);
- return cp.spawn(command, args, options);
+ return result;
}
-module.exports = spawn;
+module.exports = spawn;
module.exports.spawn = spawn;
+module.exports.sync = spawnSync;
diff --git a/package.json b/package.json
index ff17098..b1f2eaa 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
{
"name": "cross-spawn",
- "version": "0.2.6",
- "description": "Cross platform child_process#spawn",
+ "version": "2.0.0",
+ "description": "Cross platform child_process#spawn and child_process#spawnSync",
"main": "index.js",
"scripts": {
- "test": "mocha --bail -R spec"
+ "test": "node test/prepare && mocha --bail -R spec test/test"
},
"bugs": {
"url": "https://github.com/IndigoUnited/node-cross-spawn/issues/"
@@ -15,6 +15,7 @@
},
"keywords": [
"spawn",
+ "spawnSync",
"windows",
"cross",
"platform",
@@ -30,10 +31,12 @@
"author": "IndigoUnited <hello at indigounited.com> (http://indigounited.com)",
"license": "MIT",
"dependencies": {
- "lru-cache": "^2.5.0"
+ "cross-spawn-async": "^2.0.0",
+ "spawn-sync": "^1.0.13"
},
"devDependencies": {
"expect.js": "^0.3.0",
- "mocha": "^1.20.1"
+ "glob": "^5.0.12",
+ "mocha": "^2.2.5"
}
}
diff --git a/test/fixtures/()%!^&|;, .bat b/test/fixtures/()%!^&;, .bat
old mode 100644
new mode 100755
similarity index 100%
rename from test/fixtures/()%!^&|;, .bat
rename to test/fixtures/()%!^&;, .bat
diff --git a/test/fixtures/bar space.bat b/test/fixtures/bar space.bat
old mode 100644
new mode 100755
diff --git a/test/fixtures/echo.js b/test/fixtures/echo.js
old mode 100644
new mode 100755
diff --git a/test/fixtures/exit.js b/test/fixtures/exit.js
old mode 100644
new mode 100755
diff --git a/test/fixtures/()%!^&|;, b/test/fixtures/exit1
similarity index 50%
copy from test/fixtures/()%!^&|;,
copy to test/fixtures/exit1
index 051009c..d87f29e 100755
--- a/test/fixtures/()%!^&|;,
+++ b/test/fixtures/exit1
@@ -1,3 +1,3 @@
#!/bin/bash
-echo special
+exit 1
diff --git a/test/fixtures/exit1.bat b/test/fixtures/exit1.bat
new file mode 100755
index 0000000..379a4c9
--- /dev/null
+++ b/test/fixtures/exit1.bat
@@ -0,0 +1 @@
+exit 1
diff --git a/test/fixtures/foo.bat b/test/fixtures/foo.bat
old mode 100644
new mode 100755
diff --git a/test/fixtures/()%!^&|;, b/test/fixtures/prepare_()%!^&;, .sh
similarity index 100%
rename from test/fixtures/()%!^&|;,
rename to test/fixtures/prepare_()%!^&;, .sh
diff --git a/test/fixtures/shebang_enoent b/test/fixtures/shebang_enoent
new file mode 100755
index 0000000..bd86265
--- /dev/null
+++ b/test/fixtures/shebang_enoent
@@ -0,0 +1,3 @@
+#!/usr/bin/env somecommandthatwillneverexist
+
+echo foo
diff --git a/test/prepare.js b/test/prepare.js
new file mode 100644
index 0000000..addb078
--- /dev/null
+++ b/test/prepare.js
@@ -0,0 +1,14 @@
+var glob = require('glob');
+var fs = require('fs');
+
+var fixturesDir = __dirname + '/fixtures';
+
+glob.sync('prepare_*', { cwd: __dirname + '/fixtures' }).forEach(function (file) {
+ var contents = fs.readFileSync(fixturesDir + '/' + file);
+ var finalFile = file.replace(/^prepare_/, '').replace(/\.sh$/, '');
+
+ fs.writeFileSync(fixturesDir + '/' + finalFile, contents);
+ fs.chmodSync(fixturesDir + '/' + finalFile, 0777);
+
+ process.stdout.write('Copied "' + file + '" to "' + finalFile + '"\n');
+});
diff --git a/test/test.js b/test/test.js
index b8260b7..819f894 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,192 +1,381 @@
'use strict';
+var path = require('path');
+var expect = require('expect.js');
var buffered = require('./util/buffered');
-var expect = require('expect.js');
+var spawn = require('../');
+
+var isWin = process.platform === 'win32';
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!');
+ var methods = ['spawn', 'sync'];
- next();
- });
- });
+ methods.forEach(function (method) {
+ describe(method, function() {
+ it('should support shebang in executables', function (next) {
+ buffered(method, __dirname + '/fixtures/shebang', function (err, data, code) {
+ var envPath;
- 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');
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data).to.equal('shebang works!');
- next();
- });
- });
+ // Test if the actual shebang file is resolved against the PATH
+ envPath = process.env.PATH;
+ process.env.PATH = path.normalize(__dirname + '/fixtures/') + path.delimiter + process.env.PATH;
- 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');
+ buffered(method, 'shebang', function (err, data, code) {
+ process.env.PATH = envPath;
- next();
- });
- });
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data).to.equal('shebang works!');
- 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();
+ });
+ });
+ });
- next();
- });
- });
+ it('should expand using PATHEXT properly', function (next) {
+ buffered(method, __dirname + '/fixtures/foo', function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data.trim()).to.equal('foo');
- 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();
+ 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');
+ it('should handle commands with spaces', function (next) {
+ buffered(method, __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();
- });
- });
+ 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 commands with special shell chars', function (next) {
+ buffered(method, __dirname + '/fixtures/()%!^&;, ', function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data.trim()).to.equal('special');
- 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();
- });
- });
+ 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 empty arguments', function (next) {
+ buffered(method, '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');
- 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();
- });
- });
+ buffered(method, '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');
- 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();
+ 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);
+ it('should handle non-string arguments', function (next) {
+ buffered(method, '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(method, '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(method, '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(method, '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(method, '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(method, '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(method, '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 handle optional args correctly', function (next) {
+ buffered(method, __dirname + '/fixtures/foo', function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+
+ buffered(method, __dirname + '/fixtures/foo', {
+ stdio: ['pipe', 'pipe', 'pipe'],
+ }, function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+
+ buffered(method, __dirname + '/fixtures/foo', null, {
+ stdio: ['pipe', 'pipe', 'pipe'],
+ }, function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+
+ next();
+ });
+ });
+ });
+ });
+
+ it('should not mutate args nor options', function (next) {
+ var args = [];
+ var options = {};
+
+ buffered(method, __dirname + '/fixtures/foo', function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+
+ expect(args).to.have.length(0);
+ expect(Object.keys(options)).to.have.length(0);
+
+ next();
+ });
+ });
+
+ it('should give correct exit code', function (next) {
+ buffered(method, 'node', [__dirname + '/fixtures/exit'], function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(25);
+
+ next();
+ });
+ });
+
+ it('should work with a relative command', function (next) {
+ buffered(method, path.relative(process.cwd(), __dirname + '/fixtures/foo'), function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data.trim()).to.equal('foo');
+
+ if (!isWin) {
+ return next();
+ }
+
+ buffered(method, path.relative(process.cwd(), __dirname + '/fixtures/foo.bat'), function (err, data, code) {
+ expect(err).to.not.be.ok();
+ expect(code).to.be(0);
+ expect(data.trim()).to.equal('foo');
- next();
+ next();
+ });
+ });
+ });
+
+ it('should emit "error" and "close" if command does not exist', function (next) {
+ var errors;
+ var spawned = spawn[method]('somecommandthatwillneverexist');
+
+ this.timeout(5000);
+
+ function assertError(err) {
+ var syscall = method === 'sync' ? 'spawnSync' : 'spawn';
+
+ expect(err).to.be.an(Error);
+ expect(err.message).to.contain(syscall);
+ expect(err.message).to.contain('ENOENT');
+ expect(err.message).to.not.contain('undefined');
+ expect(err.code).to.be('ENOENT');
+ expect(err.errno).to.be('ENOENT');
+ expect(err.syscall).to.contain(syscall);
+ expect(err.syscall).to.not.contain('undefined');
+ }
+
+ if (method === 'spawn') {
+ errors = [];
+
+ spawned
+ .on('error', function (err) {
+ errors.push(err);
+ })
+ .on('exit', function () {
+ spawned.removeAllListeners();
+ next(new Error('Should not emit exit'));
+ })
+ .on('close', function (code, signal) {
+ expect(code).to.not.be(0);
+ expect(signal).to.be(null);
+
+ setTimeout(function () {
+ expect(errors).to.have.length(1);
+ assertError(errors[0]);
+
+ next();
+ }, 1000);
+ });
+ } else {
+ assertError(spawned.error);
+ next();
+ }
+ });
+
+ it('should NOT emit "error" if shebang command does not exist', function (next) {
+ var spawned = spawn[method](__dirname + '/fixtures/shebang_enoent');
+ var exited;
+ var timeout;
+
+ this.timeout(5000);
+
+ if (method === 'spawn') {
+ spawned
+ .on('error', function (err) {
+ spawned.removeAllListeners();
+ clearTimeout(timeout);
+ next(new Error('Should not emit error'));
+ })
+ .on('exit', function () {
+ exited = true;
+ })
+ .on('close', function (code, signal) {
+ expect(code).to.not.be(0);
+ expect(signal).to.be(null);
+ expect(exited).to.be(true);
+
+ timeout = setTimeout(next, 1000);
+ });
+ } else {
+ expect(spawned.error).to.not.be.ok();
+ next();
+ }
+ });
+
+ it('should NOT emit "error" if the command actual exists but exited with 1', function (next) {
+ var spawned = spawn[method](__dirname + '/fixtures/exit1');
+ var exited;
+ var timeout;
+
+ this.timeout(5000);
+
+ if (method === 'spawn') {
+ spawned
+ .on('error', function (err) {
+ spawned.removeAllListeners();
+ clearTimeout(timeout);
+ next(new Error('Should not emit error'));
+ })
+ .on('exit', function () {
+ exited = true;
+ })
+ .on('close', function (code, signal) {
+ expect(code).to.not.be(0);
+ expect(signal).to.be(null);
+ expect(exited).to.be(true);
+
+ timeout = setTimeout(next, 1000);
+ });
+ } else {
+ expect(spawned.error).to.not.be.ok();
+ next();
+ }
+ });
});
});
});
diff --git a/test/util/buffered.js b/test/util/buffered.js
index 4659849..37cd15e 100644
--- a/test/util/buffered.js
+++ b/test/util/buffered.js
@@ -2,7 +2,11 @@
var spawn = require('../../index');
-function buffered(command, args, options, callback) {
+function buffered(method, command, args, options, callback) {
+ var cp;
+ var data;
+ var results;
+
if (typeof options === 'function') {
callback = options;
options = null;
@@ -13,18 +17,25 @@ function buffered(command, args, options, callback) {
args = options = null;
}
- var cp = spawn(command, args, options);
- var data = '';
+ if (method === 'sync') {
+ results = spawn.sync(command, args, options);
+ callback(results.error, results.stdout ? results.stdout.toString() : null, results.status);
+ }
+ else {
+ cp = spawn(command, args, options);
+ data = null;
- cp.stdout.on('data', function (buffer) {
- data += buffer.toString();
- });
+ cp.stdout && cp.stdout.on('data', function(buffer) {
+ data = data || '';
+ data += buffer.toString();
+ });
- cp.on('error', callback);
+ cp.on('error', callback);
- cp.on('close', function (code) {
- callback(null, data, code);
- });
+ 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