123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- /*
- * grunt-execute
- * https://github.com/Bartvds/grunt-execute
- *
- * Copyright (c) 2013 Bart van der Schoor
- * Licensed under the MIT license.
- */
- module.exports = function (grunt) {
- 'use strict';
- var path = require('path');
- function executeModuleFunction(func, context, callback) {
- // private
- var isFinalised = false;
- var isAsync = false;
- var funcDone = false;
- var calledDone = false;
- var finalise = function (err, msg) {
- if (isFinalised) {
- grunt.fail.warn('executeModuleFunction() detected async flow error');
- return null;
- }
- isFinalised = true;
- if (typeof msg !== 'undefined') {
- grunt.log.writeln(msg);
- }
- process.nextTick(function () {
- callback(err);
- });
- };
- var async = function () {
- if (funcDone) {
- grunt.fail.warn('executeModuleFunction() call async() in main body');
- return null;
- }
- if (isAsync) {
- grunt.fail.warn('executeModuleFunction() detected multiple calls to async()');
- return null;
- }
- isAsync = true;
- return function (err, msg) {
- if (calledDone) {
- grunt.fail.warn('executeModuleFunction() detected multiple calls to the async callback');
- return null;
- }
- calledDone = true;
- if (typeof msg !== 'undefined') {
- grunt.log.writeln(msg);
- }
- finalise(err, msg);
- };
- };
- var msg = func(grunt, context.options, async);
- funcDone = true;
- if (!isAsync && !calledDone) {
- finalise(null, msg);
- }
- else {
- if (typeof msg !== 'undefined') {
- grunt.log.writeln(msg);
- }
- }
- }
- function executeModule(func, context, callback) {
- grunt.log.writeln('-> '.cyan + 'module call ' + (func.name ? func.cyan : '<anonymous>'));
- var start = Date.now();
- executeModuleFunction(func, context, function (err) {
- if (err) {
- grunt.fail.warn('-> '.cyan + 'error '.red + '(' + (Date.now() - start) + 'ms)');
- } else {
- context.counter += 1;
- grunt.log.writeln('-> '.cyan + 'completed ' + '(' + (Date.now() - start) + 'ms)');
- }
- callback(err);
- });
- }
- function executeSrcAsModule(src, context, callback) {
- grunt.log.writeln('-> '.cyan + 'executing module ' + src.cyan);
- var mod;
- try {
- mod = require(src);
- }
- catch (err) {
- callback(new Error('not a function'));
- return;
- }
- if (!grunt.util._.isFunction(mod)) {
- grunt.fail.warn('-> '.cyan + 'error '.red + src.cyan + ' should export a Function');
- callback(new Error('not a function'));
- return;
- }
- var start = Date.now();
- executeModuleFunction(mod, context, function (err) {
- if (err) {
- grunt.fail.warn('-> '.cyan + 'error '.red + src.cyan + ' (' + (Date.now() - start) + 'ms)');
- } else {
- context.counter += 1;
- grunt.log.writeln('-> '.cyan + 'completed ' + src.cyan + ' (' + (Date.now() - start) + 'ms)');
- }
- callback(err);
- });
- }
- function executeSrcAsChild(src, context, callback) {
- grunt.log.writeln('-> '.cyan + 'executing ' + src.cyan);
- var start = Date.now();
- var args = context.options.args ? [src].concat(context.options.args) : [src];
- if (context.options.nodeargs) {
- args = context.options.nodeargs.concat(args);
- }
- //use spawn so we don't have to depend on process.exit();
- var child = grunt.util.spawn(
- {
- cmd: 'node',
- args: args,
- opts: {
- cwd: (context.options.cwd !== null) ? context.options.cwd : path.dirname(src)
- }
- },
- function (error, result, code) {
- if (error) {
- grunt.fail.warn('-> '.cyan + 'error '.red + ('' + code).red + ' ' + src.cyan + ' (' + (Date.now() - start) + 'ms)');
- callback(error);
- } else if (code !== 0) {
- grunt.fail.warn('-> '.cyan + 'exitcode '.red + ('' + code).red + ' ' + src.cyan + ' (' + (Date.now() - start) + 'ms)');
- callback(new Error('bad exit code ' + code), code);
- } else {
- context.counter += 1;
- grunt.log.writeln('-> '.cyan + 'completed ' + src.cyan + ' (' + (Date.now() - start) + 'ms)');
- callback();
- }
- }
- );
- child.stdout.on('data', function (data) {
- grunt.log.write(data);
- });
- child.stderr.on('data', function (data) {
- grunt.log.write(('' + data).red);
- });
- }
- function pluralise(count, str) {
- return count + ' ' + str + (count === 1 ? '' : 's');
- }
- grunt.registerMultiTask('execute', 'execute code in node', function () {
- var options = this.options({
- cwd: '.'
- });
- //var self = this;
- var done = this.async();
- var context = {
- timer: Date.now(),
- calls: 0,
- files: 0,
- counter: 0,
- options: options
- };
- var checkModuleFunc = function (func, callback) {
- if (func) {
- context.calls++;
- executeModule(func, context, callback);
- }
- else {
- callback();
- }
- };
- var self = this;
- grunt.util.async.series(
- [
- function (callback) {
- checkModuleFunc(options.before, callback);
- },
- function (callback) {
- checkModuleFunc(self.data.before, callback);
- },
- function (callback) {
- checkModuleFunc(self.data.call, callback);
- },
- function (callback) {
- grunt.util.async.forEachSeries(self.filesSrc,
- function (src, callback) {
- context.files++;
- src = path.resolve(src);
- if (!src) {
- grunt.fail.warn('undefined src parameter');
- return false;
- }
- if (!grunt.file.exists(src)) {
- grunt.fail.warn('file does not exist ' + src);
- return false;
- }
- if (options.module) {
- executeSrcAsModule(src, context, callback);
- }
- else {
- executeSrcAsChild(src, context, callback);
- }
- },
- callback, self);
- },
- function (callback) {
- checkModuleFunc(self.data.after, callback);
- },
- function (callback) {
- checkModuleFunc(options.after, callback);
- }
- ],
- function (err) {
- grunt.log.writeln('');
- if (err) {
- grunt.log.writeln(err);
- done(false);
- }
- else {
- grunt.log.ok('' + pluralise(context.files, 'file') + ' and ' + pluralise(context.calls, 'call') + ' executed (' + (Date.now() - context.timer) + 'ms)\n');
- done();
- }
- }
- );
- });
- };
|