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();
     }
 }

Reply via email to