Files
meteor/tools/processes.js
ekatek 8bf5db2de0 eliminate legacy stdout.write and stderr.write functions from Console
Now that we no longer have an automatic newline on printing, we don't have to support
the awkward legacy functions that the Console used to provide. Eliminating.
2014-12-06 17:42:07 -08:00

124 lines
3.2 KiB
JavaScript

var Future = require('fibers/future');
var _ = require('underscore');
var child_process = require('child_process');
var Console = require('./console.js').Console;
var processes = exports;
var RunCommand = function (command, args, options) {
var self = this;
var defaultOptions = {};
// Make stdin,stdout & stderr pipes (not shared)
defaultOptions.stdio = ['pipe', 'pipe', 'pipe'];
defaultOptions.env = process.env;
defaultOptions.checkExitCode = true;
options = _.extend(defaultOptions, options);
self.command = command;
self.args = args;
self.options = options;
self.exitFuture = new Future();
self.exitCode = undefined;
self.stdout = '';
self.stderr = '';
};
_.extend(RunCommand.prototype, {
start: function () {
var self = this;
if (self.process) {
throw new Error("Process already started");
}
if (Console.isDebugEnabled()) {
var envString = '';
var defaultEnv = process.env;
if (self.options.env) {
_.each(self.options.env, function (v,k) {
var defaultV = defaultEnv[k];
if (v !== defaultV) {
envString += k + "=" + v + " ";
}
});
}
Console.debug("Running command", envString, self.command, self.args.join(' '));
}
self.process = child_process.spawn( self.command,
self.args,
self.options);
self.process.on('close', function (exitCode) {
self.exitCode = exitCode;
if (self.options.checkExitCode && exitCode != 0) {
console.log("Unexpected exit code", exitCode, "from", self.command, self.args, "\nstdout:\n", self.stdout, "\nstderr:\n", self.stderr);
}
self.exitFuture.isResolved() || self.exitFuture['return'](exitCode);
});
self.process.on('error', function (err) {
Console.debug("Error while running command", err);
self.exitError = err;
self.exitFuture.isResolved() || self.exitFuture['throw'](err);
});
self.process.stdout.on('data', function (data) {
self.stdout = self.stdout + data;
if (self.options.pipeOutput) {
Console.rawInfo(data);
}
if (self.options.onStdout) {
self.options.onStdout(data);
}
});
self.process.stderr.on('data', function (data) {
self.stderr = self.stderr + data;
if (self.options.pipeOutput) {
Console.rawError(data);
}
if (self.options.onStderr) {
self.options.onStderr(data);
}
});
self.stdin = self.process.stdin;
if (self.options.stdin) {
self.stdin.write(self.options.stdin);
}
if (self.options.detached) {
self.process.unref();
}
},
waitForExit: function () {
var self = this;
return self.exitFuture.wait();
},
kill: function () {
var self = this;
self.process.kill();
},
run: function () {
var self = this;
self.start();
if (self.options.detached) {
Console.debug("run called on detached process; won't wait");
return undefined;
}
self.waitForExit();
return { stdout: self.stdout, stderr: self.stderr, exitCode: self.exitCode };
}
});
exports.RunCommand = RunCommand;