Skip to content

Commit 53b0b58

Browse files
committed
Replace child_process.exec with child_process.spawn
1 parent 4cf8e9b commit 53b0b58

File tree

4 files changed

+43
-104
lines changed

4 files changed

+43
-104
lines changed

README.md

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,7 @@ type: `String`
9191
default: ``Command `<%= command %>` failed with exit code <%= error.code %>``
9292

9393
You can add a custom error message for when the command fails.
94-
This can be a [template][] which can be interpolated with the current `command`, some [file][] info (e.g. `file.path`) and some [error][] info (e.g. `error.code`).
95-
96-
[error]: http://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback
94+
This can be a [template][] which can be interpolated with the current `command`, some [file][] info (e.g. `file.path`) and some error info (e.g. `error.code`).
9795

9896
#### options.ignoreErrors
9997

@@ -111,14 +109,6 @@ default: `false`
111109

112110
By default, it will print the command output.
113111

114-
#### options.interactive
115-
116-
type: `Boolean`
117-
118-
default: `false`
119-
120-
Turn it on only if you need to run some interactive commands.
121-
122112
#### options.cwd
123113

124114
type: `String`
@@ -135,24 +125,6 @@ type: `Object`
135125

136126
The data that can be accessed in template.
137127

138-
#### options.maxBuffer
139-
140-
type: `Number`
141-
142-
default: 16MB(16 * 1024 * 1024)
143-
144-
You won't need to set this option unless you encounter a "stdout maxBuffer exceeded" error.
145-
146-
For example, setting it to `16 * 1024 * 1024` will result in 16MB.
147-
148-
#### options.timeout
149-
150-
type: `Number`
151-
152-
default: undefined (no timeout)
153-
154-
The maximum amount of time in milliseconds the process is allowed to run.
155-
156128
#### options.env
157129

158130
type: `Object`

gulpfile.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ var paths = {
55
js: ['*.js', 'test/*.js']
66
}
77

8-
gulp.task('test', shell.task('mocha -c'))
8+
gulp.task('test', shell.task('mocha'))
99

10-
gulp.task('coverage', ['test'], shell.task('istanbul cover _mocha -- -c'))
10+
gulp.task('coverage', ['test'], shell.task('istanbul cover _mocha'))
1111

1212
gulp.task('coveralls', ['coverage'], shell.task('cat coverage/lcov.info | coveralls'))
1313

index.js

Lines changed: 18 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
var _ = require('lodash')
22
var async = require('async')
3-
var exec = require('child_process').exec
43
var gutil = require('gulp-util')
54
var path = require('path')
5+
var spawn = require('child_process').spawn
66
var through = require('through2')
77

88
var PLUGIN_NAME = 'gulp-shell'
@@ -25,9 +25,7 @@ function normalizeOptions (options) {
2525
ignoreErrors: false,
2626
errorMessage: 'Command `<%= command %>` failed with exit code <%= error.code %>',
2727
quiet: false,
28-
interactive: false,
29-
cwd: process.cwd(),
30-
maxBuffer: 16 * 1024 * 1024
28+
cwd: process.cwd()
3129
}, options)
3230

3331
var pathToBin = path.join(process.cwd(), 'node_modules', '.bin')
@@ -47,44 +45,28 @@ function runCommands (commands, options, file, done) {
4745
gutil.log(gutil.colors.cyan(command))
4846
}
4947

50-
var child = exec(command, {
48+
var child = spawn(command, {
5149
env: options.env,
5250
cwd: gutil.template(options.cwd, context),
53-
maxBuffer: options.maxBuffer,
54-
timeout: options.timeout
55-
}, function (error, stdout, stderr) {
56-
if (options.interactive) {
57-
process.stdin.unpipe(child.stdin)
58-
process.stdin.resume()
59-
process.stdin.pause()
60-
}
61-
62-
if (error && !options.ignoreErrors) {
63-
error.stdout = stdout
64-
error.stderr = stderr
65-
66-
var errorContext = _.extend({
67-
command: command,
68-
file: file,
69-
error: error
70-
}, options.templateData)
51+
shell: true,
52+
stdio: options.quiet ? 'ignore' : 'inherit'
53+
})
7154

72-
error.message = gutil.template(options.errorMessage, errorContext)
55+
child.on('exit', function (code) {
56+
if (code === 0 || options.ignoreErrors) {
57+
return done()
7358
}
7459

75-
done(options.ignoreErrors ? null : error)
76-
})
60+
var context = _.extend({
61+
command: command,
62+
file: file,
63+
error: {code: code}
64+
}, options.templateData)
7765

78-
if (options.interactive) {
79-
process.stdin.resume()
80-
process.stdin.setEncoding('utf8')
81-
process.stdin.pipe(child.stdin)
82-
}
66+
var message = gutil.template(options.errorMessage, context)
8367

84-
if (!options.quiet) {
85-
child.stdout.pipe(process.stdout)
86-
child.stderr.pipe(process.stderr)
87-
}
68+
done(new gutil.PluginError(PLUGIN_NAME, message))
69+
})
8870
}, done)
8971
}
9072

