cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From agri...@apache.org
Subject git commit: CB-6049, CB-5181 Enable stdio for build sub-commands & add a spawn() helper.
Date Sun, 16 Feb 2014 17:01:29 GMT
Repository: cordova-cli
Updated Branches:
  refs/heads/master 8bc03dc00 -> a3c8badd8


CB-6049, CB-5181 Enable stdio for build sub-commands & add a spawn() helper.


Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/a3c8badd
Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/a3c8badd
Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/a3c8badd

Branch: refs/heads/master
Commit: a3c8badd8d066e92e5a9149e8e334c1eb8f5c066
Parents: 8bc03dc
Author: Andrew Grieve <agrieve@chromium.org>
Authored: Sun Feb 16 11:56:09 2014 -0500
Committer: Andrew Grieve <agrieve@chromium.org>
Committed: Sun Feb 16 11:59:46 2014 -0500

----------------------------------------------------------------------
 spec/compile.spec.js |  51 +++-------------------
 src/compile.js       |  89 +++++++++++---------------------------
 src/superspawn.js    | 107 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 139 insertions(+), 108 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/a3c8badd/spec/compile.spec.js
----------------------------------------------------------------------
diff --git a/spec/compile.spec.js b/spec/compile.spec.js
index 79761bf..ddccdf1 100644
--- a/spec/compile.spec.js
+++ b/spec/compile.spec.js
@@ -18,12 +18,12 @@
 */
 var cordova = require('../cordova'),
     platforms = require('../platforms'),
-    child_process = require('child_process'),
     path = require('path'),
     fs = require('fs'),
     hooker = require('../src/hooker'),
-    Q = require('q'),
+    superspawn = require('../src/superspawn'),
     util = require('../src/util'),
+    Q = require('q'),
     os = require('os');
 
 
