var common = require('./common');
var _tempDir = require('./tempdir').tempDir;
var _pwd = require('./pwd');
var path = require('path');
var fs = require('fs');
var child = require('child_process');
var DEFAULT_MAXBUFFER_SIZE = 20 * 1024 * 1024;
var DEFAULT_ERROR_CODE = 1;
common.register('exec', _exec, {
unix: false,
canReceivePipe: true,
wrapOutput: false,
});
function execSync(cmd, opts, pipe) {
if (!common.config.execPath) {
common.error('Unable to find a path to the node binary. Please manually set config.execPath');
}
var tempDir = _tempDir();
var paramsFile = path.resolve(tempDir + '/' + common.randomFileName());
var stderrFile = path.resolve(tempDir + '/' + common.randomFileName());
var stdoutFile = path.resolve(tempDir + '/' + common.randomFileName());
opts = common.extend({
silent: common.config.silent,
cwd: _pwd().toString(),
env: process.env,
maxBuffer: DEFAULT_MAXBUFFER_SIZE,
encoding: 'utf8',
}, opts);
if (fs.existsSync(paramsFile)) common.unlinkSync(paramsFile);
if (fs.existsSync(stderrFile)) common.unlinkSync(stderrFile);
if (fs.existsSync(stdoutFile)) common.unlinkSync(stdoutFile);
opts.cwd = path.resolve(opts.cwd);
var paramsToSerialize = {
command: cmd,
execOptions: opts,
pipe: pipe,
stdoutFile: stdoutFile,
stderrFile: stderrFile,
};
function writeFileLockedDown(filePath, data) {
fs.writeFileSync(filePath, data, {
encoding: 'utf8',
mode: parseInt('600', 8),
});
}
writeFileLockedDown(stdoutFile, '');
writeFileLockedDown(stderrFile, '');
writeFileLockedDown(paramsFile, JSON.stringify(paramsToSerialize));
var execArgs = [
path.join(__dirname, 'exec-child.js'),
paramsFile,
];
if (opts.silent) {
opts.stdio = 'ignore';
} else {
opts.stdio = [0, 1, 2];
}
var code = 0;
try {
delete opts.shell;
child.execFileSync(common.config.execPath, execArgs, opts);
} catch (e) {
code = e.status || DEFAULT_ERROR_CODE;
}
var stdout = '';
var stderr = '';
if (opts.encoding === 'buffer') {
stdout = fs.readFileSync(stdoutFile);
stderr = fs.readFileSync(stderrFile);
} else {
stdout = fs.readFileSync(stdoutFile, opts.encoding);
stderr = fs.readFileSync(stderrFile, opts.encoding);
}
try { common.unlinkSync(paramsFile); } catch (e) {}
try { common.unlinkSync(stderrFile); } catch (e) {}
try { common.unlinkSync(stdoutFile); } catch (e) {}
if (code !== 0) {
common.error(stderr, code, { continue: true, silent: true });
}
var obj = common.ShellString(stdout, stderr, code);
return obj;
}
function execAsync(cmd, opts, pipe, callback) {
opts = common.extend({
silent: common.config.silent,
cwd: _pwd().toString(),
env: process.env,
maxBuffer: DEFAULT_MAXBUFFER_SIZE,
encoding: 'utf8',
}, opts);
var c = child.exec(cmd, opts, function (err, stdout, stderr) {
if (callback) {
if (!err) {
callback(0, stdout, stderr);
} else if (err.code === undefined) {
callback(1, stdout, stderr);
} else {
callback(err.code, stdout, stderr);
}
}
});
if (pipe) c.stdin.end(pipe);
if (!opts.silent) {
c.stdout.pipe(process.stdout);
c.stderr.pipe(process.stderr);
}
return c;
}
function _exec(command, options, callback) {
options = options || {};
if (!command) common.error('must specify command');
var pipe = common.readFromPipe();
if (typeof options === 'function') {
callback = options;
options = { async: true };
}
if (typeof options === 'object' && typeof callback === 'function') {
options.async = true;
}
options = common.extend({
silent: common.config.silent,
async: false,
}, options);
if (options.async) {
return execAsync(command, options, pipe, callback);
} else {
return execSync(command, options, pipe);
}
}
module.exports = _exec;