CB-10519 Wrap all sync calls inside of `cordova.raw` methods into promises
Project: http://git-wip-us.apache.org/repos/asf/cordova-lib/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-lib/commit/4121b11f Tree: http://git-wip-us.apache.org/repos/asf/cordova-lib/tree/4121b11f Diff: http://git-wip-us.apache.org/repos/asf/cordova-lib/diff/4121b11f Branch: refs/heads/common-1.1.x Commit: 4121b11f050d8421ccd42a55ed21a0474039439a Parents: b04db5f Author: Vladimir Kotikov <v-vlk...@microsoft.com> Authored: Wed Feb 10 15:45:19 2016 +0300 Committer: Vladimir Kotikov <v-vlk...@microsoft.com> Committed: Fri Feb 19 14:06:11 2016 +0300 ---------------------------------------------------------------------- cordova-lib/spec-cordova/build.spec.js | 6 +- cordova-lib/spec-cordova/compile.spec.js | 30 +- cordova-lib/spec-cordova/emulate.spec.js | 33 +- cordova-lib/spec-cordova/prepare.spec.js | 4 +- cordova-lib/src/cordova/build.js | 29 +- cordova-lib/src/cordova/clean.js | 31 +- cordova-lib/src/cordova/compile.js | 89 ++--- cordova-lib/src/cordova/emulate.js | 38 +- cordova-lib/src/cordova/platform.js | 121 +++---- cordova-lib/src/cordova/plugin.js | 480 +++++++++++++------------- cordova-lib/src/cordova/prepare.js | 56 +-- cordova-lib/src/cordova/requirements.js | 30 +- cordova-lib/src/cordova/run.js | 99 +++--- cordova-lib/src/cordova/serve.js | 41 +-- 14 files changed, 567 insertions(+), 520 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/spec-cordova/build.spec.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/build.spec.js b/cordova-lib/spec-cordova/build.spec.js index f5f1b2b..66f0869 100644 --- a/cordova-lib/spec-cordova/build.spec.js +++ b/cordova-lib/spec-cordova/build.spec.js @@ -40,7 +40,8 @@ describe('build command', function() { describe('failure', function() { it('should not run inside a project with no platforms', function(done) { list_platforms.andReturn([]); - Q().then(cordova.raw.build).then(function() { + cordova.raw.build() + .then(function() { expect('this call').toBe('fail'); }, function(err) { expect(err.message).toEqual( @@ -52,7 +53,8 @@ describe('build command', function() { it('should not run outside of a Cordova-based project', function(done) { is_cordova.andReturn(false); - Q().then(cordova.raw.build).then(function() { + cordova.raw.build() + .then(function() { expect('this call').toBe('fail'); }, function(err) { expect(err.message).toEqual( http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/spec-cordova/compile.spec.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/compile.spec.js b/cordova-lib/spec-cordova/compile.spec.js index 7f4e8f6..9f4040f 100644 --- a/cordova-lib/spec-cordova/compile.spec.js +++ b/cordova-lib/spec-cordova/compile.spec.js @@ -26,16 +26,9 @@ var supported_platforms = Object.keys(platforms).filter(function(p) { return p ! describe('compile command', function() { - var is_cordova, list_platforms, fire, result, cd_project_root, fail, platformApi, getPlatformApi; + var is_cordova, list_platforms, fire, cd_project_root, fail, platformApi, getPlatformApi; var project_dir = '/some/path'; - function wrapper(f, post) { - runs(function() { - Q().then(f).then(function() { result = true; }, function(err) { result = err; }); - }); - waitsFor(function() { return result; }, 'promise never resolved', 500); - runs(post); - } beforeEach(function() { is_cordova = spyOn(util, 'isCordova').andReturn(project_dir); cd_project_root = spyOn(util, 'cdProjectRoot').andReturn(project_dir); @@ -46,16 +39,29 @@ describe('compile command', function() { fail = function (err) { expect(err.stack).not.toBeDefined(); }; }); describe('failure', function() { - it('should not run inside a Cordova-based project with no added platforms by calling util.listPlatforms', function() { + it('should not run inside a Cordova-based project with no added platforms by calling util.listPlatforms', function(done) { list_platforms.andReturn([]); - wrapper(cordova.raw.compile, function() { + var success = jasmine.createSpy('success'); + cordova.raw.compile() + .then(success, function(result) { + expect(result instanceof Error).toBe(true); expect('' + result).toContain('No platforms added to this project. Please use `cordova platform add <platform>`.'); + }) + .fin(function() { + expect(success).not.toHaveBeenCalled(); + done(); }); }); - it('should not run outside of a Cordova-based project', function() { + it('should not run outside of a Cordova-based project', function(done) { is_cordova.andReturn(false); - wrapper(cordova.raw.compile, function() { + var success = jasmine.createSpy('success'); + cordova.raw.compile() + .then(success, function(result) { expect(result instanceof Error).toBe(true); + }) + .fin(function() { + expect(success).not.toHaveBeenCalled(); + done(); }); }); }); http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/spec-cordova/emulate.spec.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/emulate.spec.js b/cordova-lib/spec-cordova/emulate.spec.js index 5cea968..3f9b093 100644 --- a/cordova-lib/spec-cordova/emulate.spec.js +++ b/cordova-lib/spec-cordova/emulate.spec.js @@ -25,18 +25,10 @@ var cordova = require('../src/cordova/cordova'), var supported_platforms = Object.keys(platforms).filter(function(p) { return p != 'www'; }); describe('emulate command', function() { - var is_cordova, cd_project_root, list_platforms, fire, result, fail; + var is_cordova, cd_project_root, list_platforms, fire, fail; var project_dir = '/some/path'; var prepare_spy, platformApi, getPlatformApi; - function wrapper(f, post) { - runs(function() { - Q().then(f).then(function() { result = true; }, function(err) { result = err; }); - }); - waitsFor(function() { return result; }, 'promise never resolved', 500); - runs(post); - } - beforeEach(function() { is_cordova = spyOn(util, 'isCordova').andReturn(project_dir); cd_project_root = spyOn(util, 'cdProjectRoot').andReturn(project_dir); @@ -48,16 +40,29 @@ describe('emulate command', function() { getPlatformApi = spyOn(platforms, 'getPlatformApi').andReturn(platformApi); }); describe('failure', function() { - it('should not run inside a Cordova-based project with no added platforms by calling util.listPlatforms', function() { + it('should not run inside a Cordova-based project with no added platforms by calling util.listPlatforms', function(done) { list_platforms.andReturn([]); - wrapper(cordova.raw.emulate, function() { - expect(''+ result).toContain('No platforms added to this project. Please use `cordova platform add <platform>`.'); + var success = jasmine.createSpy('success'); + cordova.raw.compile() + .then(success, function(result) { + expect(result instanceof Error).toBe(true); + expect('' + result).toContain('No platforms added to this project. Please use `cordova platform add <platform>`.'); + }) + .fin(function() { + expect(success).not.toHaveBeenCalled(); + done(); }); }); - it('should not run outside of a Cordova-based project', function() { + it('should not run outside of a Cordova-based project', function(done) { is_cordova.andReturn(false); - wrapper(cordova.raw.emulate, function() { + var success = jasmine.createSpy('success'); + cordova.raw.compile() + .then(success, function(result) { expect(result instanceof Error).toBe(true); + }) + .fin(function() { + expect(success).not.toHaveBeenCalled(); + done(); }); }); }); http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/spec-cordova/prepare.spec.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/prepare.spec.js b/cordova-lib/spec-cordova/prepare.spec.js index e475dce..f01634f 100644 --- a/cordova-lib/spec-cordova/prepare.spec.js +++ b/cordova-lib/spec-cordova/prepare.spec.js @@ -95,7 +95,7 @@ describe('prepare command', function() { it('should not run outside of a cordova-based project by calling util.isCordova', function(done) { is_cordova.andReturn(false); cd_project_root.andCallThrough(); // undo spy here because prepare depends on cdprojectRoot for isCordova check - Q().then(prepare).then(function() { + prepare().then(function() { expect('this call').toBe('fail'); }, function(err) { expect('' + err).toContain('Current working directory is not a Cordova-based project.'); @@ -103,7 +103,7 @@ describe('prepare command', function() { }); it('should not run inside a cordova-based project with no platforms', function(done) { list_platforms.andReturn([]); - Q().then(prepare).then(function() { + prepare().then(function() { expect('this call').toBe('fail'); }, function(err) { expect('' + err).toContain('No platforms added to this project. Please use `cordova platform add <platform>`.'); http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/src/cordova/build.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/cordova/build.js b/cordova-lib/src/cordova/build.js index d734d1a..fa3dca2 100644 --- a/cordova-lib/src/cordova/build.js +++ b/cordova-lib/src/cordova/build.js @@ -17,22 +17,25 @@ under the License. */ -var cordovaUtil = require('./util'), - HooksRunner = require('../hooks/HooksRunner'); +var Q = require('q'), + cordovaUtil = require('./util'), + HooksRunner = require('../hooks/HooksRunner'); // Returns a promise. module.exports = function build(options) { - var projectRoot = cordovaUtil.cdProjectRoot(); - options = cordovaUtil.preProcessOptions(options); + return Q().then(function() { + var projectRoot = cordovaUtil.cdProjectRoot(); + options = cordovaUtil.preProcessOptions(options); - // fire build hooks - var hooksRunner = new HooksRunner(projectRoot); - return hooksRunner.fire('before_build', options) - .then(function() { - return require('./cordova').raw.prepare(options); - }).then(function() { - return require('./cordova').raw.compile(options); - }).then(function() { - return hooksRunner.fire('after_build', options); + // fire build hooks + var hooksRunner = new HooksRunner(projectRoot); + return hooksRunner.fire('before_build', options) + .then(function() { + return require('./cordova').raw.prepare(options); + }).then(function() { + return require('./cordova').raw.compile(options); + }).then(function() { + return hooksRunner.fire('after_build', options); + }); }); }; http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/src/cordova/clean.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/cordova/clean.js b/cordova-lib/src/cordova/clean.js index b91b941..4ed8962 100644 --- a/cordova-lib/src/cordova/clean.js +++ b/cordova-lib/src/cordova/clean.js @@ -17,7 +17,8 @@ under the License. */ -var cordova_util = require('./util'), +var Q = require('q'), + cordova_util = require('./util'), HooksRunner = require('../hooks/HooksRunner'), events = require('cordova-common').events, chain = require('../util/promise-util').Q_chainmap, @@ -25,20 +26,22 @@ var cordova_util = require('./util'), // Returns a promise. module.exports = function clean(options) { - var projectRoot = cordova_util.cdProjectRoot(); - options = cordova_util.preProcessOptions(options); + return Q().then(function() { + var projectRoot = cordova_util.cdProjectRoot(); + options = cordova_util.preProcessOptions(options); - var hooksRunner = new HooksRunner(projectRoot); - return hooksRunner.fire('before_clean', options) - .then(function () { - return chain(options.platforms, function (platform) { - events.emit('verbose', 'Running cleanup for ' + platform + ' platform.'); - return platform_lib - .getPlatformApi(platform) - .clean(); + var hooksRunner = new HooksRunner(projectRoot); + return hooksRunner.fire('before_clean', options) + .then(function () { + return chain(options.platforms, function (platform) { + events.emit('verbose', 'Running cleanup for ' + platform + ' platform.'); + return platform_lib + .getPlatformApi(platform) + .clean(); + }); + }) + .then(function() { + return hooksRunner.fire('after_clean', options); }); - }) - .then(function() { - return hooksRunner.fire('after_clean', options); }); }; http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/src/cordova/compile.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/cordova/compile.js b/cordova-lib/src/cordova/compile.js index 5834925..e540c14 100644 --- a/cordova-lib/src/cordova/compile.js +++ b/cordova-lib/src/cordova/compile.js @@ -1,41 +1,48 @@ -/** - 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 cordova_util = require('./util'), - HooksRunner = require('../hooks/HooksRunner'), - promiseUtil = require('../util/promise-util'), - platform_lib = require('../platforms/platforms'); - -// Returns a promise. -module.exports = function compile(options) { - var projectRoot = cordova_util.cdProjectRoot(); - options = cordova_util.preProcessOptions(options); - - var hooksRunner = new HooksRunner(projectRoot); - return hooksRunner.fire('before_compile', options) - .then(function () { - return promiseUtil.Q_chainmap(options.platforms, function (platform) { - return platform_lib - .getPlatformApi(platform) - .build(options.options); - }); - }).then(function() { - return hooksRunner.fire('after_compile', options); - }); -}; +/** + 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 cordova_util = require('./util'), + HooksRunner = require('../hooks/HooksRunner'), + promiseUtil = require('../util/promise-util'), + platform_lib = require('../platforms/platforms'); + +// Returns a promise. +module.exports = function compile(options) { + return Q().then(function() { + var projectRoot = cordova_util.cdProjectRoot(); + options = cordova_util.preProcessOptions(options); + + var hooksRunner = new HooksRunner(projectRoot); + return hooksRunner.fire('before_compile', options) + .then(function () { + return promiseUtil.Q_chainmap(options.platforms, function (platform) { + return platform_lib + .getPlatformApi(platform) + .build(options.options); + }); + }).then(function() { + return hooksRunner.fire('after_compile', options); + }, function(error) { + events.emit('log', 'ERROR building one of the platforms: ' + error + '\nYou may not have the required environment or OS to build this project'); + return Q.reject(error); + }); + }).then(function() { + return hooksRunner.fire('after_compile', options); + }); +}; http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/src/cordova/emulate.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/cordova/emulate.js b/cordova-lib/src/cordova/emulate.js index 62810fc..b2ac92b 100644 --- a/cordova-lib/src/cordova/emulate.js +++ b/cordova-lib/src/cordova/emulate.js @@ -24,24 +24,26 @@ var cordova_util = require('./util'), // Returns a promise. module.exports = function emulate(options) { - var projectRoot = cordova_util.cdProjectRoot(); - options = cordova_util.preProcessOptions(options); - options.options.device = false; - options.options.emulator = true; + return Q().then(function() { + var projectRoot = cordova_util.cdProjectRoot(); + options = cordova_util.preProcessOptions(options); + options.options.device = false; + options.options.emulator = true; - var hooksRunner = new HooksRunner(projectRoot); - return hooksRunner.fire('before_emulate', options) - .then(function() { - // Run a prepare first! - return require('./cordova').raw.prepare(options); - }).then(function() { - // Deploy in parallel (output gets intermixed though...) - return Q.all(options.platforms.map(function(platform) { - return platform_lib - .getPlatformApi(platform) - .run(options.options); - })); - }).then(function() { - return hooksRunner.fire('after_emulate', options); + var hooksRunner = new HooksRunner(projectRoot); + return hooksRunner.fire('before_emulate', options) + .then(function() { + // Run a prepare first! + return require('./cordova').raw.prepare(options); + }).then(function() { + // Deploy in parallel (output gets intermixed though...) + return Q.all(options.platforms.map(function(platform) { + return platform_lib + .getPlatformApi(platform) + .run(options.options); + })); + }).then(function() { + return hooksRunner.fire('after_emulate', options); + }); }); }; http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/src/cordova/platform.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/cordova/platform.js b/cordova-lib/src/cordova/platform.js index 96c5f2f..2dff594 100644 --- a/cordova-lib/src/cordova/platform.js +++ b/cordova-lib/src/cordova/platform.js @@ -541,66 +541,69 @@ function addDeprecatedInformationToPlatforms(platformsList){ // Returns a promise. module.exports = platform; function platform(command, targets, opts) { - var projectRoot = cordova_util.cdProjectRoot(); - var msg; - var hooksRunner = new HooksRunner(projectRoot); - - if (arguments.length === 0) command = 'ls'; - - // Verify that targets look like platforms. Examples: - // - android - // - android@3.5.0 - // - ../path/to/dir/with/platform/files - // - https://github.com/apache/cordova-android.git - if (targets) { - if (!(targets instanceof Array)) targets = [targets]; - targets.forEach(function (t) { - // Trim the @version part if it's there. - var p = t.split('@')[0]; - // OK if it's one of known platform names. - if (p in platforms) return; - // Not a known platform name, check if its a real path. - var pPath = path.resolve(t); - if (fs.existsSync(pPath)) return; - - var msg; - // If target looks like a url, we will try cloning it with git - if (/[~:/\\.]/.test(t)) { - return; - } else { - // Neither path, git-url nor platform name - throw. - msg = 'Platform "' + t + - '" not recognized as a core cordova platform. See `' + - cordova_util.binname + ' platform list`.' - ; - } - throw new CordovaError(msg); - }); - } else if (command == 'add' || command == 'rm') { - msg = 'You need to qualify `add` or `remove` with one or more platforms!'; - return Q.reject(new CordovaError(msg)); - } - + // CB-10519 wrap function code into promise so throwing error + // would result in promise rejection instead of uncaught exception + return Q().then(function() { + var msg; + var projectRoot = cordova_util.cdProjectRoot(); + var hooksRunner = new HooksRunner(projectRoot); + + if (arguments.length === 0) command = 'ls'; + + // Verify that targets look like platforms. Examples: + // - android + // - android@3.5.0 + // - ../path/to/dir/with/platform/files + // - https://github.com/apache/cordova-android.git + if (targets) { + if (!(targets instanceof Array)) targets = [targets]; + targets.forEach(function (t) { + // Trim the @version part if it's there. + var p = t.split('@')[0]; + // OK if it's one of known platform names. + if (p in platforms) return; + // Not a known platform name, check if its a real path. + var pPath = path.resolve(t); + if (fs.existsSync(pPath)) return; + + var msg; + // If target looks like a url, we will try cloning it with git + if (/[~:/\\.]/.test(t)) { + return; + } else { + // Neither path, git-url nor platform name - throw. + msg = 'Platform "' + t + + '" not recognized as a core cordova platform. See `' + + cordova_util.binname + ' platform list`.' + ; + } + throw new CordovaError(msg); + }); + } else if (command == 'add' || command == 'rm') { + msg = 'You need to qualify `add` or `remove` with one or more platforms!'; + return Q.reject(new CordovaError(msg)); + } - opts = opts || {}; - opts.platforms = targets; - - switch (command) { - case 'add': - return add(hooksRunner, projectRoot, targets, opts); - case 'rm': - case 'remove': - return remove(hooksRunner, projectRoot, targets, opts); - case 'update': - case 'up': - return update(hooksRunner, projectRoot, targets, opts); - case 'check': - return check(hooksRunner, projectRoot); - case 'save': - return save(hooksRunner, projectRoot, opts); - default: - return list(hooksRunner, projectRoot, opts); - } + opts = opts || {}; + opts.platforms = targets; + + switch (command) { + case 'add': + return add(hooksRunner, projectRoot, targets, opts); + case 'rm': + case 'remove': + return remove(hooksRunner, projectRoot, targets, opts); + case 'update': + case 'up': + return update(hooksRunner, projectRoot, targets, opts); + case 'check': + return check(hooksRunner, projectRoot); + case 'save': + return save(hooksRunner, projectRoot, opts); + default: + return list(hooksRunner, projectRoot, opts); + } + }); } // Used to prevent attempts of installing platforms that are not supported on http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/src/cordova/plugin.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/cordova/plugin.js b/cordova-lib/src/cordova/plugin.js index d35e7a2..35819c3 100644 --- a/cordova-lib/src/cordova/plugin.js +++ b/cordova-lib/src/cordova/plugin.js @@ -37,268 +37,272 @@ var cordova_util = require('./util'), // Returns a promise. module.exports = function plugin(command, targets, opts) { - var projectRoot = cordova_util.cdProjectRoot(); - - // Dance with all the possible call signatures we've come up over the time. They can be: - // 1. plugin() -> list the plugins - // 2. plugin(command, Array of targets, maybe opts object) - // 3. plugin(command, target1, target2, target3 ... ) - // The targets are not really targets, they can be a mixture of plugins and options to be passed to plugman. - - command = command || 'ls'; - targets = targets || []; - opts = opts || {}; - if ( opts.length ) { - // This is the case with multiple targets as separate arguments and opts is not opts but another target. - targets = Array.prototype.slice.call(arguments, 1); - opts = {}; - } - if ( !Array.isArray(targets) ) { - // This means we had a single target given as string. - targets = [targets]; - } - opts.options = opts.options || []; - opts.plugins = []; - - // TODO: Otherwise HooksRunner will be Object instead of function when run from tests - investigate why - var HooksRunner = require('../hooks/HooksRunner'); - var hooksRunner = new HooksRunner(projectRoot); - var config_json = config.read(projectRoot); - var platformList = cordova_util.listPlatforms(projectRoot); - - // Massage plugin name(s) / path(s) - var pluginPath = path.join(projectRoot, 'plugins'); - var plugins = cordova_util.findPlugins(pluginPath); - if (!targets || !targets.length) { - if (command == 'add' || command == 'rm') { - return Q.reject(new CordovaError('You need to qualify `'+cordova_util.binname+' plugin add` or `'+cordova_util.binname+' plugin remove` with one or more plugins!')); - } else { - targets = []; + // CB-10519 wrap function code into promise so throwing error + // would result in promise rejection instead of uncaught exception + return Q().then(function () { + var projectRoot = cordova_util.cdProjectRoot(); + + // Dance with all the possible call signatures we've come up over the time. They can be: + // 1. plugin() -> list the plugins + // 2. plugin(command, Array of targets, maybe opts object) + // 3. plugin(command, target1, target2, target3 ... ) + // The targets are not really targets, they can be a mixture of plugins and options to be passed to plugman. + + command = command || 'ls'; + targets = targets || []; + opts = opts || {}; + if ( opts.length ) { + // This is the case with multiple targets as separate arguments and opts is not opts but another target. + targets = Array.prototype.slice.call(arguments, 1); + opts = {}; } - } - - //Split targets between plugins and options - //Assume everything after a token with a '-' is an option - var i; - for (i = 0; i < targets.length; i++) { - if (targets[i].match(/^-/)) { - opts.options = targets.slice(i); - break; - } else { - opts.plugins.push(targets[i]); + if ( !Array.isArray(targets) ) { + // This means we had a single target given as string. + targets = [targets]; } - } - - switch(command) { - case 'add': - if (!targets || !targets.length) { - return Q.reject(new CordovaError('No plugin specified. Please specify a plugin to add. See `'+cordova_util.binname+' plugin search`.')); + opts.options = opts.options || []; + opts.plugins = []; + + // TODO: Otherwise HooksRunner will be Object instead of function when run from tests - investigate why + var HooksRunner = require('../hooks/HooksRunner'); + var hooksRunner = new HooksRunner(projectRoot); + var config_json = config.read(projectRoot); + var platformList = cordova_util.listPlatforms(projectRoot); + + // Massage plugin name(s) / path(s) + var pluginPath = path.join(projectRoot, 'plugins'); + var plugins = cordova_util.findPlugins(pluginPath); + if (!targets || !targets.length) { + if (command == 'add' || command == 'rm') { + return Q.reject(new CordovaError('You need to qualify `'+cordova_util.binname+' plugin add` or `'+cordova_util.binname+' plugin remove` with one or more plugins!')); + } else { + targets = []; } + } - var xml = cordova_util.projectConfig(projectRoot); - var cfg = new ConfigParser(xml); - var searchPath = config_json.plugin_search_path || []; - if (typeof opts.searchpath == 'string') { - searchPath = opts.searchpath.split(path.delimiter).concat(searchPath); - } else if (opts.searchpath) { - searchPath = opts.searchpath.concat(searchPath); - } - // Blank it out to appease unit tests. - if (searchPath.length === 0) { - searchPath = undefined; + //Split targets between plugins and options + //Assume everything after a token with a '-' is an option + var i; + for (i = 0; i < targets.length; i++) { + if (targets[i].match(/^-/)) { + opts.options = targets.slice(i); + break; + } else { + opts.plugins.push(targets[i]); } + } - opts.cordova = { plugins: cordova_util.findPlugins(pluginPath) }; - return hooksRunner.fire('before_plugin_add', opts) - .then(function() { - var pluginInfoProvider = new PluginInfoProvider(); - return opts.plugins.reduce(function(soFar, target) { - return soFar.then(function() { - if (target[target.length - 1] == path.sep) { - target = target.substring(0, target.length - 1); - } + switch(command) { + case 'add': + if (!targets || !targets.length) { + return Q.reject(new CordovaError('No plugin specified. Please specify a plugin to add. See `'+cordova_util.binname+' plugin search`.')); + } - var parts = target.split('@'); - var id = parts[0]; - var version = parts[1]; - - // If no version is specified, retrieve the version (or source) from config.xml - if (!version && !cordova_util.isUrl(id) && !cordova_util.isDirectory(id)) { - events.emit('verbose', 'no version specified, retrieving version from config.xml'); - var ver = getVersionFromConfigFile(id, cfg); - - if (cordova_util.isUrl(ver) || cordova_util.isDirectory(ver)) { - target = ver; - } else { - //if version exists from config.xml, use that - if(ver) { - target = ver ? (id + '@' + ver) : target; + var xml = cordova_util.projectConfig(projectRoot); + var cfg = new ConfigParser(xml); + var searchPath = config_json.plugin_search_path || []; + if (typeof opts.searchpath == 'string') { + searchPath = opts.searchpath.split(path.delimiter).concat(searchPath); + } else if (opts.searchpath) { + searchPath = opts.searchpath.concat(searchPath); + } + // Blank it out to appease unit tests. + if (searchPath.length === 0) { + searchPath = undefined; + } + + opts.cordova = { plugins: cordova_util.findPlugins(pluginPath) }; + return hooksRunner.fire('before_plugin_add', opts) + .then(function() { + var pluginInfoProvider = new PluginInfoProvider(); + return opts.plugins.reduce(function(soFar, target) { + return soFar.then(function() { + if (target[target.length - 1] == path.sep) { + target = target.substring(0, target.length - 1); + } + + var parts = target.split('@'); + var id = parts[0]; + var version = parts[1]; + + // If no version is specified, retrieve the version (or source) from config.xml + if (!version && !cordova_util.isUrl(id) && !cordova_util.isDirectory(id)) { + events.emit('verbose', 'no version specified, retrieving version from config.xml'); + var ver = getVersionFromConfigFile(id, cfg); + + if (cordova_util.isUrl(ver) || cordova_util.isDirectory(ver)) { + target = ver; } else { - //fetch pinned version from cordova-lib - var pinnedVer = pkgJson.cordovaPlugins[id]; - target = pinnedVer ? (id + '@' + pinnedVer) : target; + //if version exists from config.xml, use that + if(ver) { + target = ver ? (id + '@' + ver) : target; + } else { + //fetch pinned version from cordova-lib + var pinnedVer = pkgJson.cordovaPlugins[id]; + target = pinnedVer ? (id + '@' + pinnedVer) : target; + } } } - } - - // Fetch the plugin first. - events.emit('verbose', 'Calling plugman.fetch on plugin "' + target + '"'); - - var fetchOptions = { - searchpath: searchPath, - noregistry: opts.noregistry, - nohooks: opts.nohooks, - link: opts.link, - pluginInfoProvider: pluginInfoProvider, - variables: opts.cli_variables, - is_top_level: true - }; - - return plugman.raw.fetch(target, pluginPath, fetchOptions) - .then(function (directory) { - return pluginInfoProvider.get(directory); - }); - }) - .then(function(pluginInfo) { - // Validate top-level required variables - var pluginVariables = pluginInfo.getPreferences(); - var missingVariables = Object.keys(pluginVariables) - .filter(function (variableName) { - // discard variables with default value - return !(pluginVariables[variableName] || opts.cli_variables[variableName]); - }); - if (missingVariables.length) { - shell.rm('-rf', pluginInfo.dir); - var msg = 'Variable(s) missing (use: --variable ' + missingVariables.join('=value --variable ') + '=value).'; - return Q.reject(new CordovaError(msg)); - } + // Fetch the plugin first. + events.emit('verbose', 'Calling plugman.fetch on plugin "' + target + '"'); - // Iterate (in serial!) over all platforms in the project and install the plugin. - return chainMap(platformList, function (platform) { - var platformRoot = path.join(projectRoot, 'platforms', platform), - options = { - cli_variables: opts.cli_variables || {}, - browserify: opts.browserify || false, + var fetchOptions = { searchpath: searchPath, noregistry: opts.noregistry, + nohooks: opts.nohooks, link: opts.link, pluginInfoProvider: pluginInfoProvider, - // Set up platform to install asset files/js modules to <platform>/platform_www dir - // instead of <platform>/www. This is required since on each prepare platform's www dir is changed - // and files from 'platform_www' merged into 'www'. Thus we need to persist these - // files platform_www directory, so they'll be applied to www on each prepare. - usePlatformWww: true, - nohooks: opts.nohooks + variables: opts.cli_variables, + is_top_level: true }; - events.emit('verbose', 'Calling plugman.install on plugin "' + pluginInfo.dir + '" for platform "' + platform); - return plugman.raw.install(platform, platformRoot, path.basename(pluginInfo.dir), pluginPath, options); + return plugman.raw.fetch(target, pluginPath, fetchOptions) + .then(function (directory) { + return pluginInfoProvider.get(directory); + }); }) - .thenResolve(pluginInfo); - }) - .then(function(pluginInfo){ - // save to config.xml - if(saveToConfigXmlOn(config_json, opts)){ - var src = parseSource(target, opts); - var attributes = { - name: pluginInfo.id, - spec: src ? src : '~' + pluginInfo.version - }; + .then(function(pluginInfo) { + // Validate top-level required variables + var pluginVariables = pluginInfo.getPreferences(); + var missingVariables = Object.keys(pluginVariables) + .filter(function (variableName) { + // discard variables with default value + return !(pluginVariables[variableName] || opts.cli_variables[variableName]); + }); + + if (missingVariables.length) { + shell.rm('-rf', pluginInfo.dir); + var msg = 'Variable(s) missing (use: --variable ' + missingVariables.join('=value --variable ') + '=value).'; + return Q.reject(new CordovaError(msg)); + } - cfg.removePlugin(pluginInfo.id); - cfg.addPlugin(attributes, opts.cli_variables); - cfg.write(); + // Iterate (in serial!) over all platforms in the project and install the plugin. + return chainMap(platformList, function (platform) { + var platformRoot = path.join(projectRoot, 'platforms', platform), + options = { + cli_variables: opts.cli_variables || {}, + browserify: opts.browserify || false, + searchpath: searchPath, + noregistry: opts.noregistry, + link: opts.link, + pluginInfoProvider: pluginInfoProvider, + // Set up platform to install asset files/js modules to <platform>/platform_www dir + // instead of <platform>/www. This is required since on each prepare platform's www dir is changed + // and files from 'platform_www' merged into 'www'. Thus we need to persist these + // files platform_www directory, so they'll be applied to www on each prepare. + usePlatformWww: true, + nohooks: opts.nohooks + }; + + events.emit('verbose', 'Calling plugman.install on plugin "' + pluginInfo.dir + '" for platform "' + platform); + return plugman.raw.install(platform, platformRoot, path.basename(pluginInfo.dir), pluginPath, options); + }) + .thenResolve(pluginInfo); + }) + .then(function(pluginInfo){ + // save to config.xml + if(saveToConfigXmlOn(config_json, opts)){ + var src = parseSource(target, opts); + var attributes = { + name: pluginInfo.id, + spec: src ? src : '~' + pluginInfo.version + }; + + cfg.removePlugin(pluginInfo.id); + cfg.addPlugin(attributes, opts.cli_variables); + cfg.write(); + + events.emit('results', 'Saved plugin info for "' + pluginInfo.id + '" to config.xml'); + } + }); + }, Q()); // end Q.all + }).then(function() { + // Need to require right here instead of doing this at the beginning of file + // otherwise tests are failing without any real reason. + return require('./prepare').preparePlatforms(platformList, projectRoot, opts); + }).then(function() { + opts.cordova = { plugins: cordova_util.findPlugins(pluginPath) }; + return hooksRunner.fire('after_plugin_add', opts); + }); + case 'rm': + case 'remove': + if (!targets || !targets.length) { + return Q.reject(new CordovaError('No plugin specified. Please specify a plugin to remove. See `'+cordova_util.binname+' plugin list`.')); + } - events.emit('results', 'Saved plugin info for "' + pluginInfo.id + '" to config.xml'); - } - }); - }, Q()); // end Q.all - }).then(function() { - // Need to require right here instead of doing this at the beginning of file - // otherwise tests are failing without any real reason. - return require('./prepare').preparePlatforms(platformList, projectRoot, opts); - }).then(function() { opts.cordova = { plugins: cordova_util.findPlugins(pluginPath) }; - return hooksRunner.fire('after_plugin_add', opts); - }); - case 'rm': - case 'remove': - if (!targets || !targets.length) { - return Q.reject(new CordovaError('No plugin specified. Please specify a plugin to remove. See `'+cordova_util.binname+' plugin list`.')); - } - - opts.cordova = { plugins: cordova_util.findPlugins(pluginPath) }; - return hooksRunner.fire('before_plugin_rm', opts) - .then(function() { - return opts.plugins.reduce(function(soFar, target) { - var validatedPluginId = validatePluginId(target, plugins); - if (!validatedPluginId) { - return Q.reject(new CordovaError('Plugin "' + target + '" is not present in the project. See `' + cordova_util.binname + ' plugin list`.')); + return hooksRunner.fire('before_plugin_rm', opts) + .then(function() { + return opts.plugins.reduce(function(soFar, target) { + var validatedPluginId = validatePluginId(target, plugins); + if (!validatedPluginId) { + return Q.reject(new CordovaError('Plugin "' + target + '" is not present in the project. See `' + cordova_util.binname + ' plugin list`.')); + } + target = validatedPluginId; + + // Iterate over all installed platforms and uninstall. + // If this is a web-only or dependency-only plugin, then + // there may be nothing to do here except remove the + // reference from the platform's plugin config JSON. + return platformList.reduce(function(soFar, platform) { + return soFar.then(function() { + var platformRoot = path.join(projectRoot, 'platforms', platform); + events.emit('verbose', 'Calling plugman.uninstall on plugin "' + target + '" for platform "' + platform + '"'); + return plugman.raw.uninstall.uninstallPlatform(platform, platformRoot, target, pluginPath); + }); + }, Q()) + .then(function() { + // TODO: Should only uninstallPlugin when no platforms have it. + return plugman.raw.uninstall.uninstallPlugin(target, pluginPath); + }).then(function(){ + //remove plugin from config.xml + if(saveToConfigXmlOn(config_json, opts)){ + var configPath = cordova_util.projectConfig(projectRoot); + if(fs.existsSync(configPath)){//should not happen with real life but needed for tests + var configXml = new ConfigParser(configPath); + configXml.removePlugin(target); + configXml.write(); + events.emit('results', 'config.xml entry for ' +target+ ' is removed'); + } + } + }) + .then(function(){ + // Remove plugin from fetch.json + events.emit('verbose', 'Removing plugin ' + target + ' from fetch.json'); + metadata.remove_fetch_metadata(pluginPath, target); + }); + }, Q()); + }).then(function () { + return require('./prepare').preparePlatforms(platformList, projectRoot, opts); + }).then(function() { + opts.cordova = { plugins: cordova_util.findPlugins(pluginPath) }; + return hooksRunner.fire('after_plugin_rm', opts); + }); + case 'search': + return hooksRunner.fire('before_plugin_search', opts) + .then(function() { + var link = 'http://cordova.apache.org/plugins/'; + if (opts.plugins.length > 0) { + var keywords = (opts.plugins).join(' '); + var query = link + '?q=' + encodeURI(keywords); + opener(query); + } + else { + opener(link); } - target = validatedPluginId; - // Iterate over all installed platforms and uninstall. - // If this is a web-only or dependency-only plugin, then - // there may be nothing to do here except remove the - // reference from the platform's plugin config JSON. - return platformList.reduce(function(soFar, platform) { - return soFar.then(function() { - var platformRoot = path.join(projectRoot, 'platforms', platform); - events.emit('verbose', 'Calling plugman.uninstall on plugin "' + target + '" for platform "' + platform + '"'); - return plugman.raw.uninstall.uninstallPlatform(platform, platformRoot, target, pluginPath); - }); - }, Q()) - .then(function() { - // TODO: Should only uninstallPlugin when no platforms have it. - return plugman.raw.uninstall.uninstallPlugin(target, pluginPath); - }).then(function(){ - //remove plugin from config.xml - if(saveToConfigXmlOn(config_json, opts)){ - var configPath = cordova_util.projectConfig(projectRoot); - if(fs.existsSync(configPath)){//should not happen with real life but needed for tests - var configXml = new ConfigParser(configPath); - configXml.removePlugin(target); - configXml.write(); - events.emit('results', 'config.xml entry for ' +target+ ' is removed'); - } - } - }) - .then(function(){ - // Remove plugin from fetch.json - events.emit('verbose', 'Removing plugin ' + target + ' from fetch.json'); - metadata.remove_fetch_metadata(pluginPath, target); - }); - }, Q()); - }).then(function () { - return require('./prepare').preparePlatforms(platformList, projectRoot, opts); - }).then(function() { - opts.cordova = { plugins: cordova_util.findPlugins(pluginPath) }; - return hooksRunner.fire('after_plugin_rm', opts); - }); - case 'search': - return hooksRunner.fire('before_plugin_search', opts) - .then(function() { - var link = 'http://cordova.apache.org/plugins/'; - if (opts.plugins.length > 0) { - var keywords = (opts.plugins).join(' '); - var query = link + '?q=' + encodeURI(keywords); - opener(query); - } - else { - opener(link); - } - - return Q.resolve(); - }).then(function() { - return hooksRunner.fire('after_plugin_search', opts); - }); - case 'save': - // save the versions/folders/git-urls of currently installed plugins into config.xml - return save(projectRoot, opts); - default: - return list(projectRoot, hooksRunner); - } + return Q.resolve(); + }).then(function() { + return hooksRunner.fire('after_plugin_search', opts); + }); + case 'save': + // save the versions/folders/git-urls of currently installed plugins into config.xml + return save(projectRoot, opts); + default: + return list(projectRoot, hooksRunner); + } + }); }; function validatePluginId(pluginId, installedPlugins) { http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/src/cordova/prepare.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/cordova/prepare.js b/cordova-lib/src/cordova/prepare.js index 2eea9f5..194122e 100644 --- a/cordova-lib/src/cordova/prepare.js +++ b/cordova-lib/src/cordova/prepare.js @@ -34,34 +34,36 @@ var cordova_util = require('./util'), // Returns a promise. exports = module.exports = prepare; function prepare(options) { - var projectRoot = cordova_util.cdProjectRoot(); - var config_json = config.read(projectRoot); - options = options || { verbose: false, platforms: [], options: {} }; - - var hooksRunner = new HooksRunner(projectRoot); - return hooksRunner.fire('before_prepare', options) - .then(function(){ - return restore.installPlatformsFromConfigXML(options.platforms, { searchpath : options.searchpath }); - }) - .then(function(){ - options = cordova_util.preProcessOptions(options); - var paths = options.platforms.map(function(p) { - var platform_path = path.join(projectRoot, 'platforms', p); - return platforms.getPlatformApi(p, platform_path).getPlatformInfo().locations.www; - }); - options.paths = paths; - }).then(function() { - options = cordova_util.preProcessOptions(options); - options.searchpath = options.searchpath || config_json.plugin_search_path; - // Iterate over each added platform - return preparePlatforms(options.platforms, projectRoot, options); - }).then(function() { - options.paths = options.platforms.map(function(platform) { - return platforms.getPlatformApi(platform).getPlatformInfo().locations.www; + return Q().then(function() { + var projectRoot = cordova_util.cdProjectRoot(); + var config_json = config.read(projectRoot); + options = options || { verbose: false, platforms: [], options: {} }; + + var hooksRunner = new HooksRunner(projectRoot); + return hooksRunner.fire('before_prepare', options) + .then(function(){ + return restore.installPlatformsFromConfigXML(options.platforms, { searchpath : options.searchpath }); + }) + .then(function(){ + options = cordova_util.preProcessOptions(options); + var paths = options.platforms.map(function(p) { + var platform_path = path.join(projectRoot, 'platforms', p); + return platforms.getPlatformApi(p, platform_path).getPlatformInfo().locations.www; + }); + options.paths = paths; + }).then(function() { + options = cordova_util.preProcessOptions(options); + options.searchpath = options.searchpath || config_json.plugin_search_path; + // Iterate over each added platform + return preparePlatforms(options.platforms, projectRoot, options); + }).then(function() { + options.paths = options.platforms.map(function(platform) { + return platforms.getPlatformApi(platform).getPlatformInfo().locations.www; + }); + return hooksRunner.fire('after_prepare', options); + }).then(function () { + return restore.installPluginsFromConfigXML(options); }); - return hooksRunner.fire('after_prepare', options); - }).then(function () { - return restore.installPluginsFromConfigXML(options); }); } http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/src/cordova/requirements.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/cordova/requirements.js b/cordova-lib/src/cordova/requirements.js index 3304636..0d8d543 100644 --- a/cordova-lib/src/cordova/requirements.js +++ b/cordova-lib/src/cordova/requirements.js @@ -32,20 +32,22 @@ var knownPlatforms = require('../platforms/platforms'); * requirements check results for each platform. */ module.exports = function check_reqs(platforms) { - platforms = cordova_util.preProcessOptions(platforms).platforms; + return Q().then(function() { + var platforms = cordova_util.preProcessOptions(platforms).platforms; - return Q.allSettled(platforms.map(function (platform) { - return knownPlatforms.getPlatformApi(platform).requirements(); - })) - .then(function (settledChecks) { - var res = {}; - settledChecks.reduce(function (result, settledCheck, idx) { - var platformName = platforms[idx]; - result[platformName] = settledCheck.state === 'fulfilled' ? - settledCheck.value : - new CordovaError(settledCheck.reason); - return result; - }, res); - return res; + return Q.allSettled(platforms.map(function (platform) { + return knownPlatforms.getPlatformApi(platform).requirements(); + })) + .then(function (settledChecks) { + var res = {}; + settledChecks.reduce(function (result, settledCheck, idx) { + var platformName = platforms[idx]; + result[platformName] = settledCheck.state === 'fulfilled' ? + settledCheck.value : + new CordovaError(settledCheck.reason); + return result; + }, res); + return res; + }); }); }; http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/src/cordova/run.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/cordova/run.js b/cordova-lib/src/cordova/run.js index fcfc9c6..f2afeed 100644 --- a/cordova-lib/src/cordova/run.js +++ b/cordova-lib/src/cordova/run.js @@ -1,46 +1,53 @@ -/** - 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 cordova_util = require('./util'), - HooksRunner = require('../hooks/HooksRunner'), - Q = require('q'), - platform_lib = require('../platforms/platforms'); - - -// Returns a promise. -module.exports = function run(options) { - var projectRoot = cordova_util.cdProjectRoot(); - options = cordova_util.preProcessOptions(options); - - var hooksRunner = new HooksRunner(projectRoot); - return hooksRunner.fire('before_run', options) - .then(function() { - // Run a prepare first, then shell out to run - return require('./cordova').raw.prepare(options); - }).then(function() { - // Deploy in parallel (output gets intermixed though...) - return Q.all(options.platforms.map(function(platform) { - return platform_lib - .getPlatformApi(platform) - .run(options.options); - })); - }).then(function() { - return hooksRunner.fire('after_run', options); - }); -}; +/** + 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 cordova_util = require('./util'), + HooksRunner = require('../hooks/HooksRunner'), + Q = require('q'), + platform_lib = require('../platforms/platforms'); + + +// Returns a promise. +module.exports = function run(options) { + return Q().then(function() { + var projectRoot = cordova_util.cdProjectRoot(); + options = cordova_util.preProcessOptions(options); + + var hooksRunner = new HooksRunner(projectRoot); + return hooksRunner.fire('before_run', options) + .then(function() { + // Run a prepare first, then shell out to run + return require('./cordova').raw.prepare(options); + }).then(function() { + // Deploy in parallel (output gets intermixed though...) + return Q.all(options.platforms.map(function(platform) { + return platform_lib + .getPlatformApi(platform) + .run(options.options); + })); + }).then(function() { + return hooksRunner.fire('after_run', options); + }, function(error) { + events.emit('log', 'ERROR running one or more of the platforms: ' + error + '\nYou may not have the required environment or OS to run this project'); + + // CB-10567 bubble up `run` error, so the caller still could get rejected promise + return Q.reject(error); + }); + }); +}; http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4121b11f/cordova-lib/src/cordova/serve.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/cordova/serve.js b/cordova-lib/src/cordova/serve.js index 59eb3e9..e24e990 100644 --- a/cordova-lib/src/cordova/serve.js +++ b/cordova-lib/src/cordova/serve.js @@ -112,29 +112,30 @@ function calculateMd5(fileName) { } module.exports = function server(port, opts) { - var d = Q.defer(); - projectRoot = cordova_util.cdProjectRoot(); port = +port || 8000; - var hooksRunner = new HooksRunner(projectRoot); - hooksRunner.fire('before_serve', opts).then(function () { - // Run a prepare first! - return require('./cordova').raw.prepare([]); - }).then(function () { - var server = serve(); - - installedPlatforms = cordova_util.listPlatforms(projectRoot); - installedPlatforms.forEach(function (platform) { - var locations = platforms.getPlatformApi(platform).getPlatformInfo().locations; - server.app.use('/' + platform + '/www', serve.static(locations.www)); - server.app.get('/' + platform + '/*', getPlatformHandler(platform, locations.www, locations.configXml)); - }); - server.app.get('*', handleRoot); + return Q.promise(function(resolve) { + projectRoot = cordova_util.cdProjectRoot(); + + var hooksRunner = new HooksRunner(projectRoot); + hooksRunner.fire('before_serve', opts).then(function () { + // Run a prepare first! + return require('./cordova').raw.prepare([]); + }).then(function () { + var server = serve(); + + installedPlatforms = cordova_util.listPlatforms(projectRoot); + installedPlatforms.forEach(function (platform) { + var locations = platforms.getPlatformApi(platform).getPlatformInfo().locations; + server.app.use('/' + platform + '/www', serve.static(locations.www)); + server.app.get('/' + platform + '/*', getPlatformHandler(platform, locations.www, locations.configXml)); + }); + server.app.get('*', handleRoot); - server.launchServer({port: port, events: events}); - hooksRunner.fire('after_serve', opts).then(function () { - d.resolve(server.server); + server.launchServer({port: port, events: events}); + hooksRunner.fire('after_serve', opts).then(function () { + resolve(server.server); + }); }); }); - return d.promise; }; --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cordova.apache.org For additional commands, e-mail: commits-h...@cordova.apache.org