start of serializing events/hooks
Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/6d81b4d9 Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/6d81b4d9 Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/6d81b4d9 Branch: refs/heads/2.8.x Commit: 6d81b4d92f4dba4a453f3f513a5eca15eeb4a0f3 Parents: b7fc9df Author: Fil Maj <[email protected]> Authored: Thu Jun 6 10:09:57 2013 -0700 Committer: Fil Maj <[email protected]> Committed: Thu Jun 6 18:30:24 2013 -0700 ---------------------------------------------------------------------- src/compile.js | 38 ++++++++++++++-------------- src/hooker.js | 70 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 73 insertions(+), 35 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/6d81b4d9/src/compile.js ---------------------------------------------------------------------- diff --git a/src/compile.js b/src/compile.js index 8d9d217..f969624 100644 --- a/src/compile.js +++ b/src/compile.js @@ -26,7 +26,6 @@ var cordova_util = require('./util'), events = require('./events'), n = require('ncallbacks'); - function shell_out_to_build(projectRoot, platform, callback) { var cmd = '"' + path.join(projectRoot, 'platforms', platform, 'cordova', 'build') + '"'; events.emit('log', 'Compiling platform "' + platform + '" with command "' + cmd + '" (output to follow)...'); @@ -70,25 +69,26 @@ module.exports = function compile(platformList, callback) { } var hooks = new hooker(projectRoot); - if (!(hooks.fire('before_compile'))) { - var err = new Error('before_compile hooks exited with non-zero code. Aborting.'); - if (callback) callback(err); - else throw err; - return; - } + hooks.fire('before_compile', function(err) { + if (err) { + var error = new Error('before_compile hooks exited with non-zero code or caused an error: ' + err.message); + if (callback) callback(error); + else throw error; + } else { + var end = n(platformList.length, function() { + hooks.fire('after_compile', function(error) { + if (error) { + var arr = new Error('after_compile hooks exited with non-zero code. Aborting.'); + if (callback) callback(arr); + else throw arr; + } else if (callback) callback(); + }); + }); - var end = n(platformList.length, function() { - if (!(hooks.fire('after_compile'))) { - var err = new Error('after_compile hooks exited with non-zero code. Aborting.'); - if (callback) callback(err); - else throw err; - return; + // Iterate over each added platform + platformList.forEach(function(platform) { + shell_out_to_build(projectRoot, platform, end); + }); } - if (callback) callback(); - }); - - // Iterate over each added platform - platformList.forEach(function(platform) { - shell_out_to_build(projectRoot, platform, end); }); }; http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/6d81b4d9/src/hooker.js ---------------------------------------------------------------------- diff --git a/src/hooker.js b/src/hooker.js index 0d51304..15c9a6c 100644 --- a/src/hooker.js +++ b/src/hooker.js @@ -29,25 +29,63 @@ module.exports = function hooker(root) { } module.exports.prototype = { - fire:function fire(hook) { + fire:function fire(hook, callback) { + var self = this; var dir = path.join(this.root, '.cordova', 'hooks', hook); if (!(fs.existsSync(dir))) return true; // hooks directory got axed post-create; ignore. - // Fire JS hook/event - events.emit(hook, this.root); - - // Fire script-based hooks - var contents = fs.readdirSync(dir); - var self = this; - contents.forEach(function(script) { - var fullpath = path.join(dir, script); - if (fs.statSync(fullpath).isDirectory()) return; // skip directories if they're in there. - var command = fullpath + ' "' + self.root + '"'; - events.emit('log', 'Executing hook "' + hook + '" (output to follow)...'); - var status = shell.exec(command); - events.emit('log', status.output); - if (status.code !== 0) throw new Error('Script "' + path.basename(script) + '"' + 'in the ' + hook + ' hook exited with non-zero status code. Aborting.'); + // Fire JS hook for the event + // These ones need to "serialize" events, that is, each handler attached to the event needs to finish processing (if it "opted in" to the callback) before the next one will fire. + var handlers = events.listeners(hook); + execute_handlers_serially(handlers, this.root, function() { + // Fire script-based hooks + var scripts = fs.readdirSync(dir); + execute_scripts_serially(scripts, self.root, dir, function(err) { + if (err) { + callback(err); + } else { + callback(); + } + }); }); - return true; + } +} + +function execute_scripts_serially(scripts, root, dir, callback) { + if (scripts.length) { + var s = scripts.shift(); + var fullpath = path.join(dir, s); + if (fs.statSync(fullpath).isDirectory()) { + execute_scripts_serially(scripts, root, dir, callback); // skip directories if they're in there. + } else { + var command = fullpath + ' "' + root + '"'; + events.emit('log', 'Executing hook "' + command + '" (output to follow)...'); + shell.exec(command, {silent:true, async:true}, function(code, output) { + events.emit('log', output); + if (code !== 0) { + callback(new Error('Script "' + fullpath + '" exited with non-zero status code. Aborting. Output: ' + output)); + } else { + execute_scripts_serially(scripts, root, dir, callback); + } + }); + } + } else { + callback(); + } +} + +function execute_handlers_serially(handlers, root, callback) { + if (handlers.length) { + var h = handlers.shift(); + if (h.length > 1) { + h(root, function() { + execute_handlers_serially(handlers, root, callback); + }); + } else { + h(root); + execute_handlers_serially(handlers, root, callback); + } + } else { + callback(); } }