@@ -31,38 +31,8 @@ var supported_platforms = Object.keys(platforms).filter(function(p) { return
p !
 
 
 describe('compile command', function() {
-    var is_cordova, list_platforms, fire, result, child, spawn_wrap, cd_project_root;
+    var is_cordova, list_platforms, fire, result, cd_project_root;
     var project_dir = '/some/path';
-    child = {
-        on: function(child_event,cb){
-            if(child_event === 'close'){
-                cb(0);
-            }
-        },
-        stdout: {
-            setEncoding: function(){},
-            on: function(){}
-        },
-        stderr: {
-            setEncoding: function(){},
-            on: function(){}
-        }
-    };
-    spawn_wrap = function(cmd,args,options){
-        var _cmd = cmd,
-            _args = args;
-
-        if (os.platform() === 'win32') {
-            _args = ['/c',_cmd].concat(_args);
-            _cmd = 'cmd';
-        }
-
-        return {
-                    "cmd": _cmd,
-                    "args": _args,
-                    "options": options
-                };
-    };
 
     function wrapper(f, post) {
         runs(function() {
@@ -76,7 +46,7 @@ describe('compile command', function() {
         cd_project_root = spyOn(util, 'cdProjectRoot').andReturn(project_dir);
         list_platforms = spyOn(util, 'listPlatforms').andReturn(supported_platforms);
         fire = spyOn(hooker.prototype, 'fire').andReturn(Q());
-        spyOn(child_process, 'spawn').andReturn(child);
+        spyOn(superspawn, 'spawn').andCallFake(function() { return Q() });
     });
     describe('failure', function() {
         it('should not run inside a Cordova-based project with no added platforms by calling
util.listPlatforms', function() {
@@ -94,24 +64,17 @@ describe('compile command', function() {
     });
 
     describe('success', function() {
-        var spawn_call;
         it('should run inside a Cordova-based project with at least one added platform and
shell out to build', function(done) {
             cordova.raw.compile(['android','ios']).then(function() {
-                spawn_call = spawn_wrap(path.join(project_dir, 'platforms', 'android', 'cordova',
'build'),[]);
-                expect(child_process.spawn).toHaveBeenCalledWith(spawn_call.cmd, spawn_call.args);
-
-                spawn_call = spawn_wrap(path.join(project_dir, 'platforms', 'ios', 'cordova',
'build'),[]);
-                expect(child_process.spawn).toHaveBeenCalledWith(spawn_call.cmd, spawn_call.args);
-
+                expect(superspawn.spawn).toHaveBeenCalledWith(path.join(project_dir, 'platforms',
'android', 'cordova', 'build'), [], jasmine.any(Object));
+                expect(superspawn.spawn).toHaveBeenCalledWith(path.join(project_dir, 'platforms',
'ios', 'cordova', 'build'), [], jasmine.any(Object));
                 done();
             });
         });
 
         it('should pass down optional parameters', function (done) {
             cordova.raw.compile({platforms:["blackberry10"], options:["--release"]}).then(function
() {
-                spawn_call = spawn_wrap(path.join(project_dir, 'platforms', 'blackberry10',
'cordova', 'build'),['--release']);
-                expect(child_process.spawn).toHaveBeenCalledWith(spawn_call.cmd, spawn_call.args);
-
+                expect(superspawn.spawn).toHaveBeenCalledWith(path.join(project_dir, 'platforms',
'blackberry10', 'cordova', 'build'), ['--release'], jasmine.any(Object));
                 done();
             });
         });

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/a3c8badd/src/compile.js
----------------------------------------------------------------------
diff --git a/src/compile.js b/src/compile.js
index 0daf56a..02f81b3 100644
--- a/src/compile.js
+++ b/src/compile.js
@@ -20,78 +20,39 @@
 /*global require: true, module: true, process: true*/
 /*jslint sloppy: true, white: true, newcap: true */
 
-var cordova_util      = require('./util'),
-    path              = require('path'),
-    child_process     = require('child_process'),
+var path              = require('path'),
+    cordova_util      = require('./util'),
     hooker            = require('./hooker'),
-    events            = require('./events'),
-    Q                 = require('q'),
-    os                = require('os');
-
-// Returns a promise.
-function shell_out_to_build(projectRoot, platform, options) {
-    var cmd = path.join(projectRoot, 'platforms', platform, 'cordova', 'build'),
-        args = options.length ? options : [],
-        d = Q.defer(),
-        errors = "",
-        child;
-
-    if (os.platform() === 'win32') {
-        args = ['/c',cmd].concat(args);
-        cmd = 'cmd';
-    }
-
-    events.emit('log', 'Compiling app on platform "' + platform + '" via command "' + cmd
+ '" ' + args.join(" "));
-
-    //using spawn instead of exec to avoid errors with stdout on maxBuffer
-    child = child_process.spawn(cmd, args);
-    child.stdout.setEncoding('utf8');
-    child.stdout.on('data', function (data) {
-        events.emit('verbose', data);
-    });
-
-    child.stderr.setEncoding('utf8');
-    child.stderr.on('data', function (data) {
-        events.emit('verbose', data);
-        errors = errors + data;
-    });
-
-    child.on('close', function (code) {
-        events.emit('verbose', "child_process.spawn(" + cmd + "," + "[" + args.join(", ")
+ "]) = " + code);
-        if (code === 0) {
-            events.emit('log', 'Platform "' + platform + '" compiled successfully.');
-            d.resolve();
-        } else {
-            d.reject(new Error('An error occurred while building the ' + platform + ' project.'
+ errors));
-        }
-    });
-
-    return d.promise;
-}
+    superspawn        = require('./superspawn'),
+    events            = require('./events');
 
 // Returns a promise.
 module.exports = function compile(options) {
-    var projectRoot = cordova_util.cdProjectRoot(),
-        hooks;
+    var projectRoot = cordova_util.cdProjectRoot();
 
-    if (!options) {
-        options = {
-            verbose: false,
-            platforms: [],
-            options: []
-        };
-    }
+    options = options || {
+        verbose: false,
+        platforms: [],
+        options: []
+    };
 
     options = cordova_util.preProcessOptions(options);
 
-    hooks = new hooker(projectRoot);
-    return hooks.fire('before_compile', options)
-    .then(function() {
-        // Iterate over each added platform
-        return Q.all(options.platforms.map(function(platform) {
-            return shell_out_to_build(projectRoot, platform, options.options);
-        }));
-    }).then(function() {
+    var hooks = new hooker(projectRoot);
+    var ret = hooks.fire('before_compile', options);
+    options.platforms.forEach(function(platform) {
+        ret = ret.then(function() {
+            var cmd = path.join(projectRoot, 'platforms', platform, 'cordova', 'build');
+
+            events.emit('log', 'Compiling ' + platform + ' project');
+            return superspawn.spawn(cmd, options.options, { stdio: 'inherit' })
+            .then(function() {
+                events.emit('log', 'Platform "' + platform + '" compiled successfully.');
+            });
+        });
+    });
+    ret = ret.then(function() {
         return hooks.fire('after_compile', options);
     });
+    return ret;
 };

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/a3c8badd/src/superspawn.js
----------------------------------------------------------------------
diff --git a/src/superspawn.js b/src/superspawn.js
new file mode 100644
index 0000000..c827ec3
--- /dev/null
+++ b/src/superspawn.js
@@ -0,0 +1,107 @@
+/**
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+var child_process = require('child_process');
+var fs = require('fs');
+var _ = require('underscore');
+var Q = require('q');
+var shell = require('shelljs');
+var events = require('./events');
+
+// On Windows, spawn() for batch files requires absolute path & having the extension.
+function resolvePath(cmd) {
+    if (fs.exists(cmd)) {
+        return cmd;
+    }
+    cmd = shell.which(cmd) || cmd;
+    if (!fs.exists(cmd)) {
+        ['.cmd', '.bat', '.js'].some(function(ext) {
+            if (fs.exists(cmd + ext)) {
+                cmd = cmd + ext;
+                return true;
+            }
+        });
+    }
+    return cmd;
+}
+
+// opts:
+//   printCommand: Whether to log the command (default: false)
+//   stdio: 'default' is to capture output and returning it as a string to success (same
as exec)
+//          'ignore' means don't bother capturing it
+//          'inherit' means pipe the input & output. This is required for anything that
prompts.
+//   env: Map of extra environment variables.
+//   cwd: Working directory for the command.
+// Returns a promise that succeeds only for return code = 0.
+exports.spawn = function(cmd, args, opts) {
+    args = args || [];
+    var d = Q.defer();
+    if (process.platform.slice(0, 3) == 'win') {
+        cmd = resolvePath(cmd);
+        // If we couldn't find the file, likely we'll end up failing,
+        // but for things like "del", cmd will do the trick.
+        if (!fs.exists(cmd)) {
+            args = ['/c', cmd].concat(args);
+            cmd = 'cmd';
+        }
+    }
+
+    events.emit(opts.printCommand ? 'log' : 'verbose', 'Running command: ' + cmd + ' Args:
' + args);
+
+    var spawnOpts = {};
+    if (opts.stdio == 'ignore') {
+        spawnOpts.stdio = 'ignore';
+    } else if (opts.stdio == 'inherit') {
+        spawnOpts.stdio = 'inherit';
+    }
+    if (opts.cwd) {
+        spawnOpts.cwd = opts.cwd;
+    }
+    if (opts.env) {
+        spawnOpts.env = _.extend(_.extend({}, process.env), opts.env);
+    }
+
+    var child = child_process.spawn(cmd, args, spawnOpts);
+    var capturedOut = '';
+    var capturedErr = '';
+
+    if (child.stdout) {
+        child.stdout.setEncoding('utf8');
+        child.stdout.on('data', function(data) {
+            capturedOut += data;
+        });
+
+        child.stderr.setEncoding('utf8');
+        child.stderr.on('data', function(data) {
+            capturedErr += data;
+        });
+    }
+
+    child.on('close', function(code) {
+        events.emit('verbose', 'Command finished with error code ' + code + ': ' + cmd +
' ' + args);
+        if (code === 0) {
+            d.resolve(capturedOut.trim());
+        } else {
+            d.reject(new Error(capturedErr.trim()));
+        }
+    });
+
+    return d.promise;
+};
+


Mime
View raw message