@@ -97,10 +79,7 @@ function shell (commands, options) {
9779

9880
runCommands(commands, options, file, function (error) {
9981
if (error) {
100-
self.emit('error', new gutil.PluginError({
101-
plugin: PLUGIN_NAME,
102-
message: error.message
103-
}))
82+
self.emit('error', error)
10483
} else {
10584
self.push(file)
10685
}

test/index.js

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@ var expect = require('chai').expect
66

77
var shell = require('..')
88

9-
var originalStdoutWrite = process.stdout.write
10-
function expectToOutput (expected, done) {
11-
process.stdout.write = function (actual) {
12-
process.stdout.write = originalStdoutWrite
13-
expect(actual.toLowerCase()).to.include(expected.toLowerCase())
14-
done()
15-
}
9+
function expectToBeOk (stream, done) {
10+
stream
11+
.on('error', done)
12+
.on('data', function () { done() })
1613
}
1714

1815
describe('gulp-shell(commands, options)', function () {
@@ -42,17 +39,21 @@ describe('gulp-shell(commands, options)', function () {
4239
})
4340

4441
it('executes command after interpolation', function (done) {
45-
var stream = shell(['echo <%= file.path %>'])
42+
var stream = shell([
43+
'test <%= file.path %> = ' + fakeFile.path
44+
])
4645

47-
expectToOutput(fakeFile.path, done)
46+
expectToBeOk(stream, done)
4847

4948
stream.write(fakeFile)
5049
})
5150

5251
it('prepends `./node_modules/.bin` to `PATH`', function (done) {
53-
var stream = shell(['echo $PATH'])
52+
var stream = shell([
53+
'echo $PATH | grep -q "' + join(process.cwd(), 'node_modules/.bin') + '"'
54+
])
5455

55-
expectToOutput(join(process.cwd(), 'node_modules/.bin'), done)
56+
expectToBeOk(stream, done)
5657

5758
stream.write(fakeFile)
5859
})
@@ -62,9 +63,8 @@ describe('gulp-shell(commands, options)', function () {
6263
var task = shell.task(['echo hello world'])
6364

6465
expect(task).to.be.a('function')
65-
expectToOutput('hello world', done)
6666

67-
task()
67+
task(done)
6868
})
6969
})
7070

@@ -99,23 +99,7 @@ describe('gulp-shell(commands, options)', function () {
9999
it("won't output anything when `quiet` == true", function (done) {
100100
var stream = shell(['echo cannot see me!'], {quiet: true})
101101

102-
expectToOutput('this should not match anything!', done)
103-
104-
stream.on('data', function () {
105-
process.stdout.write = originalStdoutWrite
106-
done()
107-
})
108-
109-
stream.write(fakeFile)
110-
})
111-
})
112-
113-
describe('interactive', function () {
114-
it('reads input when `interactive` == true', function (done) {
115-
var stream = shell(['read s; echo $s'], {interactive: true})
116-
117-
process.stdin.push('something\n')
118-
expectToOutput('something', done)
102+
expectToBeOk(stream, done)
119103

120104
stream.write(fakeFile)
121105
})
@@ -150,17 +134,21 @@ describe('gulp-shell(commands, options)', function () {
150134

151135
describe('cwd', function () {
152136
it('sets the current working directory when `cwd` is a string', function (done) {
153-
var stream = shell(['pwd'], {cwd: '..'})
137+
var stream = shell([
138+
'test $PWD = ' + join(__dirname, '../..')
139+
], {cwd: '..'})
154140

155-
expectToOutput(join(__dirname, '../..'), done)
141+
expectToBeOk(stream, done)
156142

157143
stream.write(fakeFile)
158144
})
159145

160146
it('uses the process current working directory when `cwd` is not passed', function (done) {
161-
var stream = shell(['pwd'])
147+
var stream = shell([
148+
'test $PWD = ' + join(__dirname, '..')
149+
])
162150

163-
expectToOutput(join(__dirname, '..'), done)
151+
expectToBeOk(stream, done)
164152

165153
stream.write(fakeFile)
166154
})

0 commit comments

Comments
 (0)