@linagora/grunt-run-grunt
Version:
Grunt task to run Gruntfiles in a child process. Gruntception!
252 lines (210 loc) • 5.33 kB
JavaScript
var path = require('path');
var conf = require('./lib');
var parsers = require('./parsers');
// write shell scripts
function writeShell(grunt, options, src, cwd, argArr) {
var dir = options.writeShell;
if (grunt.file.isFile(options.writeShell)) {
dir = path.dirname(options.writeShell);
}
var gf = path.basename(src.toLowerCase(), path.extname(src));
var base = path.join(dir, options.target + '__' + gf);
// beh
var shPath = base + '.sh';
var shContent = [
'#!/bin/bash',
'',
'cd ' + path.resolve(cwd),
'grunt ' + argArr.join(' '),
''
].join('\n');
grunt.file.write(shPath, shContent);
//TODO chmod the shell-script?
// semi broken
var batPath = base + '.bat';
var batContent = [
'set PWD=%~dp0',
'cd ' + path.resolve(cwd),
'grunt ' + argArr.join(' '),
'cd "%PWD%"',
''
].join('\r\n');
console.log('argArr: ' + argArr.join(' '));
grunt.file.write(batPath, batContent);
}
function runGruntfile(grunt, src, tasks, options, callback) {
//var os = require('os');
//var assert = require('assert');
var _ = grunt.util._;
var mixedStdIO = [];
var taskList = [];
var cwd = (_.isUndefined(options.cwd) || _.isNull(options.cwd) ? path.dirname(src) : options.cwd);
//return value
var result = {
error: null,
res: null,
code: '',
fail: false,
output: '',
src: src,
gruntfile: path.basename(src, path.extname(src)),
cwd: '',
tasks: taskList,
options: options,
// timing
start: Date.now(),
end: Date.now(),
duration: 0,
// parsed data
parsed: {}
};
var useArgs = options.args;
// apply defaults
var argHash = _.defaults({
'gruntfile': path.resolve(src)
}, useArgs);
if (tasks) {
if (_.isArray(tasks)) {
_.forEach(tasks, function (target) {
taskList.push(target);
});
}
else {
taskList.push(tasks);
}
}
else {
// do NOT force default
// tasks = ['default'];
}
// serialise named args
var argArr = [];
_.each(argHash, function (value, opt) {
if (opt.length === 0) {
argArr.push(value);
}
else if (opt.length === 1) {
argArr.push('-' + opt);
if (value !== true && !(_.isNull(value) && _.isUndefined(value))) {
argArr.push(value);
}
}
else {
var arg = '--' + opt;
if (value !== true && !(_.isNull(value) && _.isUndefined(value))) {
arg = arg + '=' + value;
}
argArr.push(arg);
}
});
// append task names
_.each(taskList, function (task) {
argArr.push(task);
});
// for debugging print repeatable cli commands
if (options.debugCli) {
grunt.log.writeln([
'cd ' + path.resolve(cwd),
'grunt ' + argArr.join(' '),
'cd ' + process.cwd()
].join('\n'));
grunt.log.writeln('');
}
// experimental
if (options.writeShell) {
writeShell(grunt, options, src, cwd, argArr);
}
// spawn cli options
var param = {
cmd: 'grunt',
args: argArr,
opts: {
cwd: cwd,
env: grunt.util._.extend({}, process.env, (options.env || {}))
}
};
// make a child
var child = grunt.util.spawn(param,
function (err, res, code) {
grunt.log.writeln(conf.nub + 'reporting' + ' "' + src + '"');
// *everything*
result.error = err;
result.res = res;
result.code = code;
result.output = mixedStdIO.join('');
result.end = Date.now();
result.duration = (result.end - result.start);
// basic check
if (err || code !== 0) {
result.fail = true;
}
else {
result.fail = false;
}
if (options.parser) {
if (parsers.hasOwnProperty(options.parser)) {
var parseOutput = parsers[options.parser];
result.parsed[options.parser] = parseOutput(result.output);
}
}
// process the result object
if (options.process) {
var ret = options.process(result);
if (_.isUndefined(ret)) {
// no return value: leaves as-is
}
else if (ret === true) {
// boolean true mean it passes
result.fail = false;
}
else {
// anythings else mean fail
result.fail = true;
var label = 'grunt_cli(' + [tasks].join(' / ') + ')';
grunt.log.writeln(conf.nub + ('grunt process forced failure').yellow + ' for ' + label);
if (ret !== false) {
// only log if not a boolean
grunt.log.writeln(conf.nub + ret);
}
}
}
// log the log
if (options.log && mixedStdIO.length > 0) {
if (_.isString(options.indentLog) && options.indentLog !== '') {
//TODO optimise this
grunt.log.writeln(options.indentLog + result.output.replace(/\r\n|\r|\n/g, '\n' + options.indentLog));
}
else {
grunt.log.writeln(result.output);
}
}
// file the log
if (options.logFile) {
var tmp = options.logFile;
if (grunt.file.isDir(tmp)) {
tmp = path.join(tmp, 'run-grunt-log.txt');
}
grunt.log.writeln(conf.nub + 'saving data' + ' to "' + tmp + '"');
grunt.file.write(tmp, result.output);
}
// bye
callback(null, result);
}
);
// mix output (this wise?)
child.stdout.on('data', function (data) {
if (options.stdout && typeof(options.stdout) === 'function') {
options.stdout.call(this, data);
}
mixedStdIO.push(data);
});
child.stderr.on('data', function (data) {
if (options.stderr && typeof(options.stderr) === 'function') {
options.stderr.call(this, data);
}
mixedStdIO.push(data);
});
}
module.exports = {
runGruntfile: runGruntfile
};