Files
atom/src/buffered-process.coffee
2013-09-20 10:03:02 -07:00

88 lines
2.3 KiB
CoffeeScript

ChildProcess = require 'child_process'
path = require 'path'
_ = require './underscore-extensions'
# Public: A wrapper which provides buffering for ChildProcess.
module.exports =
class BufferedProcess
process: null
killed: false
# Executes the given command.
#
# * options
# + command:
# The command to execute.
# + args:
# The arguments for the given command.
# + options:
# The options to pass to ChildProcess.
# + stdout:
# The callback to receive stdout data.
# + stderr:
# The callback to receive stderr data.
# + exit:
# The callback to receive exit status.
constructor: ({command, args, options, stdout, stderr, exit}={}) ->
options ?= {}
@process = ChildProcess.spawn(command, args, options)
stdoutClosed = true
stderrClosed = true
processExited = true
exitCode = 0
triggerExitCallback = ->
return if @killed
if stdoutClosed and stderrClosed and processExited
exit?(exitCode)
if stdout
stdoutClosed = false
@bufferStream @process.stdout, stdout, ->
stdoutClosed = true
triggerExitCallback()
if stderr
stderrClosed = false
@bufferStream @process.stderr, stderr, ->
stderrClosed = true
triggerExitCallback()
if exit
processExited = false
@process.on 'exit', (code) ->
exitCode = code
processExited = true
triggerExitCallback()
# Private: Helper method to pass data line by line.
#
# * stream:
# The Stream to read from.
# * onLines:
# The callback to call with each line of data.
# * onDone:
# The callback to call when the stream has closed.
bufferStream: (stream, onLines, onDone) ->
stream.setEncoding('utf8')
buffered = ''
stream.on 'data', (data) =>
return if @killed
buffered += data
lastNewlineIndex = buffered.lastIndexOf('\n')
if lastNewlineIndex isnt -1
onLines(buffered.substring(0, lastNewlineIndex + 1))
buffered = buffered.substring(lastNewlineIndex + 1)
stream.on 'close', =>
return if @killed
onLines(buffered) if buffered.length > 0
onDone()
# Public: Terminates the process.
kill: ->
@killed = true
@process.kill()
@process = null