You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by an...@apache.org on 2015/09/02 13:31:39 UTC
[1/5] cordova-lib git commit: CB-9597 Initial Implementation of
PlatformApiPoly
Repository: cordova-lib
Updated Branches:
refs/heads/master b0c196510 -> 07271a5c6
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/util/xml-helpers.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/util/xml-helpers.js b/cordova-lib/src/util/xml-helpers.js
index 990f9f7..8b02989 100644
--- a/cordova-lib/src/util/xml-helpers.js
+++ b/cordova-lib/src/util/xml-helpers.js
@@ -192,3 +192,75 @@ function findInsertIdx(children, after) {
//add to the beginning if no matching nodes are found
return typeof foundIndex === 'undefined' ? 0 : foundIndex+1;
}
+
+var BLACKLIST = ['platform', 'feature','plugin','engine'];
+var SINGLETONS = ['content', 'author'];
+function mergeXml(src, dest, platform, clobber) {
+ // Do nothing for blacklisted tags.
+ if (BLACKLIST.indexOf(src.tag) != -1) return;
+
+ //Handle attributes
+ Object.getOwnPropertyNames(src.attrib).forEach(function (attribute) {
+ if (clobber || !dest.attrib[attribute]) {
+ dest.attrib[attribute] = src.attrib[attribute];
+ }
+ });
+ //Handle text
+ if (src.text && (clobber || !dest.text)) {
+ dest.text = src.text;
+ }
+ //Handle platform
+ if (platform) {
+ src.findall('platform[@name="' + platform + '"]').forEach(function (platformElement) {
+ platformElement.getchildren().forEach(mergeChild);
+ });
+ }
+
+ //Handle children
+ src.getchildren().forEach(mergeChild);
+
+ function mergeChild (srcChild) {
+ var srcTag = srcChild.tag,
+ destChild = new et.Element(srcTag),
+ foundChild,
+ query = srcTag + '',
+ shouldMerge = true;
+
+ if (BLACKLIST.indexOf(srcTag) === -1) {
+ if (SINGLETONS.indexOf(srcTag) !== -1) {
+ foundChild = dest.find(query);
+ if (foundChild) {
+ destChild = foundChild;
+ dest.remove(destChild);
+ }
+ } else {
+ //Check for an exact match and if you find one don't add
+ Object.getOwnPropertyNames(srcChild.attrib).forEach(function (attribute) {
+ query += '[@' + attribute + '="' + srcChild.attrib[attribute] + '"]';
+ });
+ var foundChildren = dest.findall(query);
+ for(var i = 0; i < foundChildren.length; i++) {
+ foundChild = foundChildren[i];
+ if (foundChild && textMatch(srcChild, foundChild) && (Object.keys(srcChild.attrib).length==Object.keys(foundChild.attrib).length)) {
+ destChild = foundChild;
+ dest.remove(destChild);
+ shouldMerge = false;
+ break;
+ }
+ }
+ }
+
+ mergeXml(srcChild, destChild, platform, clobber && shouldMerge);
+ dest.append(destChild);
+ }
+ }
+}
+
+// Expose for testing.
+module.exports.mergeXml = mergeXml;
+
+function textMatch(elm1, elm2) {
+ var text1 = elm1.text ? elm1.text.replace(/\s+/, '') : '',
+ text2 = elm2.text ? elm2.text.replace(/\s+/, '') : '';
+ return (text1 === '' || text1 === text2);
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org
[2/5] cordova-lib git commit: CB-9597 Initial Implementation of
PlatformApiPoly
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/platforms/PlatformApiPoly.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/platforms/PlatformApiPoly.js b/cordova-lib/src/platforms/PlatformApiPoly.js
new file mode 100644
index 0000000..183bc4d
--- /dev/null
+++ b/cordova-lib/src/platforms/PlatformApiPoly.js
@@ -0,0 +1,706 @@
+/**
+ 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 Q = require('q');
+var fs = require('fs');
+var path = require('path');
+var unorm = require('unorm');
+var shell = require('shelljs');
+var semver = require('semver');
+
+var superspawn = require('../cordova/superspawn');
+var xmlHelpers = require('../util/xml-helpers');
+var common = require('../plugman/platforms/common');
+var knownPlatforms = require('./platforms');
+var CordovaError = require('../CordovaError');
+var PluginInfo = require('../PluginInfo');
+var ConfigParser = require('../configparser/ConfigParser');
+var PlatformJson = require('../plugman/util/PlatformJson');
+var ActionStack = require('../plugman/util/action-stack');
+var PlatformMunger = require('../plugman/util/config-changes').PlatformMunger;
+var PluginInfoProvider = require('../PluginInfoProvider');
+
+/**
+ * Class, that acts as abstraction over particular platform. Encapsulates the
+ * platform's properties and methods.
+ *
+ * Platform that implements own PlatformApi instance _should implement all
+ * prototype methods_ of this class to be fully compatible with cordova-lib.
+ *
+ * The PlatformApi instance also should define the following field:
+ *
+ * * platform: String that defines a platform name.
+ */
+function PlatformApiPoly(platform, platformRootDir) {
+ if (!platform) throw new CordovaError('\'platform\' argument is missing');
+ if (!platformRootDir) throw new CordovaError('platformRootDir argument is missing');
+
+ this.root = platformRootDir;
+ this.platform = platform;
+
+ if (!(platform in knownPlatforms))
+ throw new CordovaError('Unknown platform ' + platform);
+
+ var ParserConstructor = require(knownPlatforms[platform].parser_file);
+ this._parser = new ParserConstructor(this.root);
+ this._handler = require(knownPlatforms[platform].handler_file);
+
+ this._platformJson = PlatformJson.load(this.root, platform);
+ this._pluginInfoProvider = new PluginInfoProvider();
+ this._munger = new PlatformMunger(platform, this.root, this._platformJson, this._pluginInfoProvider);
+
+ this._config = new ConfigParser(this.getPlatformInfo().locations.configXml);
+}
+
+/**
+ * Installs platform to specified directory and creates a platform project.
+ *
+ * @param {CordovaProject} cordovaProject A CordovaProject instance, that defines a
+ * project structure and configuration, that should be applied to new platform
+ * (contains platform's target location and ConfigParser instance for
+ * project's config). This argument is optional and if not defined, this means
+ * that platform is used as standalone project and is not a part of cordova
+ * project.
+ * @param {Object} options An options object. The most common options are:
+ * @param {String} options.customTemplate A path to custom template, that
+ * should override the default one from platform.
+ * @param {Boolean} options.link Flag that indicates that platform's sources
+ * will be linked to installed platform instead of copying.
+ *
+ * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
+ * instance or rejected with CordovaError.
+ */
+PlatformApiPoly.createPlatform = function (cordovaProject, options) {
+ if (!options || !options.platformDetails)
+ return Q.reject(CordovaError('Failed to find platform\'s \'create\' script. ' +
+ 'Either \'options\' parameter or \'platformDetails\' option is missing'));
+
+ var command = path.join(options.platformDetails.libDir, 'bin', 'create');
+ var commandArguments = getCreateArgs(cordovaProject, options);
+
+ return superspawn.spawn(command, commandArguments,
+ { printCommand: true, stdio: 'inherit', chmod: true })
+ .then(function () {
+ var destination = path.join(cordovaProject.locations.platforms, options.platformDetails.platform);
+ var platformApi = knownPlatforms
+ .getPlatformApi(options.platformDetails.platform, destination);
+ copyCordovaSrc(options.platformDetails.libDir, platformApi.getPlatformInfo());
+ return platformApi;
+ });
+};
+
+/**
+ * Updates already installed platform.
+ *
+ * @param {CordovaProject} cordovaProject A CordovaProject instance, that
+ * defines a project structure and configuration, that should be applied to
+ * new platform (contains platform's target location and ConfigParser instance
+ * for project's config). This argument is optional and if not defined, this
+ * means that platform is used as standalone project and is not a part of
+ * cordova project.
+ * @param {Object} options An options object. The most common options are:
+ * @param {String} options.customTemplate A path to custom template, that
+ * should override the default one from platform.
+ * @param {Boolean} options.link Flag that indicates that platform's sources
+ * will be linked to installed platform instead of copying.
+ *
+ * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
+ * instance or rejected with CordovaError.
+ */
+PlatformApiPoly.updatePlatform = function (cordovaProject, options) {
+ if (!options || !options.platformDetails)
+ return Q.reject(CordovaError('Failed to find platform\'s \'create\' script. ' +
+ 'Either \'options\' parameter or \'platformDetails\' option is missing'));
+
+ var command = path.join(options.platformDetails.libDir, 'bin', 'update');
+ var destination = path.join(cordovaProject.locations.platforms, options.platformDetails.platform);
+
+ return superspawn.spawn(command, [destination],
+ { printCommand: true, stdio: 'inherit', chmod: true })
+ .then(function () {
+ var platformApi = knownPlatforms
+ .getPlatformApi(options.platformDetails.platform, destination);
+ copyCordovaSrc(options.platformDetails.libDir, platformApi.getPlatformInfo());
+ return platformApi;
+ });
+};
+
+/**
+ * Gets a CordovaPlatform object, that represents the platform structure.
+ *
+ * @return {CordovaPlatform} A structure that contains the description of
+ * platform's file structure and other properties of platform.
+ */
+PlatformApiPoly.prototype.getPlatformInfo = function () {
+ var self = this;
+ var result = {};
+ result.locations = {
+ www: self._parser.www_dir(),
+ platformWww: path.join(self.root, 'platform_www'),
+ configXml: self._parser.config_xml(),
+ // NOTE: Due to platformApi spec we need to return relative paths here
+ cordovaJs: path.relative(self.root, self._parser.cordovajs_path.call(self.parser, self.root)),
+ cordovaJsSrc: path.relative(self.root, self._parser.cordovajs_src_path.call(self.parser, self.root))
+ };
+ result.root = self.root;
+ result.name = self.platform;
+ result.version = knownPlatforms[self.platform].version;
+ result.projectConfig = self._config;
+
+ return result;
+};
+
+/**
+ * Updates installed platform with provided www assets and new app
+ * configuration. This method is required for CLI workflow and will be called
+ * each time before build, so the changes, made to app configuration and www
+ * code, will be applied to platform.
+ *
+ * @param {CordovaProject} cordovaProject A CordovaProject instance, that defines a
+ * project structure and configuration, that should be applied to platform
+ * (contains project's www location and ConfigParser instance for project's
+ * config).
+ *
+ * @return {Promise} Return a promise either fulfilled, or rejected with
+ * CordovaError instance.
+ */
+PlatformApiPoly.prototype.prepare = function (cordovaProject) {
+
+ // First cleanup current config and merge project's one into own
+ var defaultConfig = path.join(this.root, 'cordova', 'defaults.xml');
+ var ownConfig = this._config.path;
+ var sourceCfg = cordovaProject.projectConfig.path;
+ // If defaults.xml is present, overwrite platform config.xml with it.
+ // Otherwise save whatever is there as defaults so it can be
+ // restored or copy project config into platform if none exists.
+ if (fs.existsSync(defaultConfig)) {
+ // events.emit('verbose', 'Generating config.xml from defaults for platform "' + this.platform + '"');
+ shell.cp('-f', defaultConfig, ownConfig);
+ this._config = new ConfigParser(ownConfig);
+ } else if (fs.existsSync(ownConfig)) {
+ shell.cp('-f', ownConfig, defaultConfig);
+ } else {
+ shell.cp('-f', sourceCfg.path, ownConfig);
+ this._config = new ConfigParser(ownConfig);
+ }
+
+ xmlHelpers.mergeXml(cordovaProject.projectConfig.doc.getroot(),
+ this._config.doc.getroot(), this.platform, true);
+ // CB-6976 Windows Universal Apps. For smooth transition and to prevent mass api failures
+ // we allow using windows8 tag for new windows platform
+ if (this.platform == 'windows') {
+ xmlHelpers.mergeXml(cordovaProject.projectConfig.doc.getroot(),
+ this._config.doc.getroot(), 'windows8', true);
+ }
+ this._config.write();
+
+ // Update own www dir with project's www assets and plugins' assets and js-files
+ this._parser.update_www(cordovaProject.locations.www);
+
+ this._munger.reapply_global_munge().save_all();
+
+ // update project according to config.xml changes.
+ return this._parser.update_project(cordovaProject.projectConfig);
+};
+
+/**
+ * Installs a new plugin into platform. This method only copies non-www files
+ * (sources, libs, etc.) to platform. It also doesn't resolves the
+ * dependencies of plugin. Both of handling of www files, such as assets and
+ * js-files and resolving dependencies are the responsibility of caller.
+ *
+ * @param {PluginInfo} plugin A PluginInfo instance that represents plugin
+ * that will be installed.
+ * @param {Object} installOptions An options object. Possible options below:
+ * @param {Boolean} installOptions.link: Flag that specifies that plugin
+ * sources will be symlinked to app's directory instead of copying (if
+ * possible).
+ * @param {Object} installOptions.variables An object that represents
+ * variables that will be used to install plugin. See more details on plugin
+ * variables in documentation:
+ * https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html
+ *
+ * @return {Promise} Return a promise either fulfilled, or rejected with
+ * CordovaError instance.
+ */
+PlatformApiPoly.prototype.addPlugin = function (plugin, installOptions) {
+
+ if (!plugin || !(plugin instanceof PluginInfo))
+ return Q.reject('The parameter is incorrect. The first parameter ' +
+ 'should be valid PluginInfo instance');
+
+ installOptions = installOptions || {};
+ installOptions.variables = installOptions.variables || {};
+
+ var self = this;
+ var actions = new ActionStack();
+ var projectFile = this._handler.parseProjectFile && this._handler.parseProjectFile(this.root);
+
+ // gather all files needs to be handled during install
+ plugin.getFilesAndFrameworks(this.platform)
+ .concat(plugin.getAssets(this.platform))
+ .concat(plugin.getJsModules(this.platform))
+ .forEach(function(item) {
+ actions.push(actions.createAction(
+ self._getInstaller(item.itemType), [item, plugin.dir, plugin.id, installOptions, projectFile],
+ self._getUninstaller(item.itemType), [item, plugin.dir, plugin.id, installOptions, projectFile]));
+ });
+
+ // run through the action stack
+ return actions.process(this.platform, this.root)
+ .then(function () {
+ if (projectFile) {
+ projectFile.write();
+ }
+
+ // Add PACKAGE_NAME variable into vars
+ if (!installOptions.variables.PACKAGE_NAME) {
+ installOptions.variables.PACKAGE_NAME = self._handler.package_name(self.root);
+ }
+
+ self._munger
+ // Ignore passed `is_top_level` option since platform itself doesn't know
+ // anything about managing dependencies - it's responsibility of caller.
+ .add_plugin_changes(plugin, installOptions.variables, /*is_top_level=*/true, /*should_increment=*/true)
+ .save_all();
+
+ var targetDir = installOptions.usePlatformWww ?
+ self.getPlatformInfo().locations.platformWww :
+ self.getPlatformInfo().locations.www;
+
+ self._addModulesInfo(plugin, targetDir);
+ });
+};
+
+/**
+ * Removes an installed plugin from platform.
+ *
+ * Since method accepts PluginInfo instance as input parameter instead of plugin
+ * id, caller shoud take care of managing/storing PluginInfo instances for
+ * future uninstalls.
+ *
+ * @param {PluginInfo} plugin A PluginInfo instance that represents plugin
+ * that will be installed.
+ *
+ * @return {Promise} Return a promise either fulfilled, or rejected with
+ * CordovaError instance.
+ */
+PlatformApiPoly.prototype.removePlugin = function (plugin, uninstallOptions) {
+
+ var self = this;
+ var actions = new ActionStack();
+ var projectFile = this._handler.parseProjectFile && this._handler.parseProjectFile(this.root);
+
+ // queue up plugin files
+ plugin.getFilesAndFrameworks(this.platform)
+ .concat(plugin.getAssets(this.platform))
+ .concat(plugin.getJsModules(this.platform))
+ .filter(function (item) {
+ // CB-5238 Skip (don't uninstall) non custom frameworks.
+ return !(item.itemType == 'framework' && !item.custom);
+ }).forEach(function(item) {
+ actions.push(actions.createAction(
+ self._getUninstaller(item.itemType), [item, plugin.dir, plugin.id, uninstallOptions, projectFile],
+ self._getInstaller(item.itemType), [item, plugin.dir, plugin.id, uninstallOptions, projectFile]));
+ });
+
+ // run through the action stack
+ return actions.process(this.platform, this.root)
+ .then(function() {
+ if (projectFile) {
+ projectFile.write();
+ }
+
+ self._munger
+ // Ignore passed `is_top_level` option since platform itself doesn't know
+ // anything about managing dependencies - it's responsibility of caller.
+ .remove_plugin_changes(plugin, /*is_top_level=*/true)
+ .save_all();
+
+ var targetDir = uninstallOptions.usePlatformWww ?
+ self.getPlatformInfo().locations.platformWww :
+ self.getPlatformInfo().locations.www;
+
+ self._removeModulesInfo(plugin, targetDir);
+ // Remove stale plugin directory
+ // TODO: this should be done by plugin files uninstaller
+ shell.rm('-rf', path.resolve(self.root, 'Plugins', plugin.id));
+ });
+};
+
+PlatformApiPoly.prototype.updatePlugin = function (plugin, updateOptions) {
+ var self = this;
+
+ // Set up assets installer to copy asset files into platform_www dir instead of www
+ updateOptions = updateOptions || {};
+ updateOptions.usePlatformWww = true;
+
+ return this.removePlugin(plugin, updateOptions)
+ .then(function () {
+ return self.addPlugin(plugin, updateOptions);
+ });
+};
+
+/**
+ * Builds an application package for current platform.
+ *
+ * @param {Object} buildOptions A build options. This object's structure is
+ * highly depends on platform's specific. The most common options are:
+ * @param {Boolean} buildOptions.debug Indicates that packages should be
+ * built with debug configuration. This is set to true by default unless the
+ * 'release' option is not specified.
+ * @param {Boolean} buildOptions.release Indicates that packages should be
+ * built with release configuration. If not set to true, debug configuration
+ * will be used.
+ * @param {Boolean} buildOptions.device Specifies that built app is intended
+ * to run on device
+ * @param {Boolean} buildOptions.emulator: Specifies that built app is
+ * intended to run on emulator
+ * @param {String} buildOptions.target Specifies the device id that will be
+ * used to run built application.
+ * @param {Boolean} buildOptions.nobuild Indicates that this should be a
+ * dry-run call, so no build artifacts will be produced.
+ * @param {String[]} buildOptions.archs Specifies chip architectures which
+ * app packages should be built for. List of valid architectures is depends on
+ * platform.
+ * @param {String} buildOptions.buildConfig The path to build configuration
+ * file. The format of this file is depends on platform.
+ * @param {String[]} buildOptions.argv Raw array of command-line arguments,
+ * passed to `build` command. The purpose of this property is to pass a
+ * platform-specific arguments, and eventually let platform define own
+ * arguments processing logic.
+ *
+ * @return {Promise<Object[]>} A promise either fulfilled with an array of build
+ * artifacts (application packages) if package was built successfully,
+ * or rejected with CordovaError. The resultant build artifact objects is not
+ * strictly typed and may conatin arbitrary set of fields as in sample below.
+ *
+ * {
+ * architecture: 'x86',
+ * buildType: 'debug',
+ * path: '/path/to/build',
+ * type: 'app'
+ * }
+ *
+ * The return value in most cases will contain only one item but in some cases
+ * there could be multiple items in output array, e.g. when multiple
+ * arhcitectures is specified.
+ */
+PlatformApiPoly.prototype.build = function(buildOptions) {
+ var command = path.join(this.root, 'cordova', 'build');
+ var commandArguments = getBuildArgs(buildOptions);
+ return superspawn.spawn(command, commandArguments, {
+ printCommand: true, stdio: 'inherit', chmod: true });
+};
+
+/**
+ * Builds an application package for current platform and runs it on
+ * specified/default device. If no 'device'/'emulator'/'target' options are
+ * specified, then tries to run app on default device if connected, otherwise
+ * runs the app on emulator.
+ *
+ * @param {Object} runOptions An options object. The structure is the same
+ * as for build options.
+ *
+ * @return {Promise} A promise either fulfilled if package was built and ran
+ * successfully, or rejected with CordovaError.
+ */
+PlatformApiPoly.prototype.run = function(runOptions) {
+ var command = path.join(this.root, 'cordova', 'run');
+ var commandArguments = getBuildArgs(runOptions);
+ return superspawn.spawn(command, commandArguments, {
+ printCommand: true, stdio: 'inherit', chmod: true });
+};
+
+/**
+ * Cleans out the build artifacts from platform's directory.
+ *
+ * @return {Promise} Return a promise either fulfilled, or rejected with
+ * CordovaError.
+ */
+PlatformApiPoly.prototype.clean = function() {
+ var cmd = path.join(this.root, 'cordova', 'clean');
+ return superspawn.spawn(cmd, [], { printCommand: true, stdio: 'inherit', chmod: true });
+};
+
+/**
+ * Performs a requirements check for current platform. Each platform defines its
+ * own set of requirements, which should be resolved before platform can be
+ * built successfully.
+ *
+ * @return {Promise<Requirement[]>} Promise, resolved with set of Requirement
+ * objects for current platform.
+ */
+PlatformApiPoly.prototype.requirements = function() {
+ var modulePath = path.join(this.root, 'cordova', 'lib', 'check_reqs');
+ try {
+ return require(modulePath).check_all();
+ } catch (e) {
+ var errorMsg = 'Failed to check requirements for ' + this.platform + ' platform. ' +
+ 'check_reqs module is missing for platfrom. Skipping it...';
+ return Q.reject(errorMsg);
+ }
+};
+
+module.exports = PlatformApiPoly;
+
+/**
+ * Converts arguments, passed to createPlatform to command-line args to
+ * 'bin/create' script for specific platform.
+ *
+ * @param {ProjectInfo} project A current project information. The vauest
+ * which this method interested in are project.config - config.xml abstraction
+ * - and platformsLocation - to get install destination.
+ * @param {Object} options Set of properties for create script.
+ *
+ * @return {String[]} An array or arguments which can be passed to
+ * 'bin/create'.
+ */
+function getCreateArgs(project, options) {
+ var platformName = options.platformDetails.platform;
+ var platformVersion = options.platformDetails.version;
+
+ var args = [];
+ args.push(path.join(project.locations.platforms, platformName)); // output
+ args.push(project.projectConfig.packageName().replace(/[^\w.]/g,'_'));
+ // CB-6992 it is necessary to normalize characters
+ // because node and shell scripts handles unicode symbols differently
+ // We need to normalize the name to NFD form since iOS uses NFD unicode form
+ args.push(platformName == 'ios' ? unorm.nfd(project.projectConfig.name()) : project.projectConfig.name());
+
+ if (options.customTemplate) {
+ args.push(options.customTemplate);
+ }
+
+ if (/android|ios/.exec(platformName) &&
+ semver.gt(platformVersion, '3.3.0')) args.push('--cli');
+
+ if (options.link) args.push('--link');
+
+ if (platformName === 'android' && semver.gte(platformVersion, '4.0.0-dev')) {
+ var activityName = project.projectConfig.android_activityName();
+ if (activityName) {
+ args.push('--activity-name', activityName.replace(/\W/g, ''));
+ }
+ }
+
+ return args;
+}
+
+/**
+ * Reconstructs the buildOptions tat will be passed along to platform scripts.
+ * This is an ugly temporary fix. The code spawning or otherwise calling into
+ * platform code should be dealing with this based on the parsed args object.
+ *
+ * @param {Object} options A build options set, passed to `build` method
+ *
+ * @return {String[]} An array or arguments which can be passed to
+ * `create` build script.
+ */
+function getBuildArgs(options) {
+ // if no options passed, empty object will be returned
+ if (!options) return [];
+
+ var downstreamArgs = [];
+ var argNames =[
+ 'debug',
+ 'release',
+ 'device',
+ 'emulator',
+ 'nobuild',
+ 'list'
+ ];
+
+ argNames.forEach(function(flag) {
+ if (options[flag]) {
+ downstreamArgs.push('--' + flag);
+ }
+ });
+
+ if (options.buildConfig) {
+ downstreamArgs.push('--buildConfig=' + options.buildConfig);
+ }
+ if (options.target) {
+ downstreamArgs.push('--target=' + options.target);
+ }
+ if (options.archs) {
+ downstreamArgs.push('--archs=' + options.archs);
+ }
+
+ var unparsedArgs = options.argv || [];
+ return downstreamArgs.concat(unparsedArgs);
+}
+
+/**
+ * Removes the specified modules from list of installed modules and updates
+ * platform_json and cordova_plugins.js on disk.
+ *
+ * @param {PluginInfo} plugin PluginInfo instance for plugin, which modules
+ * needs to be added.
+ * @param {String} targetDir The directory, where updated cordova_plugins.js
+ * should be written to.
+ */
+PlatformApiPoly.prototype._addModulesInfo = function(plugin, targetDir) {
+ var installedModules = this._platformJson.root.modules || [];
+
+ var installedPaths = installedModules.map(function (installedModule) {
+ return installedModule.file;
+ });
+
+ var modulesToInstall = plugin.getJsModules(this.platform)
+ .filter(function (moduleToInstall) {
+ return installedPaths.indexOf(moduleToInstall.file) === -1;
+ }).map(function (moduleToInstall) {
+ var moduleName = plugin.id + '.' + ( moduleToInstall.name || moduleToInstall.src.match(/([^\/]+)\.js/)[1] );
+ var obj = {
+ file: ['plugins', plugin.id, moduleToInstall.src].join('/'),
+ id: moduleName
+ };
+ if (moduleToInstall.clobbers.length > 0) {
+ obj.clobbers = moduleToInstall.clobbers.map(function(o) { return o.target; });
+ }
+ if (moduleToInstall.merges.length > 0) {
+ obj.merges = moduleToInstall.merges.map(function(o) { return o.target; });
+ }
+ if (moduleToInstall.runs) {
+ obj.runs = true;
+ }
+
+ return obj;
+ });
+
+ this._platformJson.root.modules = installedModules.concat(modulesToInstall);
+ this._writePluginModules(targetDir);
+ this._platformJson.save();
+};
+
+/**
+ * Removes the specified modules from list of installed modules and updates
+ * platform_json and cordova_plugins.js on disk.
+ *
+ * @param {PluginInfo} plugin PluginInfo instance for plugin, which modules
+ * needs to be removed.
+ * @param {String} targetDir The directory, where updated cordova_plugins.js
+ * should be written to.
+ */
+PlatformApiPoly.prototype._removeModulesInfo = function(plugin, targetDir) {
+ var installedModules = this._platformJson.root.modules || [];
+ var modulesToRemove = plugin.getJsModules(this.platform)
+ .map(function (jsModule) {
+ return ['plugins', plugin.id, jsModule.src].join('/');
+ });
+
+ var updatedModules = installedModules
+ .filter(function (installedModule) {
+ return (modulesToRemove.indexOf(installedModule.file) === -1);
+ });
+
+ this._platformJson.root.modules = updatedModules;
+ this._writePluginModules(targetDir);
+ this._platformJson.save();
+};
+
+/**
+ * Fetches all installed modules, generates cordova_plugins contents and writes
+ * it to file.
+ *
+ * @param {String} targetDir Directory, where write cordova_plugins.js to.
+ * Ususally it is either <platform>/www or <platform>/platform_www
+ * directories.
+ */
+PlatformApiPoly.prototype._writePluginModules = function (targetDir) {
+ var self = this;
+ // Write out moduleObjects as JSON wrapped in a cordova module to cordova_plugins.js
+ var final_contents = 'cordova.define(\'cordova/plugin_list\', function(require, exports, module) {\n';
+ final_contents += 'module.exports = ' + JSON.stringify(this._platformJson.root.modules, null, ' ') + ';\n';
+ final_contents += 'module.exports.metadata = \n';
+ final_contents += '// TOP OF METADATA\n';
+
+ var pluginMetadata = Object.keys(this._platformJson.root.installed_plugins)
+ .reduce(function (metadata, plugin) {
+ metadata[plugin] = self._platformJson.root.installed_plugins[plugin].version;
+ return metadata;
+ }, {});
+
+ final_contents += JSON.stringify(pluginMetadata, null, ' ') + '\n';
+ final_contents += '// BOTTOM OF METADATA\n';
+ final_contents += '});'; // Close cordova.define.
+
+ shell.mkdir('-p', targetDir);
+ fs.writeFileSync(path.join(targetDir, 'cordova_plugins.js'), final_contents, 'utf-8');
+};
+
+PlatformApiPoly.prototype._getInstaller = function(type) {
+ var self = this;
+ return function (item, plugin_dir, plugin_id, options, project) {
+ var installer = self._handler[type] || common[type];
+
+ var wwwDest = options.usePlatformWww ?
+ self.getPlatformInfo().locations.platformWww :
+ self._handler.www_dir(self.root);
+
+ var installerArgs = type === 'asset' ? [wwwDest] :
+ type === 'js-module' ? [plugin_id, wwwDest]:
+ [self.root, plugin_id, options, project];
+
+ installer.install.apply(null, [item, plugin_dir].concat(installerArgs));
+ };
+};
+
+PlatformApiPoly.prototype._getUninstaller = function(type) {
+ var self = this;
+ return function (item, plugin_dir, plugin_id, options, project) {
+ var uninstaller = self._handler[type] || common[type];
+
+ var wwwDest = options.usePlatformWww ?
+ self.getPlatformInfo().locations.platformWww :
+ self._handler.www_dir(self.root);
+
+ var uninstallerArgs = (type === 'asset' || type === 'js-module') ? [wwwDest, plugin_id] :
+ [self.root, plugin_id, options, project];
+
+ uninstaller.uninstall.apply(null, [item].concat(uninstallerArgs));
+ };
+};
+
+/**
+ * Copies cordova.js itself and cordova-js source into installed/updated
+ * platform's `platform_www` directory.
+ *
+ * @param {String} sourceLib Path to platform library. Required to acquire
+ * cordova-js sources.
+ * @param {PlatformInfo} platformInfo PlatformInfo structure, required for
+ * detecting copied files destination.
+ */
+function copyCordovaSrc(sourceLib, platformInfo) {
+ // Copy the cordova.js file to platforms/<platform>/platform_www/
+ // The www dir is nuked on each prepare so we keep cordova.js in platform_www
+ shell.mkdir('-p', platformInfo.locations.platformWww);
+ shell.cp('-f', path.join(platformInfo.locations.www, 'cordova.js'),
+ path.join(platformInfo.locations.platformWww, 'cordova.js'));
+
+ // Copy cordova-js-src directory into platform_www directory.
+ // We need these files to build cordova.js if using browserify method.
+ var cordovaJsSrcPath = path.resolve(sourceLib, platformInfo.locations.cordovaJsSrc);
+
+ //only exists for platforms that have shipped cordova-js-src directory
+ if(fs.existsSync(cordovaJsSrcPath)) {
+ shell.cp('-rf', cordovaJsSrcPath, platformInfo.locations.platformWww);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/platforms/platforms.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/platforms/platforms.js b/cordova-lib/src/platforms/platforms.js
index cc0e492..d71570f 100644
--- a/cordova-lib/src/platforms/platforms.js
+++ b/cordova-lib/src/platforms/platforms.js
@@ -17,89 +17,47 @@
under the License.
*/
+var path = require('path');
+var util = require('../cordova/util');
var platforms = require('./platformsConfig.json');
-// Remove this block soon. The parser property is no longer used in
-// cordova-lib but some downstream tools still use it.
-var addModuleProperty = require('../cordova/util').addModuleProperty;
-Object.keys(platforms).forEach(function(key) {
- var obj = platforms[key];
- if (obj.parser_file) {
- addModuleProperty(module, 'parser', obj.parser_file, false, obj);
- }
-});
-
-
// Avoid loading the same platform projects more than once (identified by path)
-var cachedProjects = {};
-
-var PARSER_PUBLIC_METHODS = [
- 'config_xml',
- 'cordovajs_path',
- 'cordovajs_src_path',
- 'update_from_config',
- 'update_project',
- 'update_www',
- 'www_dir',
-];
-
-var HANDLER_PUBLIC_METHODS = [
- 'package_name',
- 'parseProjectFile',
- 'purgeProjectFileCache',
-];
-
+var cachedApis = {};
-// A single class that exposes functionality from platform specific files from
-// both places cordova/metadata and plugman/platforms. Hopefully, to be soon
-// replaced by real unified platform specific classes.
-function PlatformProjectAdapter(platform, platformRootDir) {
- var self = this;
- self.root = platformRootDir;
- self.platform = platform;
- var ParserConstructor = require(platforms[platform].parser_file);
- self.parser = new ParserConstructor(platformRootDir);
- self.handler = require(platforms[platform].handler_file);
+// getPlatformApi() should be the only method of instantiating the
+// PlatformProject classes for now.
+function getPlatformApi(platform, platformRootDir) {
- // Expose all public methods from the parser and handler, properly bound.
- PARSER_PUBLIC_METHODS.forEach(function(method) {
- self[method] = self.parser[method].bind(self.parser);
- });
+ // if platformRootDir is not specified, try to detect it first
+ if (!platformRootDir) {
+ var projectRootDir = util.isCordova();
+ platformRootDir = projectRootDir && path.join(projectRootDir, 'platforms', platform);
+ }
- HANDLER_PUBLIC_METHODS.forEach(function(method) {
- if (self.handler[method]) {
- self[method] = self.handler[method].bind(self.handler);
- }
- });
+ if (!platformRootDir) {
+ // If platformRootDir is still undefined, then we're probably is not inside of cordova project
+ throw new Error('Current location is not a Cordova project');
+ }
- self.getInstaller = function(type) {
- function installWrapper(item, plugin_dir, plugin_id, options, project) {
- self.handler[type].install(item, plugin_dir, self.root, plugin_id, options, project);
- }
- return installWrapper;
- };
+ var cached = cachedApis[platformRootDir];
+ if (cached && cached.platform == platform) return cached;
- self.getUninstaller = function(type) {
- function uninstallWrapper(item, plugin_id, options, project) {
- self.handler[type].uninstall(item, self.root, plugin_id, options, project);
- }
- return uninstallWrapper;
- };
-}
+ if (!platforms[platform]) throw new Error('Unknown platform ' + platform);
-// getPlatformProject() should be the only method of instantiating the
-// PlatformProject classes for now.
-function getPlatformProject(platform, platformRootDir) {
- var cached = cachedProjects[platformRootDir];
- if (cached && cached.platform == platform) {
- return cachedProjects[platformRootDir];
- } else if (platforms[platform]) {
- var adapter = new PlatformProjectAdapter(platform, platformRootDir);
- cachedProjects[platformRootDir] = adapter;
- return adapter;
- } else {
- throw new Error('Unknown platform ' + platform);
+ var PlatformApi;
+ try {
+ // First we need to find whether platform exposes its' API via js module
+ // If it has, then we have to require it and extend BasePlatformApi
+ // with platform's API.
+ var platformApiModule = path.join(platformRootDir, 'cordova', 'Api.js');
+ PlatformApi = require(platformApiModule);
+ } catch (err) {
+ PlatformApi = require('./PlatformApiPoly');
}
+
+ var platformApi = new PlatformApi(platform, platformRootDir);
+ cachedApis[platformRootDir] = platformApi;
+ return platformApi;
}
module.exports = platforms;
@@ -107,6 +65,5 @@ module.exports = platforms;
// We don't want these methods to be enumerable on the platforms object, because we expect enumerable properties of the
// platforms object to be platforms.
Object.defineProperties(module.exports, {
- 'getPlatformProject': {value: getPlatformProject, configurable: true, writable: true},
- 'PlatformProjectAdapter': {value: PlatformProjectAdapter, configurable: true, writable: true}
+ 'getPlatformApi': {value: getPlatformApi, configurable: true, writable: true}
});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/plugman/browserify.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/browserify.js b/cordova-lib/src/plugman/browserify.js
new file mode 100644
index 0000000..8d5581b
--- /dev/null
+++ b/cordova-lib/src/plugman/browserify.js
@@ -0,0 +1,181 @@
+/**
+ 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.
+*/
+
+/* jshint unused:false, expr:true */
+
+var platform_modules = require('../platforms/platforms'),
+ path = require('path'),
+ aliasify = require('aliasify'),
+ config_changes = require('./util/config-changes'),
+ common = require('./platforms/common'),
+ fs = require('fs'),
+ childProcess = require('child_process'),
+ util = require('util'),
+ events = require('../events'),
+ plugman = require('./plugman'),
+ bundle = require('cordova-js/tasks/lib/bundle-browserify'),
+ writeLicenseHeader = require('cordova-js/tasks/lib/write-license-header'),
+ Q = require('q'),
+ computeCommitId = require('cordova-js/tasks/lib/compute-commit-id'),
+ Readable = require('stream').Readable;
+
+var PlatformJson = require('./util/PlatformJson');
+var PluginInfoProvider = require('../PluginInfoProvider');
+
+function generateFinalBundle(platform, libraryRelease, outReleaseFile, commitId, platformVersion) {
+ var deferred = Q.defer();
+ var outReleaseFileStream = fs.createWriteStream(outReleaseFile);
+ var time = new Date().valueOf();
+ var symbolList = null;
+
+ writeLicenseHeader(outReleaseFileStream, platform, commitId, platformVersion);
+
+ var releaseBundle = libraryRelease.bundle();
+
+ releaseBundle.pipe(outReleaseFileStream);
+
+ outReleaseFileStream.on('finish', function() {
+ var newtime = new Date().valueOf() - time;
+ plugman.emit('verbose', 'generated cordova.' + platform + '.js @ ' + commitId + ' in ' + newtime + 'ms');
+ deferred.resolve();
+ // TODO clean up all the *.browserify files
+ });
+
+ outReleaseFileStream.on('error', function(err) {
+ events.emit('log', 'error while generating cordova.js');
+ deferred.reject();
+ });
+ return deferred.promise;
+}
+
+function computeCommitIdSync() {
+ var deferred = Q.defer();
+ computeCommitId(function(cId){
+ deferred.resolve(cId);
+ });
+ return deferred.promise;
+}
+
+function getPlatformVersion(cId, project_dir) {
+ var deferred = Q.defer();
+ //run version script for each platform to get platformVersion
+ var versionPath = path.join(project_dir, '/cordova/version');
+ childProcess.exec('"' + versionPath + '"', function(err, stdout, stderr) {
+ if (err) {
+ events.emit('log', 'Error running platform version script');
+ events.emit('log', err);
+ deferred.resolve('N/A');
+ } else {
+ deferred.resolve(stdout.trim());
+ }
+ });
+ return deferred.promise;
+}
+
+module.exports = function doBrowserify (project, platformApi, pluginInfoProvider) {
+ // Process:
+ // - Do config munging by calling into config-changes module
+ // - List all plugins in plugins_dir
+ // - Load and parse their plugin.xml files.
+ // - Skip those without support for this platform. (No <platform> tags means JS-only!)
+ // - Build a list of all their js-modules, including platform-specific js-modules.
+ // - For each js-module (general first, then platform) build up an object storing the path and any clobbers, merges and runs for it.
+ // Write this object into www/cordova_plugins.json.
+ // This file is not really used. Maybe cordova app harness
+ var platform = platformApi.platform;
+ events.emit('verbose', 'Preparing ' + platform + ' browserify project');
+ pluginInfoProvider = pluginInfoProvider || new PluginInfoProvider(); // Allow null for backwards-compat.
+ var platformJson = PlatformJson.load(project.locations.plugins, platform);
+ var wwwDir = platformApi.getPlatformInfo().locations.www;
+
+ var commitId;
+ return computeCommitIdSync()
+ .then(function(cId){
+ commitId = cId;
+ return getPlatformVersion(commitId, platformApi.root);
+ }).then(function(platformVersion){
+ var libraryRelease = bundle(platform, false, commitId, platformVersion);
+
+ var pluginMetadata = {};
+ var modulesMetadata = [];
+
+ var plugins = Object.keys(platformJson.root.installed_plugins).concat(Object.keys(platformJson.root.dependent_plugins));
+ events.emit('verbose', 'Iterating over installed plugins:', plugins);
+ plugins.forEach(function (plugin) {
+ var pluginDir = path.join(project.locations.plugins, plugin);
+ var pluginInfo = pluginInfoProvider.get(pluginDir);
+ // pluginMetadata is a mapping from plugin IDs to versions.
+ pluginMetadata[pluginInfo.id] = pluginInfo.version;
+
+ // Copy www assets described in <asset> tags.
+ pluginInfo.getAssets(platform)
+ .forEach(function(asset) {
+ common.asset.install(asset, pluginDir, wwwDir);
+ });
+
+ pluginInfo.getJsModules(platform)
+ .forEach(function(jsModule) {
+ var moduleName = jsModule.name ? jsModule.name : path.basename(jsModule.src, '.js');
+ var moduleId = pluginInfo.id + '.' + moduleName;
+ var moduleMetadata = {file: jsModule.src, id: moduleId, name: moduleName};
+
+ if (jsModule.clobbers.length > 0) {
+ moduleMetadata.clobbers = jsModule.clobbers.map(function(o) { return o.target; });
+ }
+ if (jsModule.merges.length > 0) {
+ moduleMetadata.merges = jsModule.merges.map(function(o) { return o.target; });
+ }
+ if (jsModule.runs) {
+ moduleMetadata.runs = true;
+ }
+
+ modulesMetadata.push(moduleMetadata);
+ libraryRelease.require(path.join(pluginDir, jsModule.src), { expose: moduleId });
+ });
+ });
+
+ events.emit('verbose', 'Writing out cordova_plugins.js...');
+
+ // Create a stream and write plugin metadata into it
+ // instead of generating intermediate file on FS
+ var cordova_plugins = new Readable();
+ cordova_plugins.push(
+ 'module.exports.metadata = ' + JSON.stringify(pluginMetadata, null, 4) + ';\n' +
+ 'module.exports = ' + JSON.stringify(modulesMetadata, null, 4) + ';\n', 'utf8');
+ cordova_plugins.push(null);
+
+ var bootstrap = new Readable();
+ bootstrap.push('require(\'cordova/init\');\n', 'utf8');
+ bootstrap.push(null);
+
+ var moduleAliases = modulesMetadata
+ .reduce(function (accum, meta) {
+ accum['./' + meta.name] = meta.id;
+ return accum;
+ }, {});
+
+ libraryRelease
+ .add(cordova_plugins, {file: path.join(wwwDir, 'cordova_plugins.js'), expose: 'cordova/plugin_list'})
+ .add(bootstrap)
+ .transform(aliasify, {aliases: moduleAliases});
+
+ var outReleaseFile = path.join(wwwDir, 'cordova.js');
+ return generateFinalBundle(platform, libraryRelease, outReleaseFile, commitId, platformVersion);
+ });
+};
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/plugman/install.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/install.js b/cordova-lib/src/plugman/install.js
index b99d155..071e851 100644
--- a/cordova-lib/src/plugman/install.js
+++ b/cordova-lib/src/plugman/install.js
@@ -471,7 +471,6 @@ function tryFetchDependency(dep, install, options) {
dep.subdir = '';
return Q(url);
}).fail(function(error){
-//console.log("Failed to resolve url='.': " + error);
return Q(dep.url);
});
@@ -565,35 +564,27 @@ function handleInstall(actions, pluginInfo, platform, project_dir, plugins_dir,
// @tests - important this event is checked spec/install.spec.js
events.emit('verbose', 'Install start for "' + pluginInfo.id + '" on ' + platform + '.');
- var handler = platform_modules.getPlatformProject(platform, project_dir);
- var frameworkFiles = pluginInfo.getFrameworks(platform); // Frameworks are needed later
- var pluginItems = pluginInfo.getFilesAndFrameworks(platform);
-
- // queue up native stuff
- pluginItems.forEach(function(item) {
- actions.push(actions.createAction(handler.getInstaller(item.itemType),
- [item, plugin_dir, pluginInfo.id, options],
- handler.getUninstaller(item.itemType),
- [item, pluginInfo.id, options]));
- });
- // run through the action stack
- return actions.process(platform, project_dir)
- .then(function(err) {
- // queue up the plugin so prepare knows what to do.
- var platformJson = PlatformJson.load(plugins_dir, platform);
- platformJson.addInstalledPluginToPrepareQueue(pluginInfo.id, filtered_variables, options.is_top_level);
- platformJson.save();
- // call prepare after a successful install
- if (options.browserify) {
- return plugman.prepareBrowserify(project_dir, platform, plugins_dir, options.www_dir, options.is_top_level, options.pluginInfoProvider);
- } else {
- return plugman.prepare(project_dir, platform, plugins_dir, options.www_dir, options.is_top_level, options.pluginInfoProvider);
- }
- }).then (function() {
+ options.variables = filtered_variables;
+ // 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.
+ options.usePlatformWww = true;
+
+ return platform_modules.getPlatformApi(platform, project_dir)
+ .addPlugin(pluginInfo, options)
+ .then (function() {
events.emit('verbose', 'Install complete for ' + pluginInfo.id + ' on ' + platform + '.');
+ // Add plugin to installed list. This already done in platform,
+ // but need to be duplicated here to manage dependencies properly.
+ PlatformJson.load(plugins_dir, platform)
+ .addPlugin(pluginInfo.id, filtered_variables, options.is_top_level)
+ .save();
+
+ if (platform == 'android' && semver.gte(options.platformVersion, '4.0.0-dev') &&
+ pluginInfo.getFrameworks('platform').length > 0) {
- if (platform == 'android' && semver.gte(options.platformVersion, '4.0.0-dev') && frameworkFiles.length > 0) {
events.emit('verbose', 'Updating build files since android plugin contained <framework>');
var buildModule;
try {
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/plugman/platforms/common.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/platforms/common.js b/cordova-lib/src/plugman/platforms/common.js
index e3d3bcd..358ceed 100644
--- a/cordova-lib/src/plugman/platforms/common.js
+++ b/cordova-lib/src/plugman/platforms/common.js
@@ -79,7 +79,11 @@ module.exports = common = {
},
// Sometimes we want to remove some java, and prune any unnecessary empty directories
deleteJava:function(project_dir, destFile) {
- var file = path.resolve(project_dir, destFile);
+ common.removeFileAndParents(project_dir, destFile, 'src');
+ },
+ removeFileAndParents:function(baseDir, destFile, stopper) {
+ stopper = stopper || '.';
+ var file = path.resolve(baseDir, destFile);
if (!fs.existsSync(file)) return;
common.removeFileF(file);
@@ -87,7 +91,7 @@ module.exports = common = {
// check if directory is empty
var curDir = path.dirname(file);
- while(curDir !== path.resolve(project_dir, 'src')) {
+ while(curDir !== path.resolve(baseDir, stopper)) {
if(fs.existsSync(curDir) && fs.readdirSync(curDir).length === 0) {
fs.rmdirSync(curDir);
curDir = path.resolve(curDir, '..');
@@ -119,5 +123,27 @@ module.exports = common = {
common.removeFile(www_dir, target);
common.removeFileF(path.resolve(www_dir, 'plugins', plugin_id));
}
+ },
+ 'js-module': {
+ install: function (jsModule, plugin_dir, plugin_id, www_dir) {
+ // Copy the plugin's files into the www directory.
+ var moduleSource = path.resolve(plugin_dir, jsModule.src);
+ var moduleName = plugin_id + '.' + (jsModule.name || path.parse(jsModule.src).name);
+
+ // Read in the file, prepend the cordova.define, and write it back out.
+ var scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM
+ if (moduleSource.match(/.*\.json$/)) {
+ scriptContent = 'module.exports = ' + scriptContent;
+ }
+ scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) { ' + scriptContent + '\n});\n';
+
+ var moduleDestination = path.resolve(www_dir, 'plugins', plugin_id, jsModule.src);
+ shell.mkdir('-p', path.dirname(moduleDestination));
+ fs.writeFileSync(moduleDestination, scriptContent, 'utf-8');
+ },
+ uninstall: function (jsModule, www_dir, plugin_id) {
+ var pluginRelativePath = path.join('plugins', plugin_id, jsModule.src);
+ common.removeFileAndParents(www_dir, pluginRelativePath);
+ }
}
};
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/plugman/plugman.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/plugman.js b/cordova-lib/src/plugman/plugman.js
index 7d952f5..67637ed 100644
--- a/cordova-lib/src/plugman/plugman.js
+++ b/cordova-lib/src/plugman/plugman.js
@@ -65,8 +65,7 @@ var plugman = {
addProperty(plugman, 'install', './install', true);
addProperty(plugman, 'uninstall', './uninstall', true);
addProperty(plugman, 'fetch', './fetch', true);
-addProperty(plugman, 'prepare', './prepare');
-addProperty(plugman, 'prepareBrowserify', './prepare-browserify');
+addProperty(plugman, 'browserify', './browserify');
addProperty(plugman, 'help', './help');
addProperty(plugman, 'config', './config', true);
addProperty(plugman, 'owner', './owner', true);
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/plugman/prepare-browserify.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/prepare-browserify.js b/cordova-lib/src/plugman/prepare-browserify.js
deleted file mode 100644
index 2dfb26a..0000000
--- a/cordova-lib/src/plugman/prepare-browserify.js
+++ /dev/null
@@ -1,214 +0,0 @@
-/**
- 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.
-*/
-
-/* jshint unused:false, expr:true */
-
-var platform_modules = require('../platforms/platforms'),
- path = require('path'),
- aliasify = require('aliasify'),
- config_changes = require('./util/config-changes'),
- common = require('./platforms/common'),
- fs = require('fs'),
- childProcess = require('child_process'),
- shell = require('shelljs'),
- util = require('util'),
- events = require('../events'),
- plugman = require('./plugman'),
- bundle = require('cordova-js/tasks/lib/bundle-browserify'),
- writeLicenseHeader = require('cordova-js/tasks/lib/write-license-header'),
- Q = require('q'),
- computeCommitId = require('cordova-js/tasks/lib/compute-commit-id'),
- Readable = require('stream').Readable;
-
-var PlatformJson = require('./util/PlatformJson');
-var PluginInfoProvider = require('../PluginInfoProvider');
-
-function uninstallQueuedPlugins(platformJson, wwwDir) {
- // Check if there are any plugins queued for uninstallation, and if so, remove any of their plugin web assets loaded in
- // via <js-module> elements
- var plugins_to_uninstall = platformJson.root.prepare_queue.uninstalled;
- if (plugins_to_uninstall && plugins_to_uninstall.length) {
- var plugins_www = path.join(wwwDir, 'plugins');
- if (fs.existsSync(plugins_www)) {
- plugins_to_uninstall.forEach(function(plug) {
- var id = plug.id;
- var plugin_modules = path.join(plugins_www, id);
- if (fs.existsSync(plugin_modules)) {
- events.emit('verbose', 'Removing plugins directory from www "'+plugin_modules+'"');
- shell.rm('-rf', plugin_modules);
- }
- });
- }
- }
-}
-
-function generateFinalBundle(platform, libraryRelease, outReleaseFile, commitId, platformVersion) {
- var deferred = Q.defer();
- var outReleaseFileStream = fs.createWriteStream(outReleaseFile);
- var time = new Date().valueOf();
- var symbolList = null;
-
- writeLicenseHeader(outReleaseFileStream, platform, commitId, platformVersion);
-
- var releaseBundle = libraryRelease.bundle();
-
- releaseBundle.pipe(outReleaseFileStream);
-
- outReleaseFileStream.on('finish', function() {
- var newtime = new Date().valueOf() - time;
- plugman.emit('verbose', 'generated cordova.' + platform + '.js @ ' + commitId + ' in ' + newtime + 'ms');
- deferred.resolve();
- // TODO clean up all the *.browserify files
- });
-
- outReleaseFileStream.on('error', function(err) {
- var newtime = new Date().valueOf() - time;
- events.emit('log', 'error while generating cordova.js');
- deferred.reject();
- });
- return deferred.promise;
-}
-
-function computeCommitIdSync() {
- var deferred = Q.defer();
- computeCommitId(function(cId){
- deferred.resolve(cId);
- });
- return deferred.promise;
-}
-
-function getPlatformVersion(cId, project_dir) {
- var deferred = Q.defer();
- //run version script for each platform to get platformVersion
- var versionPath = path.join(project_dir, '/cordova/version');
- childProcess.exec('"' + versionPath + '"', function(err, stdout, stderr) {
- if (err) {
- events.emit('log', 'Error running platform version script');
- events.emit('log', err);
- deferred.resolve('N/A');
- } else {
- deferred.resolve(stdout.trim());
- }
- });
- return deferred.promise;
-}
-
-// Called on --prepare.
-// Sets up each plugin's Javascript code to be loaded properly.
-// Expects a path to the project (platforms/android in CLI, . in plugman-only),
-// a path to where the plugins are downloaded, the www dir, and the platform ('android', 'ios', etc.).
-module.exports = function handlePrepare(project_dir, platform, plugins_dir, www_dir, is_top_level, pluginInfoProvider) {
- // Process:
- // - Do config munging by calling into config-changes module
- // - List all plugins in plugins_dir
- // - Load and parse their plugin.xml files.
- // - Skip those without support for this platform. (No <platform> tags means JS-only!)
- // - Build a list of all their js-modules, including platform-specific js-modules.
- // - For each js-module (general first, then platform) build up an object storing the path and any clobbers, merges and runs for it.
- // Write this object into www/cordova_plugins.json.
- // This file is not really used. Maybe cordova app harness
- events.emit('verbose', 'Preparing ' + platform + ' browserify project');
- pluginInfoProvider = pluginInfoProvider || new PluginInfoProvider(); // Allow null for backwards-compat.
- var platformJson = PlatformJson.load(plugins_dir, platform);
- var wwwDir = www_dir || platform_modules.getPlatformProject(platform, project_dir).www_dir();
-
- uninstallQueuedPlugins(platformJson, www_dir);
-
- events.emit('verbose', 'Processing configuration changes for plugins.');
- config_changes.process(plugins_dir, project_dir, platform, platformJson, pluginInfoProvider);
-
- if(!is_top_level) {
- return Q();
- }
-
- var commitId;
- return computeCommitIdSync()
- .then(function(cId){
- commitId = cId;
- return getPlatformVersion(commitId, project_dir);
- }).then(function(platformVersion){
- var libraryRelease = bundle(platform, false, commitId, platformVersion);
-
- var pluginMetadata = {};
- var modulesMetadata = [];
-
- var plugins = Object.keys(platformJson.root.installed_plugins).concat(Object.keys(platformJson.root.dependent_plugins));
- events.emit('verbose', 'Iterating over installed plugins:', plugins);
- plugins && plugins.forEach(function(plugin) {
- var pluginDir = path.join(plugins_dir, plugin);
- var pluginInfo = pluginInfoProvider.get(pluginDir);
- // pluginMetadata is a mapping from plugin IDs to versions.
- pluginMetadata[pluginInfo.id] = pluginInfo.version;
-
- // Copy www assets described in <asset> tags.
- pluginInfo.getAssets(platform)
- .forEach(function(asset) {
- common.asset.install(asset, pluginDir, wwwDir);
- });
-
- pluginInfo.getJsModules(platform)
- .forEach(function(jsModule) {
- var moduleName = jsModule.name ? jsModule.name : path.basename(jsModule.src, '.js');
- var moduleId = pluginInfo.id + '.' + moduleName;
- var moduleMetadata = {file: jsModule.src, id: moduleId, name: moduleName};
-
- if (jsModule.clobbers.length > 0) {
- moduleMetadata.clobbers = jsModule.clobbers.map(function(o) { return o.target; });
- }
- if (jsModule.merges.length > 0) {
- moduleMetadata.merges = jsModule.merges.map(function(o) { return o.target; });
- }
- if (jsModule.runs) {
- moduleMetadata.runs = true;
- }
-
- modulesMetadata.push(moduleMetadata);
- libraryRelease.require(path.join(pluginDir, jsModule.src), { expose: moduleId });
- });
- });
-
- events.emit('verbose', 'Writing out cordova_plugins.js...');
-
- // Create a stream and write plugin metadata into it
- // instead of generating intermediate file on FS
- var cordova_plugins = new Readable();
- cordova_plugins.push(
- 'module.exports.metadata = ' + JSON.stringify(pluginMetadata, null, 4) + ';\n' +
- 'module.exports = ' + JSON.stringify(modulesMetadata, null, 4) + ';\n', 'utf8');
- cordova_plugins.push(null);
-
- var bootstrap = new Readable();
- bootstrap.push('require(\'cordova/init\');\n', 'utf8');
- bootstrap.push(null);
-
- var moduleAliases = modulesMetadata
- .reduce(function (accum, meta) {
- accum['./' + meta.name] = meta.id;
- return accum;
- }, {});
-
- libraryRelease
- .add(cordova_plugins, {file: path.join(wwwDir, 'cordova_plugins.js'), expose: 'cordova/plugin_list'})
- .add(bootstrap)
- .transform(aliasify, {aliases: moduleAliases});
-
- var outReleaseFile = path.join(wwwDir, 'cordova.js');
- return generateFinalBundle(platform, libraryRelease, outReleaseFile, commitId, platformVersion);
- });
-};
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/plugman/prepare.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/prepare.js b/cordova-lib/src/plugman/prepare.js
deleted file mode 100644
index c52d92e..0000000
--- a/cordova-lib/src/plugman/prepare.js
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- 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.
-*/
-
-/* jshint expr:true, quotmark:false */
-
-var platform_modules = require('../platforms/platforms'),
- path = require('path'),
- config_changes = require('./util/config-changes'),
- common = require('./platforms/common'),
- fs = require('fs'),
- shell = require('shelljs'),
- Q = require('q'),
- events = require('../events');
-var PlatformJson = require('./util/PlatformJson');
-var PluginInfoProvider = require('../PluginInfoProvider');
-
-// Called on --prepare.
-// Sets up each plugin's Javascript code to be loaded properly.
-// Expects a path to the project (platforms/android in CLI, . in plugman-only),
-// a path to where the plugins are downloaded, the www dir, and the platform ('android', 'ios', etc.).
-module.exports = function handlePrepare(project_dir, platform, plugins_dir, www_dir, is_top_level, pluginInfoProvider) {
- // Process:
- // - Do config munging by calling into config-changes module
- // - List all plugins in plugins_dir
- // - Load and parse their plugin.xml files.
- // - Skip those without support for this platform. (No <platform> tags means JS-only!)
- // - Build a list of all their js-modules, including platform-specific js-modules.
- // - For each js-module (general first, then platform) build up an object storing the path and any clobbers, merges and runs for it.
- // - Write this object into www/cordova_plugins.json.
- // - Cordova.js contains code to load them at runtime from that file.
- events.emit('verbose', 'Preparing ' + platform + ' project');
- pluginInfoProvider = pluginInfoProvider || new PluginInfoProvider(); // Allow null for backwards-compat.
- var platformJson = PlatformJson.load(plugins_dir, platform);
- var wwwDir = www_dir || platform_modules.getPlatformProject(platform, project_dir).www_dir();
-
- // Check if there are any plugins queued for uninstallation, and if so, remove any of their plugin web assets loaded in
- // via <js-module> elements
- var plugins_to_uninstall = platformJson.root.prepare_queue.uninstalled;
- if (plugins_to_uninstall && plugins_to_uninstall.length) {
- var plugins_www = path.join(wwwDir, 'plugins');
- if (fs.existsSync(plugins_www)) {
- plugins_to_uninstall.forEach(function(plug) {
- var id = plug.id;
- var plugin_modules = path.join(plugins_www, id);
- if (fs.existsSync(plugin_modules)) {
- events.emit('verbose', 'Removing plugins directory from www "'+plugin_modules+'"');
- shell.rm('-rf', plugin_modules);
- }
- });
- }
- }
-
- events.emit('verbose', 'Processing configuration changes for plugins.');
- config_changes.process(plugins_dir, project_dir, platform, platformJson, pluginInfoProvider);
-
- // This array holds all the metadata for each module and ends up in cordova_plugins.json
- var plugins = Object.keys(platformJson.root.installed_plugins).concat(Object.keys(platformJson.root.dependent_plugins));
- var moduleObjects = [];
- var pluginMetadata = {};
- events.emit('verbose', 'Iterating over installed plugins:', plugins);
-
- plugins && plugins.forEach(function(plugin) {
- var pluginDir = path.join(plugins_dir, plugin);
- var pluginInfo = pluginInfoProvider.get(pluginDir);
-
- var plugin_id = pluginInfo.id;
- // pluginMetadata is a mapping from plugin IDs to versions.
- pluginMetadata[plugin_id] = pluginInfo.version;
-
- // add the plugins dir to the platform's www.
- var platformPluginsDir = path.join(wwwDir, 'plugins');
- // XXX this should not be here if there are no js-module. It leaves an empty plugins/ directory
- shell.mkdir('-p', platformPluginsDir);
-
- var jsModules = pluginInfo.getJsModules(platform);
- var assets = pluginInfo.getAssets(platform);
-
- // Copy www assets described in <asset> tags.
- assets.forEach(function(asset) {
- common.asset.install(asset, pluginDir, wwwDir);
- });
-
- jsModules.forEach(function(module) {
- // Copy the plugin's files into the www directory.
- // NB: We can't always use path.* functions here, because they will use platform slashes.
- // But the path in the plugin.xml and in the cordova_plugins.js should be always forward slashes.
- var pathParts = module.src.split('/');
-
- var fsDirname = path.join.apply(path, pathParts.slice(0, -1));
- var fsDir = path.join(platformPluginsDir, plugin_id, fsDirname);
- shell.mkdir('-p', fsDir);
-
- // Read in the file, prepend the cordova.define, and write it back out.
- var moduleName = plugin_id + '.';
- if (module.name) {
- moduleName += module.name;
- } else {
- var result = module.src.match(/([^\/]+)\.js/);
- moduleName += result[1];
- }
-
- var fsPath = path.join.apply(path, pathParts);
- var scriptContent = fs.readFileSync(path.join(pluginDir, fsPath), 'utf-8').replace(/^\ufeff/, ''); // Window BOM
- if (fsPath.match(/.*\.json$/)) {
- scriptContent = 'module.exports = ' + scriptContent;
- }
- scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) { ' + scriptContent + '\n});\n';
- fs.writeFileSync(path.join(platformPluginsDir, plugin_id, fsPath), scriptContent, 'utf-8');
-
- // Prepare the object for cordova_plugins.json.
- var obj = {
- file: ['plugins', plugin_id, module.src].join('/'),
- id: moduleName
- };
- if (module.clobbers.length > 0) {
- obj.clobbers = module.clobbers.map(function(o) { return o.target; });
- }
- if (module.merges.length > 0) {
- obj.merges = module.merges.map(function(o) { return o.target; });
- }
- if (module.runs) {
- obj.runs = true;
- }
-
- // Add it to the list of module objects bound for cordova_plugins.json
- moduleObjects.push(obj);
- });
- });
-
- // Write out moduleObjects as JSON wrapped in a cordova module to cordova_plugins.js
- var final_contents = "cordova.define('cordova/plugin_list', function(require, exports, module) {\n";
- final_contents += 'module.exports = ' + JSON.stringify(moduleObjects,null,' ') + ';\n';
- final_contents += 'module.exports.metadata = \n';
- final_contents += '// TOP OF METADATA\n';
- final_contents += JSON.stringify(pluginMetadata, null, ' ') + '\n';
- final_contents += '// BOTTOM OF METADATA\n';
- final_contents += '});'; // Close cordova.define.
-
- events.emit('verbose', 'Writing out cordova_plugins.js...');
- fs.writeFileSync(path.join(wwwDir, 'cordova_plugins.js'), final_contents, 'utf-8');
-
- return Q();
-};
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/plugman/uninstall.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/uninstall.js b/cordova-lib/src/plugman/uninstall.js
index 9fdc2e4..1bc1e2f 100644
--- a/cordova-lib/src/plugman/uninstall.js
+++ b/cordova-lib/src/plugman/uninstall.js
@@ -30,7 +30,6 @@ var path = require('path'),
Q = require('q'),
events = require('../events'),
platform_modules = require('../platforms/platforms'),
- plugman = require('./plugman'),
promiseutil = require('../util/promise-util'),
HooksRunner = require('../hooks/HooksRunner'),
cordovaUtil = require('../cordova/util');
@@ -299,49 +298,23 @@ function runUninstallPlatform(actions, platform, project_dir, plugin_dir, plugin
// Returns a promise.
function handleUninstall(actions, platform, pluginInfo, project_dir, www_dir, plugins_dir, is_top_level, options) {
- var plugin_id = pluginInfo.id;
- var plugin_dir = pluginInfo.dir;
- var handler = platform_modules.getPlatformProject(platform, project_dir);
- www_dir = www_dir || handler.www_dir();
- events.emit('log', 'Uninstalling ' + plugin_id + ' from ' + platform);
-
- var pluginItems = pluginInfo.getFilesAndFrameworks(platform);
- var assets = pluginInfo.getAssets(platform);
- var frameworkFiles = pluginInfo.getFrameworks(platform);
-
- // queue up native stuff
- pluginItems.forEach(function(item) {
- // CB-5238 Don't uninstall non custom frameworks.
- if (item.itemType == 'framework' && !item.custom) return;
- actions.push(actions.createAction(handler.getUninstaller(item.itemType),
- [item, plugin_id, options],
- handler.getInstaller(item.itemType),
- [item, plugin_dir, plugin_id, options]));
- });
-
- // queue up asset uninstallation
- var common = require('./platforms/common');
- assets.forEach(function(asset) {
- actions.push(actions.createAction(common.asset.uninstall, [asset, www_dir, plugin_id], common.asset.install, [asset, plugin_dir, www_dir]));
- });
+ events.emit('log', 'Uninstalling ' + pluginInfo.id + ' from ' + platform);
- // run through the action stack
- return actions.process(platform, project_dir)
+ // Set up platform to uninstall asset files/js modules
+ // from <platform>/platform_www dir instead of <platform>/www.
+ options.usePlatformWww = true;
+ return platform_modules.getPlatformApi(platform, project_dir)
+ .removePlugin(pluginInfo, options)
.then(function() {
- // WIN!
- events.emit('verbose', plugin_id + ' uninstalled from ' + platform + '.');
- // queue up the plugin so prepare can remove the config changes
- var platformJson = PlatformJson.load(plugins_dir, platform);
- platformJson.addUninstalledPluginToPrepareQueue(plugin_id, is_top_level);
- platformJson.save();
- // call prepare after a successful uninstall
- if (options.browserify) {
- return plugman.prepareBrowserify(project_dir, platform, plugins_dir, www_dir, is_top_level, options.pluginInfoProvider);
- } else {
- return plugman.prepare(project_dir, platform, plugins_dir, www_dir, is_top_level, options.pluginInfoProvider);
- }
- }).then(function() {
- if (platform == 'android' && semver.gte(options.platformVersion, '4.0.0-dev') && frameworkFiles.length > 0) {
+ // Remove plugin from installed list. This already done in platform,
+ // but need to be duplicated here to remove plugin entry from project's
+ // plugin list to manage dependencies properly.
+ PlatformJson.load(plugins_dir, platform)
+ .removePlugin(pluginInfo.id, is_top_level)
+ .save();
+
+ if (platform == 'android' && semver.gte(options.platformVersion, '4.0.0-dev') &&
+ pluginInfo.getFrameworks(platform).length > 0) {
events.emit('verbose', 'Updating build files since android plugin contained <framework>');
var buildModule;
try {
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/plugman/util/ConfigFile.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/util/ConfigFile.js b/cordova-lib/src/plugman/util/ConfigFile.js
index c317668..15191ad 100644
--- a/cordova-lib/src/plugman/util/ConfigFile.js
+++ b/cordova-lib/src/plugman/util/ConfigFile.js
@@ -69,7 +69,7 @@ function ConfigFile_load() {
self.data = xml_helpers.parseElementtreeSync(filepath);
} else if (ext == '.pbxproj') {
self.type = 'pbxproj';
- var projectFile = platforms.getPlatformProject('ios', self.project_dir).parseProjectFile(self.project_dir);
+ var projectFile = platforms.getPlatformApi('ios', self.project_dir)._handler.parseProjectFile(self.project_dir);
self.data = projectFile.xcode;
self.cordovaVersion = projectFile.cordovaVersion;
} else {
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/plugman/util/PlatformJson.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/util/PlatformJson.js b/cordova-lib/src/plugman/util/PlatformJson.js
index 1b9f05b..318a5d9 100644
--- a/cordova-lib/src/plugman/util/PlatformJson.js
+++ b/cordova-lib/src/plugman/util/PlatformJson.js
@@ -81,6 +81,26 @@ PlatformJson.prototype.isPluginInstalled = function(pluginId) {
this.isPluginDependent(pluginId);
};
+PlatformJson.prototype.addPlugin = function(pluginId, variables, isTopLevel) {
+ var pluginsList = isTopLevel ?
+ this.root.installed_plugins :
+ this.root.dependent_plugins;
+
+ pluginsList[pluginId] = variables;
+
+ return this;
+};
+
+PlatformJson.prototype.removePlugin = function(pluginId, isTopLevel) {
+ var pluginsList = isTopLevel ?
+ this.root.installed_plugins :
+ this.root.dependent_plugins;
+
+ delete pluginsList[pluginId];
+
+ return this;
+};
+
PlatformJson.prototype.addInstalledPluginToPrepareQueue = function(pluginDirName, vars, is_top_level) {
this.root.prepare_queue.installed.push({'plugin':pluginDirName, 'vars':vars, 'topLevel':is_top_level});
};
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/plugman/util/action-stack.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/util/action-stack.js b/cordova-lib/src/plugman/util/action-stack.js
index c8bd21b..c1c2a4e 100644
--- a/cordova-lib/src/plugman/util/action-stack.js
+++ b/cordova-lib/src/plugman/util/action-stack.js
@@ -19,8 +19,7 @@
/* jshint quotmark:false */
-var platforms = require("../../platforms/platforms"),
- events = require('../../events'),
+var events = require('../../events'),
Q = require('q');
function ActionStack() {
@@ -47,22 +46,11 @@ ActionStack.prototype = {
// Returns a promise.
process:function(platform, project_dir) {
events.emit('verbose', 'Beginning processing of action stack for ' + platform + ' project...');
- var project_files;
-
- // parse platform-specific project files once
- var platformProject = platforms.getPlatformProject(platform, project_dir);
- if (platformProject.parseProjectFile) {
- events.emit('verbose', 'Parsing ' + platform + ' project files...');
- project_files = platformProject.parseProjectFile(project_dir);
- }
while (this.stack.length) {
var action = this.stack.shift();
var handler = action.handler.run;
var action_params = action.handler.params;
- if (project_files) {
- action_params.push(project_files);
- }
try {
handler.apply(null, action_params);
@@ -76,10 +64,6 @@ ActionStack.prototype = {
var revert = undo.reverter.run;
var revert_params = undo.reverter.params;
- if (project_files) {
- revert_params.push(project_files);
- }
-
try {
revert.apply(null, revert_params);
} catch(err) {
@@ -94,10 +78,6 @@ ActionStack.prototype = {
}
events.emit('verbose', 'Action stack processing complete.');
- if (project_files) {
- events.emit('verbose', 'Writing out ' + platform + ' project files...');
- project_files.write();
- }
return Q();
}
};
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/plugman/util/config-changes.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/util/config-changes.js b/cordova-lib/src/plugman/util/config-changes.js
index 63c3ec3..ff23e2a 100644
--- a/cordova-lib/src/plugman/util/config-changes.js
+++ b/cordova-lib/src/plugman/util/config-changes.js
@@ -54,8 +54,8 @@ var keep_these_frameworks = [
exports.PlatformMunger = PlatformMunger;
exports.process = function(plugins_dir, project_dir, platform, platformJson, pluginInfoProvider) {
- var munger = new PlatformMunger(platform, project_dir, plugins_dir, platformJson, pluginInfoProvider);
- munger.process();
+ var munger = new PlatformMunger(platform, project_dir, platformJson, pluginInfoProvider);
+ munger.process(plugins_dir);
munger.save_all();
};
@@ -65,12 +65,10 @@ exports.process = function(plugins_dir, project_dir, platform, platformJson, plu
* Can deal with config file of a single project.
* Parsed config files are cached in a ConfigKeeper object.
******************************************************************************/
-function PlatformMunger(platform, project_dir, plugins_dir, platformJson, pluginInfoProvider) {
+function PlatformMunger(platform, project_dir, platformJson, pluginInfoProvider) {
checkPlatform(platform);
this.platform = platform;
this.project_dir = project_dir;
- this.plugins_dir = plugins_dir;
- this.platform_handler = platforms.getPlatformProject(platform, project_dir);
this.config_keeper = new ConfigKeeper(project_dir);
this.platformJson = platformJson;
this.pluginInfoProvider = pluginInfoProvider;
@@ -130,14 +128,15 @@ function PlatformMunger_apply_file_munge(file, munge, remove) {
PlatformMunger.prototype.remove_plugin_changes = remove_plugin_changes;
-function remove_plugin_changes(plugin_name, plugin_id, is_top_level) {
+function remove_plugin_changes(pluginInfo, is_top_level) {
var self = this;
var platform_config = self.platformJson.root;
- var plugin_dir = path.join(self.plugins_dir, plugin_name);
- var plugin_vars = (is_top_level ? platform_config.installed_plugins[plugin_id] : platform_config.dependent_plugins[plugin_id]);
+ var plugin_vars = is_top_level ?
+ platform_config.installed_plugins[pluginInfo.id] :
+ platform_config.dependent_plugins[pluginInfo.id];
// get config munge, aka how did this plugin change various config files
- var config_munge = self.generate_plugin_config_munge(plugin_dir, plugin_vars);
+ var config_munge = self.generate_plugin_config_munge(pluginInfo, plugin_vars);
// global munge looks at all plugins' changes to config files
var global_munge = platform_config.config_munge;
var munge = mungeutil.decrement_munge(global_munge, config_munge);
@@ -147,7 +146,7 @@ function remove_plugin_changes(plugin_name, plugin_id, is_top_level) {
// TODO: remove this check and <plugins-plist> sections in spec/plugins/../plugin.xml files.
events.emit(
'warn',
- 'WARNING: Plugin "' + plugin_id + '" uses <plugins-plist> element(s), ' +
+ 'WARNING: Plugin "' + pluginInfo.id + '" uses <plugins-plist> element(s), ' +
'which are no longer supported. Support has been removed as of Cordova 3.4.'
);
continue;
@@ -168,22 +167,18 @@ function remove_plugin_changes(plugin_name, plugin_id, is_top_level) {
}
// Remove from installed_plugins
- if (is_top_level) {
- delete platform_config.installed_plugins[plugin_id];
- } else {
- delete platform_config.dependent_plugins[plugin_id];
- }
+ self.platformJson.removePlugin(pluginInfo.id, is_top_level);
+ return self;
}
PlatformMunger.prototype.add_plugin_changes = add_plugin_changes;
-function add_plugin_changes(plugin_id, plugin_vars, is_top_level, should_increment) {
+function add_plugin_changes(pluginInfo, plugin_vars, is_top_level, should_increment) {
var self = this;
var platform_config = self.platformJson.root;
- var plugin_dir = path.join(self.plugins_dir, plugin_id);
// get config munge, aka how should this plugin change various config files
- var config_munge = self.generate_plugin_config_munge(plugin_dir, plugin_vars);
+ var config_munge = self.generate_plugin_config_munge(pluginInfo, plugin_vars);
// global munge looks at all plugins' changes to config files
// TODO: The should_increment param is only used by cordova-cli and is going away soon.
@@ -203,7 +198,7 @@ function add_plugin_changes(plugin_id, plugin_vars, is_top_level, should_increme
if (file == 'plugins-plist' && self.platform == 'ios') {
events.emit(
'warn',
- 'WARNING: Plugin "' + plugin_id + '" uses <plugins-plist> element(s), ' +
+ 'WARNING: Plugin "' + pluginInfo.id + '" uses <plugins-plist> element(s), ' +
'which are no longer supported. Support has been removed as of Cordova 3.4.'
);
continue;
@@ -222,12 +217,9 @@ function add_plugin_changes(plugin_id, plugin_vars, is_top_level, should_increme
self.apply_file_munge(file, munge.files[file]);
}
- // Move to installed_plugins if it is a top-level plugin
- if (is_top_level) {
- platform_config.installed_plugins[plugin_id] = plugin_vars || {};
- } else {
- platform_config.dependent_plugins[plugin_id] = plugin_vars || {};
- }
+ // Move to installed/dependent_plugins
+ self.platformJson.addPlugin(pluginInfo.id, plugin_vars || {}, is_top_level);
+ return self;
}
@@ -253,24 +245,19 @@ function reapply_global_munge () {
self.apply_file_munge(file, global_munge.files[file]);
}
+
+ return self;
}
// generate_plugin_config_munge
// Generate the munge object from plugin.xml + vars
PlatformMunger.prototype.generate_plugin_config_munge = generate_plugin_config_munge;
-function generate_plugin_config_munge(plugin_dir, vars) {
+function generate_plugin_config_munge(pluginInfo, vars) {
var self = this;
vars = vars || {};
- // Add PACKAGE_NAME variable into vars
- if (!vars['PACKAGE_NAME']) {
- vars['PACKAGE_NAME'] = self.platform_handler.package_name(self.project_dir);
- }
-
var munge = { files: {} };
- var pluginInfo = self.pluginInfoProvider.get(plugin_dir);
-
var changes = pluginInfo.getConfigFiles(self.platform);
// note down pbxproj framework munges in special section of munge obj
@@ -283,10 +270,14 @@ function generate_plugin_config_munge(plugin_dir, vars) {
}
});
}
-
+
// Demux 'package.appxmanifest' into relevant platform-specific appx manifests.
// Only spend the cycles if there are version-specific plugin settings
- if (self.platform === 'windows' && changes.some(function(change) { return ((typeof change.versions !== 'undefined') || (typeof change.deviceTarget !== 'undefined')); }))
+ if (self.platform === 'windows' &&
+ changes.some(function(change) {
+ return ((typeof change.versions !== 'undefined') ||
+ (typeof change.deviceTarget !== 'undefined'));
+ }))
{
var manifests = {
'windows': {
@@ -334,7 +325,7 @@ function generate_plugin_config_munge(plugin_dir, vars) {
// at this point, 'change' targets package.appxmanifest and has a version attribute
knownWindowsVersionsForTargetDeviceSet.forEach(function(winver) {
- // This is a local function that creates the new replacement representing the
+ // This is a local function that creates the new replacement representing the
// mutation. Used to save code further down.
var createReplacement = function(manifestFile, originalChange) {
var replacement = {
@@ -389,18 +380,20 @@ function generate_plugin_config_munge(plugin_dir, vars) {
// Go over the prepare queue and apply the config munges for each plugin
// that has been (un)installed.
PlatformMunger.prototype.process = PlatformMunger_process;
-function PlatformMunger_process() {
+function PlatformMunger_process(plugins_dir) {
var self = this;
var platform_config = self.platformJson.root;
// Uninstallation first
platform_config.prepare_queue.uninstalled.forEach(function(u) {
- self.remove_plugin_changes(u.plugin, u.id, u.topLevel);
+ var pluginInfo = self.pluginInfoProvider.get(path.join(plugins_dir, u.plugin));
+ self.remove_plugin_changes(pluginInfo, u.topLevel);
});
// Now handle installation
platform_config.prepare_queue.installed.forEach(function(u) {
- self.add_plugin_changes(u.plugin, u.vars, u.topLevel, true);
+ var pluginInfo = self.pluginInfoProvider.get(path.join(plugins_dir, u.plugin));
+ self.add_plugin_changes(pluginInfo, u.vars, u.topLevel, true);
});
// Empty out installed/ uninstalled queues.
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org
[5/5] cordova-lib git commit: CB-9597 Initial Implementation of
PlatformApiPoly
Posted by an...@apache.org.
CB-9597 Initial Implementation of PlatformApiPoly
This implements PlatformApiPoly class according to PlatformApi spec, which allows to:
* create/update platform
* execute platform's actions (build/run/add/update)
* do a prepare (needed for CLI workflow only)
* install/uninstall plugins
Other noticeable changes:
* removes `getPlatformProject` and PlatformProject method/class in favor of PlatformApiPoly/getPlatformApi
* make assets and js-modules installing/uninstalling through ActionStack
* refactor configChanges to not require plugins_dir in constructor
* moves mergeXml helper to xml-helpers
This should be used along with cordova-cli/platformApi branch
Project: http://git-wip-us.apache.org/repos/asf/cordova-lib/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-lib/commit/07271a5c
Tree: http://git-wip-us.apache.org/repos/asf/cordova-lib/tree/07271a5c
Diff: http://git-wip-us.apache.org/repos/asf/cordova-lib/diff/07271a5c
Branch: refs/heads/master
Commit: 07271a5c6162c0b2bee55e1ea23f91ebdfbbb34c
Parents: b0c1965
Author: Vladimir Kotikov <v-...@microsoft.com>
Authored: Thu Jul 9 16:55:31 2015 +0300
Committer: Vladimir Kotikov <v-...@microsoft.com>
Committed: Wed Sep 2 14:24:03 2015 +0300
----------------------------------------------------------------------
cordova-lib/spec-cordova/cofdova-lib.spec.js | 23 -
cordova-lib/spec-cordova/compile.spec.js | 36 +-
cordova-lib/spec-cordova/cordova-lib.spec.js | 23 +
cordova-lib/spec-cordova/emulate.spec.js | 48 +-
.../platforms/android/AndroidManifest.xml | 14 +
.../platformApi/platforms/android/android.json | 11 +
.../platforms/android/res/xml/config.xml | 17 +
.../platforms/windows/cordova/Api.js | 3 +
.../metadata/android_parser.spec.js | 12 +-
.../metadata/blackberry_parser.spec.js | 12 +-
.../metadata/browser_parser.spec.js | 10 +-
.../metadata/firefoxos_parser.spec.js | 10 +-
.../spec-cordova/metadata/ios_parser.spec.js | 12 +-
.../spec-cordova/metadata/webos_parser.spec.js | 6 +-
.../metadata/windows8_parser.spec.js | 12 +-
.../spec-cordova/metadata/wp8_parser.spec.js | 12 +-
.../platforms/PlatformApiPoly.spec.js | 315 +++++++++
.../spec-cordova/platforms/platforms.spec.js | 72 ++
cordova-lib/spec-cordova/prepare.spec.js | 159 +----
cordova-lib/spec-cordova/run.spec.js | 26 +-
cordova-lib/spec-cordova/save.spec.js | 31 +-
cordova-lib/spec-cordova/xml-helpers.spec.js | 132 ++++
.../spec-plugman/install-browserify.spec.js | 519 --------------
cordova-lib/spec-plugman/install.spec.js | 224 +++---
cordova-lib/spec-plugman/prepare.spec.js | 73 --
.../spec-plugman/projects/wp8/config.xml | 12 +
.../spec-plugman/uninstall-browserify.spec.js | 315 ---------
cordova-lib/spec-plugman/uninstall.spec.js | 117 ++-
.../spec-plugman/util/action-stack.spec.js | 14 +-
.../spec-plugman/util/config-changes.spec.js | 96 ++-
cordova-lib/src/PluginInfo.js | 7 +-
cordova-lib/src/cordova/clean.js | 20 +-
cordova-lib/src/cordova/compile.js | 27 +-
cordova-lib/src/cordova/emulate.js | 18 +-
cordova-lib/src/cordova/platform.js | 161 ++---
cordova-lib/src/cordova/plugin.js | 107 ++-
cordova-lib/src/cordova/prepare.js | 205 +-----
cordova-lib/src/cordova/requirements.js | 42 +-
cordova-lib/src/cordova/run.js | 17 +-
cordova-lib/src/cordova/serve.js | 19 +-
cordova-lib/src/cordova/targets.js | 7 +-
cordova-lib/src/cordova/util.js | 9 +-
cordova-lib/src/platforms/PlatformApiPoly.js | 706 +++++++++++++++++++
cordova-lib/src/platforms/platforms.js | 107 +--
cordova-lib/src/plugman/browserify.js | 181 +++++
cordova-lib/src/plugman/install.js | 45 +-
cordova-lib/src/plugman/platforms/common.js | 30 +-
cordova-lib/src/plugman/plugman.js | 3 +-
cordova-lib/src/plugman/prepare-browserify.js | 214 ------
cordova-lib/src/plugman/prepare.js | 159 -----
cordova-lib/src/plugman/uninstall.js | 57 +-
cordova-lib/src/plugman/util/ConfigFile.js | 2 +-
cordova-lib/src/plugman/util/PlatformJson.js | 20 +
cordova-lib/src/plugman/util/action-stack.js | 22 +-
cordova-lib/src/plugman/util/config-changes.js | 71 +-
cordova-lib/src/util/xml-helpers.js | 72 ++
56 files changed, 2268 insertions(+), 2426 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/cofdova-lib.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/cofdova-lib.spec.js b/cordova-lib/spec-cordova/cofdova-lib.spec.js
deleted file mode 100644
index 7f734b4..0000000
--- a/cordova-lib/spec-cordova/cofdova-lib.spec.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- 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.
-*/
-
-/* jshint unused:false */
-
-// Verify that cordova-lib.js can be loaded
-var cordovaLib = require('../cordova-lib');
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/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 ea69743..67a8968 100644
--- a/cordova-lib/spec-cordova/compile.spec.js
+++ b/cordova-lib/spec-cordova/compile.spec.js
@@ -18,9 +18,7 @@
*/
var cordova = require('../src/cordova/cordova'),
platforms = require('../src/platforms/platforms'),
- path = require('path'),
HooksRunner = require('../src/hooks/HooksRunner'),
- superspawn = require('../src/cordova/superspawn'),
util = require('../src/cordova/util'),
Q = require('q');
@@ -28,7 +26,7 @@ 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;
+ var is_cordova, list_platforms, fire, result, cd_project_root, fail, platformApi, getPlatformApi;
var project_dir = '/some/path';
function wrapper(f, post) {
@@ -43,7 +41,9 @@ describe('compile command', function() {
cd_project_root = spyOn(util, 'cdProjectRoot').andReturn(project_dir);
list_platforms = spyOn(util, 'listPlatforms').andReturn(supported_platforms);
fire = spyOn(HooksRunner.prototype, 'fire').andReturn(Q());
- spyOn(superspawn, 'spawn').andCallFake(function() { return Q(); });
+ platformApi = { build: jasmine.createSpy('build').andReturn(Q()) };
+ getPlatformApi = spyOn(platforms, 'getPlatformApi').andReturn(platformApi);
+ 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() {
@@ -63,17 +63,21 @@ describe('compile command', function() {
describe('success', function() {
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() {
- 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();
- });
+ expect(getPlatformApi).toHaveBeenCalledWith('android');
+ expect(getPlatformApi).toHaveBeenCalledWith('ios');
+ expect(platformApi.build).toHaveBeenCalled();
+ })
+ .fail(fail)
+ .fin(done);
});
it('should pass down optional parameters', function (done) {
- cordova.raw.compile({platforms:['blackberry10'], options:['--release']}).then(function () {
- expect(superspawn.spawn).toHaveBeenCalledWith(path.join(project_dir, 'platforms', 'blackberry10', 'cordova', 'build'), ['--release'], jasmine.any(Object));
- done();
- });
+ cordova.raw.compile({platforms:['blackberry10'], options:{release: true}}).then(function () {
+ expect(getPlatformApi).toHaveBeenCalledWith('blackberry10');
+ expect(platformApi.build).toHaveBeenCalledWith({release: true});
+ })
+ .fail(fail)
+ .fin(done);
});
});
@@ -83,13 +87,17 @@ describe('compile command', function() {
cordova.raw.compile(['android', 'ios']).then(function() {
expect(fire).toHaveBeenCalledWith('before_compile', {verbose: false, platforms:['android', 'ios'], options: []});
done();
- });
+ })
+ .fail(fail)
+ .fin(done);
});
it('should fire after hooks through the hooker module', function(done) {
cordova.raw.compile('android').then(function() {
expect(fire).toHaveBeenCalledWith('after_compile', {verbose: false, platforms:['android'], options: []});
done();
- });
+ })
+ .fail(fail)
+ .fin(done);
});
});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/cordova-lib.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/cordova-lib.spec.js b/cordova-lib/spec-cordova/cordova-lib.spec.js
new file mode 100644
index 0000000..7f734b4
--- /dev/null
+++ b/cordova-lib/spec-cordova/cordova-lib.spec.js
@@ -0,0 +1,23 @@
+/**
+ 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.
+*/
+
+/* jshint unused:false */
+
+// Verify that cordova-lib.js can be loaded
+var cordovaLib = require('../cordova-lib');
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/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 9561447..e38715f 100644
--- a/cordova-lib/spec-cordova/emulate.spec.js
+++ b/cordova-lib/spec-cordova/emulate.spec.js
@@ -18,8 +18,6 @@
*/
var cordova = require('../src/cordova/cordova'),
platforms = require('../src/platforms/platforms'),
- superspawn = require('../src/cordova/superspawn'),
- path = require('path'),
HooksRunner = require('../src/hooks/HooksRunner'),
Q = require('q'),
util = require('../src/cordova/util');
@@ -27,9 +25,9 @@ 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;
+ var is_cordova, cd_project_root, list_platforms, fire, result, fail;
var project_dir = '/some/path';
- var prepare_spy;
+ var prepare_spy, platformApi, getPlatformApi;
function wrapper(f, post) {
runs(function() {
@@ -45,7 +43,9 @@ describe('emulate command', function() {
list_platforms = spyOn(util, 'listPlatforms').andReturn(supported_platforms);
fire = spyOn(HooksRunner.prototype, 'fire').andReturn(Q());
prepare_spy = spyOn(cordova.raw, 'prepare').andReturn(Q());
- spyOn(superspawn, 'spawn').andCallFake(Q);
+ fail = function (err) { expect(err.stack).not.toBeDefined(); };
+ platformApi = { run: jasmine.createSpy('run').andReturn(Q()) };
+ 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() {
@@ -66,19 +66,21 @@ describe('emulate command', function() {
it('should run inside a Cordova-based project with at least one added platform and call prepare and shell out to the emulate script', function(done) {
cordova.raw.emulate(['android','ios']).then(function(err) {
expect(prepare_spy).toHaveBeenCalledWith(['android', 'ios']);
- expect(superspawn.spawn).toHaveBeenCalledWith(path.join(project_dir, 'platforms', 'android', 'cordova', 'run'), ['--emulator'], jasmine.any(Object));
- expect(superspawn.spawn).toHaveBeenCalledWith(path.join(project_dir, 'platforms', 'ios', 'cordova', 'run'), ['--emulator'], jasmine.any(Object));
-
- done();
- });
+ expect(getPlatformApi).toHaveBeenCalledWith('android');
+ expect(getPlatformApi).toHaveBeenCalledWith('ios');
+ expect(platformApi.run).toHaveBeenCalled();
+ })
+ .fail(fail)
+ .fin(done);
});
it('should pass down options', function(done) {
- cordova.raw.emulate({platforms: ['ios'], options:['--optionTastic']}).then(function(err) {
+ cordova.raw.emulate({platforms: ['ios'], options: {optionTastic: true }}).then(function(err) {
expect(prepare_spy).toHaveBeenCalledWith(['ios']);
- expect(superspawn.spawn).toHaveBeenCalledWith(path.join(project_dir, 'platforms', 'ios', 'cordova', 'run'), ['--emulator', '--optionTastic'], jasmine.any(Object));
-
- done();
- });
+ expect(getPlatformApi).toHaveBeenCalledWith('ios');
+ expect(platformApi.run).toHaveBeenCalledWith({ device: false, emulator: true, optionTastic: true });
+ })
+ .fail(fail)
+ .fin(done);
});
});
@@ -86,15 +88,19 @@ describe('emulate command', function() {
describe('when platforms are added', function() {
it('should fire before hooks through the hooker module', function(done) {
cordova.raw.emulate(['android', 'ios']).then(function() {
- expect(fire).toHaveBeenCalledWith('before_emulate', {verbose: false, platforms:['android', 'ios'], options: []});
- done();
- });
+ expect(fire).toHaveBeenCalledWith('before_emulate',
+ jasmine.objectContaining({verbose: false, platforms:['android', 'ios'], options: jasmine.any(Object)}));
+ })
+ .fail(fail)
+ .fin(done);
});
it('should fire after hooks through the hooker module', function(done) {
cordova.raw.emulate('android').then(function() {
- expect(fire).toHaveBeenCalledWith('after_emulate', {verbose: false, platforms:['android'], options: []});
- done();
- });
+ expect(fire).toHaveBeenCalledWith('after_emulate',
+ jasmine.objectContaining({verbose: false, platforms:['android'], options: jasmine.any(Object)}));
+ })
+ .fail(fail)
+ .fin(done);
});
});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/android/AndroidManifest.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/android/AndroidManifest.xml b/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/android/AndroidManifest.xml
new file mode 100644
index 0000000..be3f245
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/android/AndroidManifest.xml
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='utf-8'?>
+<manifest android:hardwareAccelerated="true" android:versionCode="1" android:versionName="0.0.1" android:windowSoftInputMode="adjustPan" package="org.testing" xmlns:android="http://schemas.android.com/apk/res/android">
+ <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <application android:debuggable="true" android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="@string/app_name">
+ <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/app_name" android:name="TestBase" android:theme="@android:style/Theme.Black.NoTitleBar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+ <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" />
+</manifest>
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/android/android.json
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/android/android.json b/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/android/android.json
new file mode 100644
index 0000000..07c3697
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/android/android.json
@@ -0,0 +1,11 @@
+{
+ "prepare_queue": {
+ "installed": [],
+ "uninstalled": []
+ },
+ "config_munge": {
+ "files": {}
+ },
+ "installed_plugins": {},
+ "dependent_plugins": {}
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/android/res/xml/config.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/android/res/xml/config.xml b/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/android/res/xml/config.xml
new file mode 100644
index 0000000..645eeb5
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/android/res/xml/config.xml
@@ -0,0 +1,17 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+ <description>
+ A sample Apache Cordova application that responds to the deviceready event.
+ </description>
+ <name>Hello Cordova</name>
+ <description>
+ A sample Apache Cordova application that responds to the deviceready event.
+ </description>
+ <author email="dev@cordova.apache.org" href="http://cordova.io">
+ Apache Cordova Team
+ </author>
+ <content src="index.html" />
+ <access origin="*" />
+ <preference name="fullscreen" value="true" />
+ <preference name="webviewbounce" value="true" />
+</widget>
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/windows/cordova/Api.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/windows/cordova/Api.js b/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/windows/cordova/Api.js
new file mode 100644
index 0000000..bb56cda
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projects/platformApi/platforms/windows/cordova/Api.js
@@ -0,0 +1,3 @@
+module.exports = function PlatformApi (argument) {
+ this.platform = 'windows';
+};
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/metadata/android_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/android_parser.spec.js b/cordova-lib/spec-cordova/metadata/android_parser.spec.js
index fd29806..1f56628 100644
--- a/cordova-lib/spec-cordova/metadata/android_parser.spec.js
+++ b/cordova-lib/spec-cordova/metadata/android_parser.spec.js
@@ -19,7 +19,7 @@
/* jshint boss:true */
-var platforms = require('../../src/platforms/platforms'),
+var androidParser = require('../../src/cordova/metadata/android_parser'),
util = require('../../src/cordova/util'),
path = require('path'),
shell = require('shelljs'),
@@ -65,12 +65,12 @@ describe('android project parser', function() {
it('should throw if provided directory does not contain an AndroidManifest.xml', function() {
exists.andReturn(false);
expect(function() {
- new platforms.android.parser(android_proj);
+ new androidParser(android_proj);
}).toThrow();
});
it('should create an instance with path, strings, manifest and android_config properties', function() {
expect(function() {
- var p = new platforms.android.parser(android_proj);
+ var p = new androidParser(android_proj);
expect(p.path).toEqual(android_proj);
expect(p.strings).toEqual(path.join(android_proj, 'res', 'values', 'strings.xml'));
expect(p.manifest).toEqual(path.join(android_proj, 'AndroidManifest.xml'));
@@ -78,11 +78,11 @@ describe('android project parser', function() {
}).not.toThrow();
});
it('should be an instance of Parser', function() {
- expect(new platforms.android.parser(android_proj) instanceof Parser).toBe(true);
+ expect(new androidParser(android_proj) instanceof Parser).toBe(true);
});
it('should call super with the correct arguments', function() {
var call = spyOn(Parser, 'call');
- var p = new platforms.android.parser(android_proj);
+ var p = new androidParser(android_proj);
expect(call).toHaveBeenCalledWith(p, 'android', android_proj);
});
});
@@ -94,7 +94,7 @@ describe('android project parser', function() {
beforeEach(function() {
stringsRoot = null;
manifestRoot = null;
- p = new platforms.android.parser(android_proj);
+ p = new androidParser(android_proj);
cp = spyOn(shell, 'cp');
rm = spyOn(shell, 'rm');
is_cordova = spyOn(util, 'isCordova').andReturn(android_proj);
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/metadata/blackberry_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/blackberry_parser.spec.js b/cordova-lib/spec-cordova/metadata/blackberry_parser.spec.js
index aea0a49..7df3e24 100644
--- a/cordova-lib/spec-cordova/metadata/blackberry_parser.spec.js
+++ b/cordova-lib/spec-cordova/metadata/blackberry_parser.spec.js
@@ -17,7 +17,7 @@
under the License.
*/
-var platforms = require('../../src/platforms/platforms'),
+var blackberryParser = require('../../src/cordova/metadata/blackberry10_parser'),
util = require('../../src/cordova/util'),
path = require('path'),
shell = require('shelljs'),
@@ -76,22 +76,22 @@ describe('blackberry10 project parser', function() {
it('should throw an exception with a path that is not a native blackberry project', function() {
exists.andReturn(false);
expect(function() {
- new platforms.blackberry10.parser(proj);
+ new blackberryParser(proj);
}).toThrow();
});
it('should accept a proper native blackberry project path as construction parameter', function() {
var project;
expect(function() {
- project = new platforms.blackberry10.parser(proj);
+ project = new blackberryParser(proj);
}).not.toThrow();
expect(project).toBeDefined();
});
it('should be an instance of Parser', function() {
- expect(new platforms.blackberry10.parser(proj) instanceof Parser).toBe(true);
+ expect(new blackberryParser(proj) instanceof Parser).toBe(true);
});
it('should call super with the correct arguments', function() {
var call = spyOn(Parser, 'call');
- var p = new platforms.blackberry10.parser(proj);
+ var p = new blackberryParser(proj);
expect(call).toHaveBeenCalledWith(p, 'blackberry10', proj);
});
});
@@ -100,7 +100,7 @@ describe('blackberry10 project parser', function() {
var p, cp, rm, mkdir, is_cordova, write, read;
var bb_proj = path.join(proj, 'platforms', 'blackberry10');
beforeEach(function() {
- p = new platforms.blackberry10.parser(bb_proj);
+ p = new blackberryParser(bb_proj);
cp = spyOn(shell, 'cp');
rm = spyOn(shell, 'rm');
mkdir = spyOn(shell, 'mkdir');
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/metadata/browser_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/browser_parser.spec.js b/cordova-lib/spec-cordova/metadata/browser_parser.spec.js
index 2677103..a44d7d3 100644
--- a/cordova-lib/spec-cordova/metadata/browser_parser.spec.js
+++ b/cordova-lib/spec-cordova/metadata/browser_parser.spec.js
@@ -17,7 +17,7 @@
under the License.
*/
-var platforms = require('../../src/platforms/platforms'),
+var browserParser = require('../../src/cordova/metadata/browser_parser'),
util = require('../../src/cordova/util'),
path = require('path'),
shell = require('shelljs'),
@@ -35,16 +35,16 @@ describe('browser project parser', function() {
describe('constructions', function() {
it('should create an instance with a path', function() {
expect(function() {
- var p = new platforms.browser.parser(proj);
+ var p = new browserParser(proj);
expect(p.path).toEqual(proj);
}).not.toThrow();
});
it('should be an instance of Parser', function() {
- expect(new platforms.browser.parser(proj) instanceof Parser).toBe(true);
+ expect(new browserParser(proj) instanceof Parser).toBe(true);
});
it('should call super with the correct arguments', function() {
var call = spyOn(Parser, 'call');
- var p = new platforms.browser.parser(proj);
+ var p = new browserParser(proj);
expect(call).toHaveBeenCalledWith(p, 'browser', proj);
});
});
@@ -54,7 +54,7 @@ describe('browser project parser', function() {
var browser_proj = path.join(proj, 'platforms', 'browser');
beforeEach(function() {
- p = new platforms.browser.parser(browser_proj);
+ p = new browserParser(browser_proj);
cp = spyOn(shell, 'cp');
rm = spyOn(shell, 'rm');
mkdir = spyOn(shell, 'mkdir');
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/metadata/firefoxos_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/firefoxos_parser.spec.js b/cordova-lib/spec-cordova/metadata/firefoxos_parser.spec.js
index c918d16..e4a7eaa 100644
--- a/cordova-lib/spec-cordova/metadata/firefoxos_parser.spec.js
+++ b/cordova-lib/spec-cordova/metadata/firefoxos_parser.spec.js
@@ -19,7 +19,7 @@
/* jshint boss:true */
-var platforms = require('../../src/platforms/platforms'),
+var firefoxosParser = require('../../src/cordova/metadata/firefoxos_parser'),
util = require('../../src/cordova/util'),
path = require('path'),
shell = require('shelljs'),
@@ -53,18 +53,18 @@ describe('firefoxos project parser', function() {
describe('constructions', function() {
it('should create an instance with a path', function() {
expect(function() {
- var p = new platforms.firefoxos.parser(proj);
+ var p = new firefoxosParser(proj);
expect(p.path).toEqual(proj);
expect(p.config_path).toEqual(path.join(proj, 'config.xml'));
expect(p.manifest_path).toEqual(path.join(p.www_dir(), 'manifest.webapp'));
}).not.toThrow();
});
it('should be an instance of Parser', function() {
- expect(new platforms.firefoxos.parser(proj) instanceof Parser).toBe(true);
+ expect(new firefoxosParser(proj) instanceof Parser).toBe(true);
});
it('should call super with the correct arguments', function() {
var call = spyOn(Parser, 'call');
- var p = new platforms.firefoxos.parser(proj);
+ var p = new firefoxosParser(proj);
expect(call).toHaveBeenCalledWith(p, 'firefoxos', proj);
});
});
@@ -74,7 +74,7 @@ describe('firefoxos project parser', function() {
var ff_proj = path.join(proj, 'platforms', 'firefoxos');
var manifestJson = null;
beforeEach(function() {
- p = new platforms.firefoxos.parser(ff_proj);
+ p = new firefoxosParser(ff_proj);
cp = spyOn(shell, 'cp');
rm = spyOn(shell, 'rm');
is_cordova = spyOn(util, 'isCordova').andReturn(proj);
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/metadata/ios_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/ios_parser.spec.js b/cordova-lib/spec-cordova/metadata/ios_parser.spec.js
index 6ab42da..d7ae6f0 100644
--- a/cordova-lib/spec-cordova/metadata/ios_parser.spec.js
+++ b/cordova-lib/spec-cordova/metadata/ios_parser.spec.js
@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
-var platforms = require('../../src/platforms/platforms'),
+var iosParser = require('../../src/cordova/metadata/ios_parser'),
util = require('../../src/cordova/util'),
path = require('path'),
shell = require('shelljs'),
@@ -55,23 +55,23 @@ describe('ios project parser', function () {
it('should throw if provided directory does not contain an xcodeproj file', function() {
readdir.andReturn(['noxcodehere']);
expect(function() {
- new platforms.ios.parser(proj);
+ new iosParser(proj);
}).toThrow();
});
it('should create an instance with path, pbxproj, xcodeproj, originalName and cordovaproj properties', function() {
expect(function() {
- var p = new platforms.ios.parser(proj);
+ var p = new iosParser(proj);
expect(p.path).toEqual(proj);
expect(p.pbxproj).toEqual(path.join(proj, 'test.xcodeproj', 'project.pbxproj'));
expect(p.xcodeproj).toEqual(path.join(proj, 'test.xcodeproj'));
}).not.toThrow();
});
it('should be an instance of Parser', function() {
- expect(new platforms.ios.parser(proj) instanceof Parser).toBe(true);
+ expect(new iosParser(proj) instanceof Parser).toBe(true);
});
it('should call super with the correct arguments', function() {
var call = spyOn(Parser, 'call');
- var p = new platforms.ios.parser(proj);
+ var p = new iosParser(proj);
expect(call).toHaveBeenCalledWith(p, 'ios', proj);
});
});
@@ -80,7 +80,7 @@ describe('ios project parser', function () {
var p, cp, rm, mkdir, is_cordova, write, read, getOrientation;
var ios_proj = path.join(proj, 'platforms', 'ios');
beforeEach(function() {
- p = new platforms.ios.parser(ios_proj);
+ p = new iosParser(ios_proj);
cp = spyOn(shell, 'cp');
rm = spyOn(shell, 'rm');
mkdir = spyOn(shell, 'mkdir');
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/metadata/webos_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/webos_parser.spec.js b/cordova-lib/spec-cordova/metadata/webos_parser.spec.js
index 59010c4..c8b1b9b 100755
--- a/cordova-lib/spec-cordova/metadata/webos_parser.spec.js
+++ b/cordova-lib/spec-cordova/metadata/webos_parser.spec.js
@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
-var platforms = require('../../src/platforms/platforms'),
+var webosParser = require('../../src/cordova/metadata/webos_parser'),
util = require('../../src/cordova/util'),
path = require('path'),
shell = require('shelljs'),
@@ -39,7 +39,7 @@ describe('webos project parser', function() {
describe('constructions', function() {
it('should create an instance with a path', function() {
expect(function() {
- var p = new platforms.android.parser(proj);
+ var p = new webosParser(proj);
expect(p.path).toEqual(proj);
}).not.toThrow();
});
@@ -49,7 +49,7 @@ describe('webos project parser', function() {
var p, cp, rm, is_cordova, write, read;
var wos_proj = path.join(proj, 'platforms', 'webos');
beforeEach(function() {
- p = new platforms.webos.parser(wos_proj);
+ p = new webosParser(wos_proj);
cp = spyOn(shell, 'cp');
rm = spyOn(shell, 'rm');
is_cordova = spyOn(util, 'isCordova').andReturn(proj);
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/metadata/windows8_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/windows8_parser.spec.js b/cordova-lib/spec-cordova/metadata/windows8_parser.spec.js
index f8371d5..d26b5b3 100644
--- a/cordova-lib/spec-cordova/metadata/windows8_parser.spec.js
+++ b/cordova-lib/spec-cordova/metadata/windows8_parser.spec.js
@@ -19,7 +19,7 @@
/* jshint boss:true */
-var platforms = require('../../src/platforms/platforms'),
+var windowsParser = require('../../src/cordova/metadata/windows_parser'),
util = require('../../src/cordova/util'),
path = require('path'),
shell = require('shelljs'),
@@ -81,22 +81,22 @@ describe('windows8 project parser', function() {
it('should throw if provided directory does not contain a jsproj file', function() {
readdir.andReturn([]);
expect(function() {
- new platforms.windows8.parser(proj);
+ new windowsParser(proj);
}).toThrow();
});
it('should create an instance with path, manifest properties', function() {
expect(function() {
- var parser = new platforms.windows8.parser(proj);
+ var parser = new windowsParser(proj);
expect(parser.projDir).toEqual(proj);
expect(parser.manifestPath).toEqual(path.join(proj, 'package.appxmanifest'));
}).not.toThrow();
});
it('should be an instance of Parser', function() {
- expect(new platforms.windows8.parser(proj) instanceof Parser).toBe(true);
+ expect(new windowsParser(proj) instanceof Parser).toBe(true);
});
it('should call super with the correct arguments', function() {
var call = spyOn(Parser, 'call');
- var p = new platforms.windows8.parser(proj);
+ var p = new windowsParser(proj);
expect(call).toHaveBeenCalledWith(p, 'windows8', proj);
});
});
@@ -105,7 +105,7 @@ describe('windows8 project parser', function() {
var parser, cp, rm, is_cordova, write, read, mv, mkdir;
var windows8_proj = path.join(proj, 'platforms', 'windows8');
beforeEach(function() {
- parser = new platforms.windows8.parser(windows8_proj);
+ parser = new windowsParser(windows8_proj);
cp = spyOn(shell, 'cp');
rm = spyOn(shell, 'rm');
mv = spyOn(shell, 'mv');
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/metadata/wp8_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/wp8_parser.spec.js b/cordova-lib/spec-cordova/metadata/wp8_parser.spec.js
index 5228fa7..aae2643 100644
--- a/cordova-lib/spec-cordova/metadata/wp8_parser.spec.js
+++ b/cordova-lib/spec-cordova/metadata/wp8_parser.spec.js
@@ -19,7 +19,7 @@
/* jshint boss:true, sub:true */
-var platforms = require('../../src/platforms/platforms'),
+var wp8Parser = require('../../src/cordova/metadata/wp8_parser'),
util = require('../../src/cordova/util'),
path = require('path'),
shell = require('shelljs'),
@@ -105,22 +105,22 @@ describe('wp8 project parser', function() {
it('should throw if provided directory does not contain a csproj file', function() {
readdir.andReturn([]);
expect(function() {
- new platforms.wp8.parser(proj);
+ new wp8Parser(proj);
}).toThrow();
});
it('should create an instance with path, manifest properties', function() {
expect(function() {
- var p = new platforms.wp8.parser(proj);
+ var p = new wp8Parser(proj);
expect(p.wp8_proj_dir).toEqual(proj);
expect(p.manifest_path).toEqual(path.join(proj, 'Properties', 'WMAppManifest.xml'));
}).not.toThrow();
});
it('should be an instance of Parser', function() {
- expect(new platforms.wp8.parser(proj) instanceof Parser).toBe(true);
+ expect(new wp8Parser(proj) instanceof Parser).toBe(true);
});
it('should call super with the correct arguments', function() {
var call = spyOn(Parser, 'call');
- var p = new platforms.wp8.parser(proj);
+ var p = new wp8Parser(proj);
expect(call).toHaveBeenCalledWith(p, 'wp8', proj);
});
});
@@ -129,7 +129,7 @@ describe('wp8 project parser', function() {
var p, cp, rm, is_cordova, write, read, mv, mkdir, getOrientation;
var wp8_proj = path.join(proj, 'platforms', 'wp8');
beforeEach(function() {
- p = new platforms.wp8.parser(wp8_proj);
+ p = new wp8Parser(wp8_proj);
cp = spyOn(shell, 'cp');
rm = spyOn(shell, 'rm');
mv = spyOn(shell, 'mv');
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/platforms/PlatformApiPoly.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/platforms/PlatformApiPoly.spec.js b/cordova-lib/spec-cordova/platforms/PlatformApiPoly.spec.js
new file mode 100644
index 0000000..0f60dd8
--- /dev/null
+++ b/cordova-lib/spec-cordova/platforms/PlatformApiPoly.spec.js
@@ -0,0 +1,315 @@
+/**
+ 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 Q = require('q');
+var fs = require('fs');
+var et = require('elementtree');
+var path = require('path');
+var shell = require('shelljs');
+var xmlHelpers = require('../../src/util/xml-helpers');
+var ActionStack = require('../../src/plugman/util/action-stack');
+var superspawn = require('../../src/cordova/superspawn');
+var PluginInfo = require('../../src/PluginInfo');
+var ConfigParser = require('../../src/configparser/ConfigParser');
+var knownPlatforms = require('../../src/platforms/platforms');
+var PlatformApiPoly = require('../../src/platforms/PlatformApiPoly');
+
+var PLATFORM = 'android';
+var PLATFORM_VERSION = '3.7.0';
+var PLATFORM_LIB = '/some/platform/lib';
+var CORDOVA_ROOT = path.join(__dirname, '../fixtures/projects/platformApi');
+var PLATFORM_ROOT = path.join(CORDOVA_ROOT, 'platforms/android');
+var DUMMY_PLUGIN = path.join(__dirname, '../fixtures/plugins/test');
+var TEST_XML = '<?xml version="1.0" encoding="UTF-8"?>\n' +
+ '<widget xmlns = "http://www.w3.org/ns/widgets"\n' +
+ ' xmlns:cdv = "http://cordova.apache.org/ns/1.0"\n' +
+ ' id = "io.cordova.hellocordova"\n' +
+ ' version = "0.0.1">\n' +
+ ' <name>Hello Cordova</name>\n' +
+ ' <description>\n' +
+ ' A sample Apache Cordova application that responds to the deviceready event.\n' +
+ ' </description>\n' +
+ ' <author href="http://cordova.io" email="dev@cordova.apache.org">\n' +
+ ' Apache Cordova Team\n' +
+ ' </author>\n' +
+ ' <content src="index.html" />\n' +
+ ' <access origin="*" />\n' +
+ ' <preference name="fullscreen" value="true" />\n' +
+ ' <preference name="webviewbounce" value="true" />\n' +
+ '</widget>\n';
+
+var platformApiPolyPublicMethods = [
+ 'getPlatformInfo',
+ 'prepare',
+ 'addPlugin',
+ 'removePlugin',
+ 'updatePlugin',
+ 'build',
+ 'run',
+ 'clean',
+ 'requirements'
+];
+
+describe('PlatformApi polyfill', function () {
+ var platformApi;
+
+ beforeEach(function () {
+ var originalParseElementtreeSync = xmlHelpers.parseElementtreeSync;
+ spyOn(xmlHelpers, 'parseElementtreeSync').andCallFake(function (configPath) {
+ return /config\.xml$/.test(configPath) ? new et.ElementTree(et.XML(TEST_XML)) :
+ originalParseElementtreeSync(configPath);
+ });
+
+ platformApi = new PlatformApiPoly(PLATFORM, PLATFORM_ROOT);
+ });
+
+ it('should be constructable', function () {
+ var api;
+ expect(function(){api = new PlatformApiPoly(PLATFORM, PLATFORM_ROOT);}).not.toThrow();
+ expect(api).toEqual(jasmine.any(PlatformApiPoly));
+ });
+
+ it('should fail when unknown platform is specified', function () {
+ var api;
+ expect(function(){api = new PlatformApiPoly('fakePlatform', PLATFORM_ROOT);}).toThrow();
+ });
+
+ it('should fail when mandatory argument is not specified', function () {
+ var api;
+ expect(function(){api = new PlatformApiPoly(PLATFORM);}).toThrow();
+ expect(function(){api = new PlatformApiPoly(null, PLATFORM_ROOT);}).toThrow();
+ });
+
+ it('should have fields defined', function () {
+ expect(platformApi.platform).toBe(PLATFORM);
+ expect(platformApi.root).toBe(PLATFORM_ROOT);
+ });
+
+ it('should have \'static\' methods defined', function () {
+ expect(platformApi.constructor.createPlatform).toEqual(jasmine.any(Function));
+ expect(platformApi.constructor.updatePlatform).toEqual(jasmine.any(Function));
+ });
+
+ it('should have methods defined', function () {
+ platformApiPolyPublicMethods.forEach(function (methodName) {
+ expect(platformApi[methodName]).toEqual(jasmine.any(Function));
+ });
+ });
+
+ describe('methods:', function () {
+
+ var FAKE_PROJECT, OPTIONS, getPlatformApi, fail, success;
+
+ beforeEach(function () {
+ getPlatformApi = spyOn(knownPlatforms, 'getPlatformApi').andReturn(platformApi);
+
+ spyOn(shell, 'cp');
+ spyOn(shell, 'rm');
+ spyOn(shell, 'mkdir');
+ spyOn(fs, 'writeFileSync');
+
+ fail = jasmine.createSpy('fail');
+ success = jasmine.createSpy('success');
+
+ FAKE_PROJECT = {locations: {platforms: path.dirname(PLATFORM_ROOT), www: path.join(CORDOVA_ROOT, 'www')}, projectConfig: new ConfigParser('/fake/config.xml')};
+ OPTIONS = {platformDetails: {libDir: PLATFORM_LIB, platform: PLATFORM, version: PLATFORM_VERSION}};
+ });
+
+ describe('static create/updatePlatform methods', function () {
+ var spawn;
+
+ beforeEach(function () {
+ spawn = spyOn(superspawn, 'spawn').andReturn(Q());
+ });
+
+ it('should create/update platform through running platforms\' scripts', function (done) {
+ Q.all([PlatformApiPoly.createPlatform(FAKE_PROJECT, OPTIONS),
+ PlatformApiPoly.updatePlatform(FAKE_PROJECT, OPTIONS)])
+ .then(function () {
+ expect(spawn).toHaveBeenCalled();
+ expect(spawn.calls.length).toBe(2);
+ }).fail(function (err) {
+ expect(err).not.toBeDefined();
+ }).fin(done);
+ });
+
+ it('should pass down arguments to platforms\' scripts', function (done) {
+ Q.all([PlatformApiPoly.createPlatform(FAKE_PROJECT, OPTIONS),
+ PlatformApiPoly.updatePlatform(FAKE_PROJECT, OPTIONS)])
+ .then(function () {
+ expect(spawn).toHaveBeenCalled();
+ expect(spawn.calls.length).toBe(2);
+ expect(spawn.calls[0].args[0]).toBe(path.join(PLATFORM_LIB, 'bin/create'));
+ expect(spawn.calls[0].args[1]).toContain(PLATFORM_ROOT);
+ expect(spawn.calls[1].args[0]).toBe(path.join(PLATFORM_LIB, 'bin/update'));
+ expect(spawn.calls[1].args[1]).toContain(PLATFORM_ROOT);
+ }).fail(function (err) {
+ expect(err).not.toBeDefined();
+ }).fin(done);
+ });
+
+ it('should copy cordova JS sources into created platform', function (done) {
+ Q.all([PlatformApiPoly.createPlatform(FAKE_PROJECT, OPTIONS),
+ PlatformApiPoly.updatePlatform(FAKE_PROJECT, OPTIONS)])
+ .then(function () {
+ expect(shell.cp).toHaveBeenCalled();
+ expect(shell.cp.calls.length).toBe(2);
+ }).fail(fail)
+ .fin(function () {
+ expect(fail).not.toHaveBeenCalled();
+ done();
+ });
+ });
+
+ it('should fail immediately if options.platformInfo is not specified', function (done) {
+ Q.all([PlatformApiPoly.createPlatform(FAKE_PROJECT),
+ PlatformApiPoly.updatePlatform(FAKE_PROJECT)])
+ .then(success)
+ .fail(fail)
+ .fin(function function_name (argument) {
+ expect(success).not.toHaveBeenCalled();
+ expect(fail).toHaveBeenCalled();
+ expect(spawn).not.toHaveBeenCalled();
+ done();
+ });
+ });
+ });
+
+ describe('prepare method', function () {
+ beforeEach(function () {
+ spyOn(platformApi._parser, 'update_www');
+ spyOn(platformApi._parser, 'update_project').andReturn(Q());
+ });
+
+ it('should return promise', function (done) {
+ var promise = platformApi.prepare(FAKE_PROJECT, OPTIONS);
+ expect(Q.isPromise(promise)).toBeTruthy();
+ promise.fin(done);
+ });
+
+ it('should call parser\'s corresponding methods', function (done) {
+ platformApi.prepare(FAKE_PROJECT, OPTIONS)
+ .then(function () {
+ [platformApi._parser.update_www, platformApi._parser.update_project]
+ .forEach(function (method) {
+ expect(method).toHaveBeenCalled();
+ });
+ })
+ .fail(fail)
+ .fin(function () {
+ expect(fail).not.toHaveBeenCalled();
+ done();
+ });
+ });
+ });
+
+ describe('pluginAdd method', function () {
+ var plugin, actionsProcess;
+
+ beforeEach(function () {
+ plugin = new PluginInfo(DUMMY_PLUGIN);
+ actionsProcess = spyOn(ActionStack.prototype, 'process').andCallThrough();
+ });
+
+ it('should return promise', function (done) {
+ var promise = platformApi.addPlugin(plugin);
+ expect(Q.isPromise(promise)).toBeTruthy();
+ promise.fin(done);
+ });
+
+ it('should fail if plugin parameter is not specified', function (done) {
+ platformApi.addPlugin()
+ .then(success)
+ .fail(fail)
+ .fin(function () {
+ expect(success).not.toHaveBeenCalled();
+ expect(fail).toHaveBeenCalled();
+ done();
+ });
+ });
+
+ it('should process all plugin files through action stack', function (done) {
+ platformApi.addPlugin(plugin)
+ .then(success)
+ .fail(fail)
+ .fin(function () {
+ expect(actionsProcess).toHaveBeenCalled();
+ expect(success).toHaveBeenCalled();
+ expect(fail).not.toHaveBeenCalled();
+ done();
+ });
+ });
+ });
+
+ describe('platform actions', function () {
+ var spawnSpy;
+
+ beforeEach(function () {
+ spawnSpy = spyOn(superspawn, 'spawn');
+ });
+
+ it('should return promise', function (done) {
+ var ops = [
+ platformApi.build(/*opts*/),
+ platformApi.run(/*opts*/),
+ platformApi.clean(/*opts*/),
+ platformApi.requirements()
+ ];
+
+ ops.forEach(function (op) {
+ expect(Q.isPromise(op));
+ });
+ Q.all(ops).fin(done);
+ });
+
+ it('should do their job through running platforms\' scripts', function (done) {
+ var ops = [
+ platformApi.build(/*opts*/),
+ platformApi.run(/*opts*/),
+ platformApi.clean(/*opts*/)
+ ];
+
+ Q.all(ops)
+ .then(function () {
+ expect(spawnSpy).toHaveBeenCalled();
+ expect(spawnSpy.calls.length).toEqual(3);
+ }).fin(done);
+ });
+
+ it('should convert and pass down options to platforms\' scripts', function (done) {
+ var options = {
+ release: true,
+ nobuild: true,
+ device: true,
+ target: 'FakeDevice',
+ archs: ['arm', 'x86'],
+ buildConfig: '/some/path'
+ };
+ spawnSpy.andReturn(Q());
+ platformApi.build(options)
+ .then(function () {
+ ['--release', '--nobuild', '--device', '--target=' + options.target, '--archs=arm,x86', '--buildConfig=' +options.buildConfig]
+ .forEach(function (arg) {
+ expect(spawnSpy.calls[0].args[1]).toContain(arg);
+ });
+ }).fin(done);
+ });
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/platforms/platforms.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/platforms/platforms.spec.js b/cordova-lib/spec-cordova/platforms/platforms.spec.js
new file mode 100644
index 0000000..90b690c
--- /dev/null
+++ b/cordova-lib/spec-cordova/platforms/platforms.spec.js
@@ -0,0 +1,72 @@
+/**
+ 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 path = require('path');
+var rewire = require('rewire');
+
+var util = require('../../src/cordova/util');
+var platforms = rewire('../../src/platforms/platforms');
+
+var CORDOVA_ROOT = path.join(__dirname, '../fixtures/projects/platformApi');
+var PLATFORM_WITH_API = path.join(CORDOVA_ROOT, 'platforms/windows');
+var PLATFORM_WOUT_API = path.join(CORDOVA_ROOT, 'platforms/android');
+
+var MockPlatformApi = require(path.join(PLATFORM_WITH_API, 'cordova', 'Api'));
+var PlatformApiPoly = require('../../src/platforms/PlatformApiPoly');
+
+describe('getPlatformApi method', function () {
+ var isCordova;
+
+ beforeEach(function () {
+ // reset api cache after each spec
+ platforms.__set__('cachedApis', {});
+ isCordova = spyOn(util, 'isCordova').andReturn(CORDOVA_ROOT);
+ });
+
+ it('should return PlatformApi class defined by platform', function () {
+ var platformApi = platforms.getPlatformApi('windows', PLATFORM_WITH_API);
+ expect(platformApi).toEqual(jasmine.any(MockPlatformApi));
+ });
+
+ it('should return PlatformApi polyfill if PlatformApi is not defined by platform', function () {
+ var platformApi = platforms.getPlatformApi('android', PLATFORM_WOUT_API);
+ expect(platformApi).toEqual(jasmine.any(PlatformApiPoly));
+ });
+
+ it('should cache PlatformApi instance for further calls', function () {
+ var platformApi = platforms.getPlatformApi('windows', PLATFORM_WITH_API);
+ expect(platformApi.fakeProperty).not.toBeDefined();
+ platformApi.fakeProperty = 'fakeValue';
+ expect(platforms.getPlatformApi('windows', PLATFORM_WITH_API).fakeProperty).toBe('fakeValue');
+ });
+
+ it('should succeed if called inside of cordova project w/out platformRoot param', function () {
+ var platformApi = platforms.getPlatformApi('windows');
+ expect(platformApi instanceof MockPlatformApi).toBeTruthy();
+ });
+
+ it('should throw if called outside of cordova project w/out platformRoot param', function () {
+ isCordova.andReturn(false);
+ expect(function () { platforms.getPlatformApi('windows'); }).toThrow();
+ });
+
+ it('should throw for unknown platform', function () {
+ expect(function () { platforms.getPlatformApi('invalid_platform'); }).toThrow();
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/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 666394c..bf9d31a 100644
--- a/cordova-lib/spec-cordova/prepare.spec.js
+++ b/cordova-lib/spec-cordova/prepare.spec.js
@@ -18,7 +18,6 @@
*/
var shell = require('shelljs'),
- plugman = require('../src/plugman/plugman'),
PlatformJson = require('../src/plugman/util/PlatformJson'),
path = require('path'),
util = require('../src/cordova/util'),
@@ -59,35 +58,33 @@ describe('prepare command', function() {
list_platforms,
fire,
parsers = {},
- plugman_prepare,
find_plugins,
cp,
mkdir,
- load;
- beforeEach(function() {
- is_cordova = spyOn(util, 'isCordova').andReturn(project_dir);
- cd_project_root = spyOn(util, 'cdProjectRoot').andReturn(project_dir);
- list_platforms = spyOn(util, 'listPlatforms').andReturn(supported_platforms);
- fire = spyOn(HooksRunner.prototype, 'fire').andReturn(Q());
+ load, platformApi, getPlatformApi;
- spyOn(platforms, 'getPlatformProject').andCallFake(function(platform, rootDir) {
+ beforeEach(function () {
+ getPlatformApi = spyOn(platforms, 'getPlatformApi').andCallFake(function (platform, rootDir) {
return {
- update_www: jasmine.createSpy(platform + ' update_www'),
- cordovajs_path: function(libDir) { return 'path/to/cordova.js/in/.cordova/lib';},
- www_dir:function() { return path.join(project_dir, 'platforms', platform, 'www'); },
- config_xml: function () { return path.join(project_dir, 'platforms', platform, 'www', 'config.xml');},
- update_project: function () { return Q();},
+ prepare: jasmine.createSpy('prepare').andReturn(Q()),
+ getPlatformInfo: jasmine.createSpy('getPlatformInfo').andReturn({
+ locations: {
+ www: path.join(project_dir, 'platforms', platform, 'www')
+ }
+ }),
};
});
+ is_cordova = spyOn(util, 'isCordova').andReturn(project_dir);
+ cd_project_root = spyOn(util, 'cdProjectRoot').andReturn(project_dir);
+ list_platforms = spyOn(util, 'listPlatforms').andReturn(supported_platforms);
+ fire = spyOn(HooksRunner.prototype, 'fire').andReturn(Q());
- plugman_prepare = spyOn(plugman, 'prepare').andReturn(Q());
find_plugins = spyOn(util, 'findPlugins').andReturn([]);
spyOn(PlatformJson, 'load').andReturn(new PlatformJson(null, null, {}));
spyOn(PlatformJson.prototype, 'save');
load = spyOn(lazy_load, 'based_on_config').andReturn(Q());
cp = spyOn(shell, 'cp').andReturn(true);
mkdir = spyOn(shell, 'mkdir');
- spyOn(prepare, '_mergeXml');
spyOn(ConfigParser.prototype, 'write');
spyOn(xmlHelpers, 'parseElementtreeSync').andCallFake(function() {
return new et.ElementTree(et.XML(TEST_XML));
@@ -122,26 +119,17 @@ describe('prepare command', function() {
expect(err).toBeUndefined();
}).fin(done);
});
- it('should invoke each platform\'s parser\'s update_project method', function(done) {
+ it('should get PlatformApi instance for each platform and invoke its\' run method', function(done) {
prepare().then(function() {
supported_platforms.forEach(function(p) {
expect(parsers[p]).toHaveBeenCalled();
+ expect(getPlatformApi).toHaveBeenCalledWith(p);
});
+ expect(platformApi.run).toHaveBeenCalled();
}, function(err) {
expect(err).toBeUndefined();
}).fin(done);
});
- describe('plugman integration', function() {
- it('should invoke plugman.prepare after update_project', function(done) {
- prepare().then(function() {
- supported_platforms.forEach(function(p) {
- expect(plugman_prepare).toHaveBeenCalled();
- });
- }, function(err) {
- expect(err).toBeUndefined();
- }).fin(done);
- });
- });
});
describe('hooks', function() {
@@ -178,118 +166,3 @@ describe('prepare command', function() {
});
});
});
-
-describe('prepare._mergeXml', function () {
- var dstXml;
- beforeEach(function() {
- dstXml = et.XML(TEST_XML);
- });
- it('should merge attributes and text of the root element without clobbering', function () {
- var testXml = et.XML('<widget foo="bar" id="NOTANID">TEXT</widget>');
- prepare._mergeXml(testXml, dstXml);
- expect(dstXml.attrib.foo).toEqual('bar');
- expect(dstXml.attrib.id).not.toEqual('NOTANID');
- expect(dstXml.text).not.toEqual('TEXT');
- });
-
- it('should merge attributes and text of the root element with clobbering', function () {
- var testXml = et.XML('<widget foo="bar" id="NOTANID">TEXT</widget>');
- prepare._mergeXml(testXml, dstXml, 'foo', true);
- expect(dstXml.attrib.foo).toEqual('bar');
- expect(dstXml.attrib.id).toEqual('NOTANID');
- expect(dstXml.text).toEqual('TEXT');
- });
-
- it('should not merge platform tags with the wrong platform', function () {
- var testXml = et.XML('<widget><platform name="bar"><testElement testAttrib="value">testTEXT</testElement></platform></widget>'),
- origCfg = et.tostring(dstXml);
-
- prepare._mergeXml(testXml, dstXml, 'foo', true);
- expect(et.tostring(dstXml)).toEqual(origCfg);
- });
-
- it('should merge platform tags with the correct platform', function () {
- var testXml = et.XML('<widget><platform name="bar"><testElement testAttrib="value">testTEXT</testElement></platform></widget>'),
- origCfg = et.tostring(dstXml);
-
- prepare._mergeXml(testXml, dstXml, 'bar', true);
- expect(et.tostring(dstXml)).not.toEqual(origCfg);
- var testElement = dstXml.find('testElement');
- expect(testElement).toBeDefined();
- expect(testElement.attrib.testAttrib).toEqual('value');
- expect(testElement.text).toEqual('testTEXT');
- });
-
- it('should merge singelton children without clobber', function () {
- var testXml = et.XML('<widget><author testAttrib="value" href="http://www.nowhere.com">SUPER_AUTHOR</author></widget>');
-
- prepare._mergeXml(testXml, dstXml);
- var testElements = dstXml.findall('author');
- expect(testElements).toBeDefined();
- expect(testElements.length).toEqual(1);
- expect(testElements[0].attrib.testAttrib).toEqual('value');
- expect(testElements[0].attrib.href).toEqual('http://cordova.io');
- expect(testElements[0].attrib.email).toEqual('dev@cordova.apache.org');
- expect(testElements[0].text).toContain('Apache Cordova Team');
- });
-
- it('should clobber singelton children with clobber', function () {
- var testXml = et.XML('<widget><author testAttrib="value" href="http://www.nowhere.com">SUPER_AUTHOR</author></widget>');
-
- prepare._mergeXml(testXml, dstXml, '', true);
- var testElements = dstXml.findall('author');
- expect(testElements).toBeDefined();
- expect(testElements.length).toEqual(1);
- expect(testElements[0].attrib.testAttrib).toEqual('value');
- expect(testElements[0].attrib.href).toEqual('http://www.nowhere.com');
- expect(testElements[0].attrib.email).toEqual('dev@cordova.apache.org');
- expect(testElements[0].text).toEqual('SUPER_AUTHOR');
- });
-
- it('should append non singelton children', function () {
- var testXml = et.XML('<widget><preference num="1"/> <preference num="2"/></widget>');
-
- prepare._mergeXml(testXml, dstXml, '', true);
- var testElements = dstXml.findall('preference');
- expect(testElements.length).toEqual(4);
- });
-
- it('should handle namespaced elements', function () {
- var testXml = et.XML('<widget><foo:bar testAttrib="value">testText</foo:bar></widget>');
-
- prepare._mergeXml(testXml, dstXml, 'foo', true);
- var testElement = dstXml.find('foo:bar');
- expect(testElement).toBeDefined();
- expect(testElement.attrib.testAttrib).toEqual('value');
- expect(testElement.text).toEqual('testText');
- });
-
- it('should not append duplicate non singelton children', function () {
- var testXml = et.XML('<widget><preference name="fullscreen" value="true"/></widget>');
-
- prepare._mergeXml(testXml, dstXml, '', true);
- var testElements = dstXml.findall('preference');
- expect(testElements.length).toEqual(2);
- });
-
- it('should not skip partial duplicate non singelton children', function () {
- //remove access tags from dstXML
- var testElements = dstXml.findall('access');
- for(var i = 0; i < testElements.length; i++) {
- dstXml.remove(testElements[i]);
- }
- testElements = dstXml.findall('access');
- expect(testElements.length).toEqual(0);
- //add an external whitelist access tag
- var testXml = et.XML('<widget><access origin="*" launch-external="yes"/></widget>');
- prepare._mergeXml(testXml, dstXml, '', true);
- testElements = dstXml.findall('access');
- expect(testElements.length).toEqual(1);
- //add an internal whitelist access tag
- testXml = et.XML('<widget><access origin="*"/></widget>');
- prepare._mergeXml(testXml, dstXml, '', true);
- testElements = dstXml.findall('access');
- expect(testElements.length).toEqual(2);
-
- });
-});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/run.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/run.spec.js b/cordova-lib/spec-cordova/run.spec.js
index 6271cfe..627451b 100644
--- a/cordova-lib/spec-cordova/run.spec.js
+++ b/cordova-lib/spec-cordova/run.spec.js
@@ -18,8 +18,6 @@
*/
var cordova = require('../src/cordova/cordova'),
platforms = require('../src/platforms/platforms'),
- superspawn = require('../src/cordova/superspawn'),
- path = require('path'),
HooksRunner = require('../src/hooks/HooksRunner'),
Q = require('q'),
util = require('../src/cordova/util');
@@ -27,7 +25,7 @@ var cordova = require('../src/cordova/cordova'),
var supported_platforms = Object.keys(platforms).filter(function(p) { return p != 'www'; });
describe('run command', function() {
- var is_cordova, cd_project_root, list_platforms, fire;
+ var is_cordova, cd_project_root, list_platforms, fire, platformApi, getPlatformApi;
var project_dir = '/some/path';
var prepare_spy;
@@ -37,7 +35,8 @@ describe('run command', function() {
list_platforms = spyOn(util, 'listPlatforms').andReturn(supported_platforms);
fire = spyOn(HooksRunner.prototype, 'fire').andReturn(Q());
prepare_spy = spyOn(cordova.raw, 'prepare').andReturn(Q());
- spyOn(superspawn, 'spawn').andReturn(Q);
+ platformApi = { run: jasmine.createSpy('run').andReturn(Q()) };
+ 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(done) {
@@ -61,19 +60,26 @@ describe('run command', function() {
});
describe('success', function() {
- it('should run inside a Cordova-based project with at least one added platform and call prepare and shell out to the run script', function(done) {
+ it('should call prepare before actually run platform ', function(done) {
cordova.raw.run(['android','ios']).then(function() {
expect(prepare_spy).toHaveBeenCalledWith({ platforms: [ 'android', 'ios' ], verbose: false, options: [] });
- expect(superspawn.spawn).toHaveBeenCalledWith(path.join(project_dir, 'platforms', 'android', 'cordova', 'run'), [], jasmine.any(Object));
- expect(superspawn.spawn).toHaveBeenCalledWith(path.join(project_dir, 'platforms', 'ios', 'cordova', 'run'), [], jasmine.any(Object));
+ }, function(err) {
+ expect(err).toBeUndefined();
+ }).fin(done);
+ });
+ it('should get PlatformApi instance for each platform and call its\' run method', function(done) {
+ cordova.raw.run(['android','ios']).then(function() {
+ expect(getPlatformApi).toHaveBeenCalledWith('android');
+ expect(getPlatformApi).toHaveBeenCalledWith('ios');
+ expect(platformApi.run).toHaveBeenCalled();
}, function(err) {
expect(err).toBeUndefined();
}).fin(done);
});
it('should pass down parameters', function(done) {
- cordova.raw.run({platforms: ['blackberry10'], options:['--password', '1q1q']}).then(function() {
- expect(prepare_spy).toHaveBeenCalledWith({ platforms: [ 'blackberry10' ], options: [ '--password', '1q1q' ], verbose: false });
- expect(superspawn.spawn).toHaveBeenCalledWith(path.join(project_dir, 'platforms', 'blackberry10', 'cordova', 'run'), ['--password', '1q1q'], jasmine.any(Object));
+ cordova.raw.run({platforms: ['blackberry10'], options:{password: '1q1q'}}).then(function() {
+ expect(prepare_spy).toHaveBeenCalledWith({ platforms: [ 'blackberry10' ], options: { password: '1q1q' }, verbose: false });
+ expect(platformApi.run).toHaveBeenCalledWith({password: '1q1q'});
}, function(err) {
expect(err).toBeUndefined();
}).fin(done);
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/save.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/save.spec.js b/cordova-lib/spec-cordova/save.spec.js
index a04dc4b..24a6128 100644
--- a/cordova-lib/spec-cordova/save.spec.js
+++ b/cordova-lib/spec-cordova/save.spec.js
@@ -23,9 +23,11 @@ describe('(save flag)', function () {
helpers = require('./helpers'),
path = require('path'),
Q = require('q'),
+ fs = require('fs'),
shell = require('shelljs'),
util = require('../src/cordova/util'),
prepare = require('../src/cordova/prepare'),
+ PlatformApi = require('../src/platforms/PlatformApiPoly'),
platform = rewire('../src/cordova/platform');
var appName = 'testApp',
@@ -54,9 +56,8 @@ describe('(save flag)', function () {
timeout = 60 * 1000;
//mock variables
- var revert_copy_cordova_js,
- revert_copy_cordovajs_src,
- revert_install_plugins_for_new_platform;
+ var revert_install_plugins_for_new_platform,
+ createPlatformOrig = PlatformApi.createPlatform;
beforeEach(function (done) {
// initial cleanup
@@ -68,9 +69,10 @@ describe('(save flag)', function () {
spyOn(util, 'cdProjectRoot').andReturn(appPath);
spyOn(cordova.raw, 'prepare').andReturn(Q());
+ spyOn(PlatformApi, 'createPlatform').andReturn(Q());
+ spyOn(PlatformApi, 'updatePlatform').andReturn(Q());
+
//rewire mocks
- revert_copy_cordova_js = platform.__set__('copy_cordova_js', function () {});
- revert_copy_cordovajs_src = platform.__set__('copy_cordovajs_src', function () {});
revert_install_plugins_for_new_platform = platform.__set__('installPluginsForNewPlatform', function () { return Q(); });
//creating test app
@@ -86,8 +88,6 @@ describe('(save flag)', function () {
}, timeout);
afterEach(function () {
- revert_copy_cordova_js();
- revert_copy_cordovajs_src();
revert_install_plugins_for_new_platform();
});
@@ -232,7 +232,11 @@ describe('(save flag)', function () {
helpers.setEngineSpec(appPath, platformName, platformVersionNew);
platform('add', platformName + '@' + platformVersionNew)
.then(function () {
- return cordova.raw.platform('update', platformName + '@' + platformVersionOld, { 'save': true });
+ var fsExistsSync = fs.existsSync.bind(fs);
+ spyOn(fs, 'existsSync').andCallFake(function (somePath) {
+ return (somePath === path.join(appPath, 'platforms', platformName)) || fsExistsSync(somePath);
+ });
+ return platform('update', platformName + '@' + platformVersionOld, { 'save': true });
}).then(function () {
expect(helpers.getEngineSpec(appPath, platformName)).toBe('~' + platformVersionOld);
done();
@@ -247,7 +251,11 @@ describe('(save flag)', function () {
helpers.setEngineSpec(appPath, platformName, platformVersionNew);
platform('add', platformName + '@' + platformVersionNew)
.then(function () {
- return cordova.raw.platform('update', platformGitUrl, { 'save': true });
+ var fsExistsSync = fs.existsSync.bind(fs);
+ spyOn(fs, 'existsSync').andCallFake(function (somePath) {
+ return (somePath === path.join(appPath, 'platforms', platformName)) || fsExistsSync(somePath);
+ });
+ return platform('update', platformGitUrl, { 'save': true });
}).then(function () {
var spec = helpers.getEngineSpec(appPath, platformName);
expect(spec).not.toBe(null);
@@ -437,6 +445,11 @@ describe('(save flag)', function () {
});
describe('prepare', function () {
+ beforeEach(function () {
+ // Restore back mocked createPlatform functionality
+ PlatformApi.createPlatform = createPlatformOrig;
+ });
+
it('spec.23 should restore all platforms and plugins', function (done) {
helpers.setEngineSpec(appPath, platformName, platformLocalPath);
helpers.setPluginSpec(appPath, localPluginName, localPluginPath);
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-cordova/xml-helpers.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/xml-helpers.spec.js b/cordova-lib/spec-cordova/xml-helpers.spec.js
index 25e6c8f..ade3c47 100644
--- a/cordova-lib/spec-cordova/xml-helpers.spec.js
+++ b/cordova-lib/spec-cordova/xml-helpers.spec.js
@@ -34,6 +34,23 @@ var path = require('path')
, goodbyeTag = et.XML('<h1>GOODBYE</h1>')
, helloTagTwo = et.XML('<h1> HELLO </h1>');
+var TEST_XML = '<?xml version="1.0" encoding="UTF-8"?>\n' +
+ '<widget xmlns = "http://www.w3.org/ns/widgets"\n' +
+ ' xmlns:cdv = "http://cordova.apache.org/ns/1.0"\n' +
+ ' id = "io.cordova.hellocordova"\n' +
+ ' version = "0.0.1">\n' +
+ ' <name>Hello Cordova</name>\n' +
+ ' <description>\n' +
+ ' A sample Apache Cordova application that responds to the deviceready event.\n' +
+ ' </description>\n' +
+ ' <author href="http://cordova.io" email="dev@cordova.apache.org">\n' +
+ ' Apache Cordova Team\n' +
+ ' </author>\n' +
+ ' <content src="index.html" />\n' +
+ ' <access origin="*" />\n' +
+ ' <preference name="fullscreen" value="true" />\n' +
+ ' <preference name="webviewbounce" value="true" />\n' +
+ '</widget>\n';
describe('xml-helpers', function(){
describe('parseElementtreeSync', function() {
@@ -136,4 +153,119 @@ describe('xml-helpers', function(){
expect(config_xml.findall('access').length).toEqual(3);
});
});
+
+ describe('mergeXml', function () {
+ var dstXml;
+ beforeEach(function() {
+ dstXml = et.XML(TEST_XML);
+ });
+ it('should merge attributes and text of the root element without clobbering', function () {
+ var testXml = et.XML('<widget foo="bar" id="NOTANID">TEXT</widget>');
+ xml_helpers.mergeXml(testXml, dstXml);
+ expect(dstXml.attrib.foo).toEqual('bar');
+ expect(dstXml.attrib.id).not.toEqual('NOTANID');
+ expect(dstXml.text).not.toEqual('TEXT');
+ });
+
+ it('should merge attributes and text of the root element with clobbering', function () {
+ var testXml = et.XML('<widget foo="bar" id="NOTANID">TEXT</widget>');
+ xml_helpers.mergeXml(testXml, dstXml, 'foo', true);
+ expect(dstXml.attrib.foo).toEqual('bar');
+ expect(dstXml.attrib.id).toEqual('NOTANID');
+ expect(dstXml.text).toEqual('TEXT');
+ });
+
+ it('should not merge platform tags with the wrong platform', function () {
+ var testXml = et.XML('<widget><platform name="bar"><testElement testAttrib="value">testTEXT</testElement></platform></widget>'),
+ origCfg = et.tostring(dstXml);
+
+ xml_helpers.mergeXml(testXml, dstXml, 'foo', true);
+ expect(et.tostring(dstXml)).toEqual(origCfg);
+ });
+
+ it('should merge platform tags with the correct platform', function () {
+ var testXml = et.XML('<widget><platform name="bar"><testElement testAttrib="value">testTEXT</testElement></platform></widget>'),
+ origCfg = et.tostring(dstXml);
+
+ xml_helpers.mergeXml(testXml, dstXml, 'bar', true);
+ expect(et.tostring(dstXml)).not.toEqual(origCfg);
+ var testElement = dstXml.find('testElement');
+ expect(testElement).toBeDefined();
+ expect(testElement.attrib.testAttrib).toEqual('value');
+ expect(testElement.text).toEqual('testTEXT');
+ });
+
+ it('should merge singelton children without clobber', function () {
+ var testXml = et.XML('<widget><author testAttrib="value" href="http://www.nowhere.com">SUPER_AUTHOR</author></widget>');
+
+ xml_helpers.mergeXml(testXml, dstXml);
+ var testElements = dstXml.findall('author');
+ expect(testElements).toBeDefined();
+ expect(testElements.length).toEqual(1);
+ expect(testElements[0].attrib.testAttrib).toEqual('value');
+ expect(testElements[0].attrib.href).toEqual('http://cordova.io');
+ expect(testElements[0].attrib.email).toEqual('dev@cordova.apache.org');
+ expect(testElements[0].text).toContain('Apache Cordova Team');
+ });
+
+ it('should clobber singelton children with clobber', function () {
+ var testXml = et.XML('<widget><author testAttrib="value" href="http://www.nowhere.com">SUPER_AUTHOR</author></widget>');
+
+ xml_helpers.mergeXml(testXml, dstXml, '', true);
+ var testElements = dstXml.findall('author');
+ expect(testElements).toBeDefined();
+ expect(testElements.length).toEqual(1);
+ expect(testElements[0].attrib.testAttrib).toEqual('value');
+ expect(testElements[0].attrib.href).toEqual('http://www.nowhere.com');
+ expect(testElements[0].attrib.email).toEqual('dev@cordova.apache.org');
+ expect(testElements[0].text).toEqual('SUPER_AUTHOR');
+ });
+
+ it('should append non singelton children', function () {
+ var testXml = et.XML('<widget><preference num="1"/> <preference num="2"/></widget>');
+
+ xml_helpers.mergeXml(testXml, dstXml, '', true);
+ var testElements = dstXml.findall('preference');
+ expect(testElements.length).toEqual(4);
+ });
+
+ it('should handle namespaced elements', function () {
+ var testXml = et.XML('<widget><foo:bar testAttrib="value">testText</foo:bar></widget>');
+
+ xml_helpers.mergeXml(testXml, dstXml, 'foo', true);
+ var testElement = dstXml.find('foo:bar');
+ expect(testElement).toBeDefined();
+ expect(testElement.attrib.testAttrib).toEqual('value');
+ expect(testElement.text).toEqual('testText');
+ });
+
+ it('should not append duplicate non singelton children', function () {
+ var testXml = et.XML('<widget><preference name="fullscreen" value="true"/></widget>');
+
+ xml_helpers.mergeXml(testXml, dstXml, '', true);
+ var testElements = dstXml.findall('preference');
+ expect(testElements.length).toEqual(2);
+ });
+
+ it('should not skip partial duplicate non singelton children', function () {
+ //remove access tags from dstXML
+ var testElements = dstXml.findall('access');
+ for(var i = 0; i < testElements.length; i++) {
+ dstXml.remove(testElements[i]);
+ }
+ testElements = dstXml.findall('access');
+ expect(testElements.length).toEqual(0);
+ //add an external whitelist access tag
+ var testXml = et.XML('<widget><access origin="*" launch-external="yes"/></widget>');
+ xml_helpers.mergeXml(testXml, dstXml, '', true);
+ testElements = dstXml.findall('access');
+ expect(testElements.length).toEqual(1);
+ //add an internal whitelist access tag
+ testXml = et.XML('<widget><access origin="*"/></widget>');
+ xml_helpers.mergeXml(testXml, dstXml, '', true);
+ testElements = dstXml.findall('access');
+ expect(testElements.length).toEqual(2);
+
+ });
+ });
});
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org
[3/5] cordova-lib git commit: CB-9597 Initial Implementation of
PlatformApiPoly
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-plugman/util/config-changes.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/util/config-changes.spec.js b/cordova-lib/spec-plugman/util/config-changes.spec.js
index 09bd350..4ffd737 100644
--- a/cordova-lib/spec-plugman/util/config-changes.spec.js
+++ b/cordova-lib/spec-plugman/util/config-changes.spec.js
@@ -44,6 +44,7 @@ var configChanges = require('../../src/plugman/util/config-changes'),
var mungeutil = require('../../src/plugman/util/munge-util');
var PlatformJson = require('../../src/plugman/util/PlatformJson');
var PluginInfoProvider = require('../../src/PluginInfoProvider');
+var PluginInfo = require('../../src/PluginInfo');
// TODO: dont do fs so much
@@ -134,7 +135,7 @@ describe('config-changes module', function() {
var xml;
var dummy_xml = new et.ElementTree(et.XML(fs.readFileSync(path.join(dummyplugin, 'plugin.xml'), 'utf-8')));
var munger = new configChanges.PlatformMunger('android', temp, 'unused', null, pluginInfoProvider);
- var munge = munger.generate_plugin_config_munge(dummyplugin, {});
+ var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(dummyplugin), {});
expect(munge.files['AndroidManifest.xml']).toBeDefined();
expect(munge.files['AndroidManifest.xml'].parents['/manifest/application']).toBeDefined();
xml = (new et.ElementTree(dummy_xml.find('./platform[@name="android"]/config-file[@target="AndroidManifest.xml"]'))).write({xml_declaration:false});
@@ -153,7 +154,7 @@ describe('config-changes module', function() {
});
it('should split out multiple children of config-file elements into individual leaves', function() {
var munger = new configChanges.PlatformMunger('android', temp, 'unused', null, pluginInfoProvider);
- var munge = munger.generate_plugin_config_munge(childrenplugin, {});
+ var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(childrenplugin), {PACKAGE_NAME: 'com.alunny.childapp'});
expect(munge.files['AndroidManifest.xml']).toBeDefined();
expect(munge.files['AndroidManifest.xml'].parents['/manifest']).toBeDefined();
expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />')).toBeDefined();
@@ -168,48 +169,35 @@ describe('config-changes module', function() {
});
it('should not use xml comments as config munge leaves', function() {
var munger = new configChanges.PlatformMunger('android', temp, 'unused', null, pluginInfoProvider);
- var munge = munger.generate_plugin_config_munge(childrenplugin, {});
+ var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(childrenplugin), {});
expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<!--library-->')).not.toBeDefined();
expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<!-- GCM connects to Google Services. -->')).not.toBeDefined();
});
it('should increment config hierarchy leaves if different config-file elements target the same file + selector + xml', function() {
var munger = new configChanges.PlatformMunger('android', temp, 'unused', null, pluginInfoProvider);
- var munge = munger.generate_plugin_config_munge(configplugin, {});
+ var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(configplugin), {});
expect(get_munge_change(munge, 'res/xml/config.xml', '/widget', '<poop />').count).toEqual(2);
});
it('should take into account interpolation variables', function() {
var munger = new configChanges.PlatformMunger('android', temp, 'unused', null, pluginInfoProvider);
- var munge = munger.generate_plugin_config_munge(childrenplugin, {PACKAGE_NAME:'ca.filmaj.plugins'});
+ var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(childrenplugin), {PACKAGE_NAME:'ca.filmaj.plugins'});
expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="ca.filmaj.plugins.permission.C2D_MESSAGE" />')).toBeDefined();
});
it('should create munges for platform-agnostic config.xml changes', function() {
var munger = new configChanges.PlatformMunger('android', temp, 'unused', null, pluginInfoProvider);
- var munge = munger.generate_plugin_config_munge(dummyplugin, {});
+ var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(dummyplugin), {});
expect(get_munge_change(munge, 'config.xml', '/*', '<access origin="build.phonegap.com" />')).toBeDefined();
expect(get_munge_change(munge, 'config.xml', '/*', '<access origin="s3.amazonaws.com" />')).toBeDefined();
});
- it('should automatically add on app java identifier as PACKAGE_NAME variable for android config munges', function() {
- shell.cp('-rf', android_two_project, temp);
- var munger = new configChanges.PlatformMunger('android', temp, 'unused', null, pluginInfoProvider);
- var munge = munger.generate_plugin_config_munge(varplugin, {});
- var expected_xml = '<package>com.alunny.childapp</package>';
- expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', expected_xml)).toBeDefined();
- });
});
describe('for ios projects', function() {
beforeEach(function() {
shell.cp('-rf', ios_config_xml, temp);
});
- it('should automatically add on ios bundle identifier as PACKAGE_NAME variable for ios config munges', function() {
- var munger = new configChanges.PlatformMunger('ios', temp, 'unused', null, pluginInfoProvider);
- var munge = munger.generate_plugin_config_munge(varplugin, {});
- var expected_xml = '<cfbundleid>com.example.friendstring</cfbundleid>';
- expect(get_munge_change(munge, 'config.xml', '/widget', expected_xml)).toBeDefined();
- });
it('should special case framework elements for ios', function() {
var munger = new configChanges.PlatformMunger('ios', temp, 'unused', null, pluginInfoProvider);
- var munge = munger.generate_plugin_config_munge(cbplugin, {});
+ var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(cbplugin), {});
expect(munge.files['framework']).toBeDefined();
expect(get_munge_change(munge, 'framework', 'libsqlite3.dylib', false)).toBeDefined();
expect(get_munge_change(munge, 'framework', 'social.framework', true)).toBeDefined();
@@ -223,11 +211,8 @@ describe('config-changes module', function() {
});
it('should special case config-file elements for windows', function() {
var munger = new configChanges.PlatformMunger('windows', temp, 'unused', null, pluginInfoProvider);
- // Unit testing causes a failure when the package_name function is called from generate_plugin_config_munge
- // the results aren't really important during the unit test
- munger.platform_handler.package_name = function() { return 'org.apache.testapppackage'; };
- var munge = munger.generate_plugin_config_munge(configplugin, {});
+ var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(configplugin), {});
var packageAppxManifest = munge.files['package.appxmanifest'];
var windows80AppxManifest = munge.files['package.windows80.appxmanifest'];
var windows81AppxManifest = munge.files['package.windows.appxmanifest'];
@@ -257,10 +242,10 @@ describe('config-changes module', function() {
shell.cp('-rf', android_two_project, temp);
var platformJson = PlatformJson.load(plugins_dir, 'android');
platformJson.root.prepare_queue.installed = [{'plugin':'org.test.plugins.dummyplugin', 'vars':{}}];
- var munger = new configChanges.PlatformMunger('android', temp, plugins_dir, platformJson, pluginInfoProvider);
+ var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
var spy = spyOn(munger, 'generate_plugin_config_munge').andReturn({});
- munger.process();
- expect(spy).toHaveBeenCalledWith(path.join(plugins_dir, 'org.test.plugins.dummyplugin'), {});
+ munger.process(plugins_dir);
+ expect(spy).toHaveBeenCalledWith(jasmine.any(PluginInfo), {});
});
describe(': installation', function() {
describe('of xml config files', function() {
@@ -273,8 +258,8 @@ describe('config-changes module', function() {
var spy = spyOn(xml_helpers, 'graftXML').andReturn(true);
- var munger = new configChanges.PlatformMunger('android', temp, plugins_dir, platformJson, pluginInfoProvider);
- munger.process();
+ var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+ munger.process(plugins_dir);
expect(spy.calls.length).toEqual(4);
expect(spy.argsForCall[0][2]).toEqual('/*');
expect(spy.argsForCall[1][2]).toEqual('/*');
@@ -287,8 +272,8 @@ describe('config-changes module', function() {
platformJson.addInstalledPluginToPrepareQueue('org.test.configtest', {});
var spy = spyOn(xml_helpers, 'graftXML').andReturn(true);
- var munger = new configChanges.PlatformMunger('android', temp, plugins_dir, platformJson, pluginInfoProvider);
- munger.process();
+ var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+ munger.process(plugins_dir);
expect(spy.calls.length).toEqual(1);
});
it('should not call graftXML for a config munge targeting a config file that does not exist', function() {
@@ -297,8 +282,8 @@ describe('config-changes module', function() {
var spy = spyOn(fs, 'readFileSync').andCallThrough();
- var munger = new configChanges.PlatformMunger('android', temp, plugins_dir, platformJson, pluginInfoProvider);
- munger.process();
+ var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+ munger.process(plugins_dir);
expect(spy).not.toHaveBeenCalledWith(path.join(temp, 'res', 'xml', 'plugins.xml'), 'utf-8');
});
});
@@ -333,8 +318,8 @@ describe('config-changes module', function() {
it('should call into xcode.addFramework if plugin has <framework> file defined and is ios',function() {
var platformJson = PlatformJson.load(plugins_dir, 'ios');
platformJson.addInstalledPluginToPrepareQueue('org.test.plugins.childbrowser', {});
- var munger = new configChanges.PlatformMunger('ios', temp, plugins_dir, platformJson, pluginInfoProvider);
- munger.process();
+ var munger = new configChanges.PlatformMunger('ios', temp, platformJson, pluginInfoProvider);
+ munger.process(plugins_dir);
expect(xcode_add).toHaveBeenCalledWith('libsqlite3.dylib', {weak:false});
expect(xcode_add).toHaveBeenCalledWith('social.framework', {weak:true});
expect(xcode_add).toHaveBeenCalledWith('music.framework', {weak:false});
@@ -348,8 +333,8 @@ describe('config-changes module', function() {
platformJson.addInstalledPluginToPrepareQueue('org.test.plugins.childbrowser', {});
var spy = spyOn(fs, 'readFileSync').andCallThrough();
- var munger = new configChanges.PlatformMunger('ios', temp, plugins_dir, platformJson, pluginInfoProvider);
- munger.process();
+ var munger = new configChanges.PlatformMunger('ios', temp, platformJson, pluginInfoProvider);
+ munger.process(plugins_dir);
expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 'SampleApp-Info.plist').replace(/\\/g, '/'), 'utf8');
});
it('should move successfully installed plugins from queue to installed plugins section, and include/retain vars if applicable', function() {
@@ -358,8 +343,8 @@ describe('config-changes module', function() {
var platformJson = PlatformJson.load(plugins_dir, 'android');
platformJson.addInstalledPluginToPrepareQueue('com.adobe.vars', {'API_KEY':'hi'}, true);
- var munger = new configChanges.PlatformMunger('android', temp, plugins_dir, platformJson, pluginInfoProvider);
- munger.process();
+ var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+ munger.process(plugins_dir);
expect(platformJson.root.prepare_queue.installed.length).toEqual(0);
expect(platformJson.root.installed_plugins['com.adobe.vars']).toBeDefined();
@@ -374,13 +359,13 @@ describe('config-changes module', function() {
// Run through an "install"
var platformJson = PlatformJson.load(plugins_dir, 'android');
platformJson.addInstalledPluginToPrepareQueue('org.test.plugins.dummyplugin', {});
- var munger = new configChanges.PlatformMunger('android', temp, plugins_dir, platformJson, pluginInfoProvider);
- munger.process();
+ var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+ munger.process(plugins_dir);
// Now set up an uninstall and make sure prunexml is called properly
platformJson.addUninstalledPluginToPrepareQueue('org.test.plugins.dummyplugin');
var spy = spyOn(xml_helpers, 'pruneXML').andReturn(true);
- munger.process();
+ munger.process(plugins_dir);
expect(spy.calls.length).toEqual(4);
expect(spy.argsForCall[0][2]).toEqual('/*');
expect(spy.argsForCall[1][2]).toEqual('/*');
@@ -393,15 +378,16 @@ describe('config-changes module', function() {
// Run through an "install"
var platformJson = PlatformJson.load(plugins_dir, 'android');
platformJson.addInstalledPluginToPrepareQueue('com.adobe.vars', {'API_KEY':'canucks'});
- var munger = new configChanges.PlatformMunger('android', temp, plugins_dir, platformJson, pluginInfoProvider);
- munger.process();
+ var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+ munger.process(plugins_dir);
// Now set up an uninstall and make sure prunexml is called properly
platformJson.addUninstalledPluginToPrepareQueue('com.adobe.vars');
var spy = spyOn(munger, 'generate_plugin_config_munge').andReturn({});
- munger.process();
+ munger.process(plugins_dir);
var munge_params = spy.mostRecentCall.args;
- expect(munge_params[0]).toEqual(path.join(plugins_dir, 'com.adobe.vars'));
+ expect(munge_params[0]).toEqual(jasmine.any(PluginInfo));
+ expect(munge_params[0].dir).toEqual(path.join(plugins_dir, 'com.adobe.vars'));
expect(munge_params[1]['API_KEY']).toEqual('canucks');
});
it('should not call pruneXML for a config munge that another plugin depends on', function() {
@@ -413,12 +399,12 @@ describe('config-changes module', function() {
var platformJson = PlatformJson.load(plugins_dir, 'android');
platformJson.addInstalledPluginToPrepareQueue('org.test.multiple-children', {});
platformJson.addInstalledPluginToPrepareQueue('org.test.shareddeps', {});
- var munger = new configChanges.PlatformMunger('android', temp, plugins_dir, platformJson, pluginInfoProvider);
- munger.process();
+ var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+ munger.process(plugins_dir);
// Now set up an uninstall for multi-child plugin
platformJson.addUninstalledPluginToPrepareQueue('org.test.multiple-children');
- munger.process();
+ munger.process(plugins_dir);
munger.save_all();
var am_xml = new et.ElementTree(et.XML(fs.readFileSync(path.join(temp, 'AndroidManifest.xml'), 'utf-8')));
var permission = am_xml.find('./uses-permission');
@@ -430,14 +416,14 @@ describe('config-changes module', function() {
// install a plugin
var platformJson = PlatformJson.load(plugins_dir, 'android');
platformJson.addInstalledPluginToPrepareQueue('org.test.plugins.dummyplugin', {});
- var munger = new configChanges.PlatformMunger('android', temp, plugins_dir, platformJson, pluginInfoProvider);
- munger.process();
+ var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+ munger.process(plugins_dir);
// set up an uninstall for the same plugin
platformJson.addUninstalledPluginToPrepareQueue('org.test.plugins.dummyplugin');
var spy = spyOn(fs, 'readFileSync').andCallThrough();
- munger.process();
+ munger.process(plugins_dir);
expect(spy).not.toHaveBeenCalledWith(path.join(temp, 'res', 'xml', 'plugins.xml'), 'utf-8');
});
@@ -447,12 +433,12 @@ describe('config-changes module', function() {
// install the var plugin
var platformJson = PlatformJson.load(plugins_dir, 'android');
platformJson.addInstalledPluginToPrepareQueue('com.adobe.vars', {'API_KEY':'eat my shorts'});
- var munger = new configChanges.PlatformMunger('android', temp, plugins_dir, platformJson, pluginInfoProvider);
- munger.process();
+ var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+ munger.process(plugins_dir);
// queue up an uninstall for the same plugin
platformJson.addUninstalledPluginToPrepareQueue('com.adobe.vars');
- munger.process();
+ munger.process(plugins_dir);
expect(platformJson.root.prepare_queue.uninstalled.length).toEqual(0);
expect(platformJson.root.installed_plugins['com.adobe.vars']).not.toBeDefined();
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/PluginInfo.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/PluginInfo.js b/cordova-lib/src/PluginInfo.js
index 08b0a97..1802f24 100644
--- a/cordova-lib/src/PluginInfo.js
+++ b/cordova-lib/src/PluginInfo.js
@@ -83,7 +83,11 @@ function PluginInfo(dirname) {
throw new Error(msg);
}
- var asset = { src: src, target: target };
+ var asset = {
+ itemType: 'asset',
+ src: src,
+ target: target
+ };
return asset;
}
@@ -258,6 +262,7 @@ function PluginInfo(dirname) {
function _parseJsModule(tag) {
var ret = {
+ itemType: 'js-module',
name: tag.attrib.name,
src: tag.attrib.src,
clobbers: tag.findall('clobbers').map(function(tag) { return { target: tag.attrib.target }; }),
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/cordova/clean.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/clean.js b/cordova-lib/src/cordova/clean.js
index 8814ff6..59696ed 100644
--- a/cordova-lib/src/cordova/clean.js
+++ b/cordova-lib/src/cordova/clean.js
@@ -17,12 +17,11 @@
under the License.
*/
-var path = require('path'),
- cordova_util = require('./util'),
- HooksRunner = require('../hooks/HooksRunner'),
- events = require('../events'),
- chain = require('../util/promise-util').Q_chainmap,
- superspawn = require('./superspawn');
+var cordova_util = require('./util'),
+ HooksRunner = require('../hooks/HooksRunner'),
+ events = require('../events'),
+ chain = require('../util/promise-util').Q_chainmap,
+ platform_lib = require('../platforms/platforms');
// Returns a promise.
module.exports = function clean(options) {
@@ -34,12 +33,9 @@ module.exports = function clean(options) {
.then(function () {
return chain(options.platforms, function (platform) {
events.emit('verbose', 'Running cleanup for ' + platform + ' platform.');
- var cmd = path.join(projectRoot, 'platforms', platform, 'cordova', 'clean');
- return superspawn.spawn(cmd, options.options, {
- stdio: options.silent ? 'ignore' : 'inherit', // hide script output in silent mode
- printCommand: !!options.verbose, // print command only if --verbose specified
- chmod: true
- });
+ return platform_lib
+ .getPlatformApi(platform)
+ .clean();
});
})
.then(function() {
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/cordova/compile.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/compile.js b/cordova-lib/src/cordova/compile.js
index 3728b67..dbf69ec 100644
--- a/cordova-lib/src/cordova/compile.js
+++ b/cordova-lib/src/cordova/compile.js
@@ -17,12 +17,12 @@
under the License.
*/
-var path = require('path'),
- cordova_util = require('./util'),
- HooksRunner = require('../hooks/HooksRunner'),
- events = require('../events'),
- Q = require('q'),
- superspawn = require('./superspawn');
+var cordova_util = require('./util'),
+ HooksRunner = require('../hooks/HooksRunner'),
+ events = require('../events'),
+ Q = require('q'),
+ promiseUtil = require('../util/promise-util'),
+ platform_lib = require('../platforms/platforms');
// Returns a promise.
module.exports = function compile(options) {
@@ -30,18 +30,17 @@ module.exports = function compile(options) {
options = cordova_util.preProcessOptions(options);
var hooksRunner = new HooksRunner(projectRoot);
- var ret = hooksRunner.fire('before_compile', options);
- options.platforms.forEach(function(platform) {
- ret = ret.then(function() {
- var cmd = path.join(projectRoot, 'platforms', platform, 'cordova', 'build');
- return superspawn.spawn(cmd, options.options, { stdio: 'inherit', printCommand: true, chmod: true });
+ return hooksRunner.fire('before_compile', options)
+ .then(function () {
+ return promiseUtil.Q_chainmap(options.platforms, function (platform) {
+ return platform_lib
+ .getPlatformApi(platform)
+ .build(options.options);
});
- });
- ret = ret.then(function() {
+ }).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);
});
- return ret;
};
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/cordova/emulate.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/emulate.js b/cordova-lib/src/cordova/emulate.js
index 3b09545..67dedeb 100644
--- a/cordova-lib/src/cordova/emulate.js
+++ b/cordova-lib/src/cordova/emulate.js
@@ -17,16 +17,17 @@
under the License.
*/
-var cordova_util = require('./util'),
- path = require('path'),
- HooksRunner = require('../hooks/HooksRunner'),
- superspawn = require('./superspawn'),
- Q = require('q');
+var cordova_util = require('./util'),
+ HooksRunner = require('../hooks/HooksRunner'),
+ Q = require('q'),
+ platform_lib = require('../platforms/platforms');
// 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;
var hooksRunner = new HooksRunner(projectRoot);
return hooksRunner.fire('before_emulate', options)
@@ -36,10 +37,9 @@ module.exports = function emulate(options) {
}).then(function() {
// Deploy in parallel (output gets intermixed though...)
return Q.all(options.platforms.map(function(platform) {
- var cmd = path.join(projectRoot, 'platforms', platform, 'cordova', 'run');
- var args = ['--emulator'].concat(options.options);
-
- return superspawn.spawn(cmd, args, {stdio: 'inherit', printCommand: true, chmod: true});
+ 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/07271a5c/cordova-lib/src/cordova/platform.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/platform.js b/cordova-lib/src/cordova/platform.js
index 4739f80..3e963b0 100644
--- a/cordova-lib/src/cordova/platform.js
+++ b/cordova-lib/src/cordova/platform.js
@@ -33,7 +33,6 @@ var config = require('./config'),
promiseutil = require('../util/promise-util'),
superspawn = require('./superspawn'),
semver = require('semver'),
- unorm = require('unorm'),
shell = require('shelljs'),
_ = require('underscore'),
PlatformJson = require('../plugman/util/PlatformJson'),
@@ -124,59 +123,69 @@ function addHelper(cmd, hooksRunner, projectRoot, targets, opts) {
var platformPath = path.join(projectRoot, 'platforms', platform);
var platformAlreadyAdded = fs.existsSync(platformPath);
- return Q().then(function() {
- if (cmd == 'add') {
- if (platformAlreadyAdded) {
- throw new CordovaError('Platform ' + platform + ' already added.');
- }
-
- // Remove the <platform>.json file from the plugins directory, so we start clean (otherwise we
- // can get into trouble not installing plugins if someone deletes the platform folder but
- // <platform>.json still exists).
- removePlatformPluginsJson(projectRoot, target);
-
- var template_dir = config_json && config_json.lib && config_json.lib[platform] && config_json.lib[platform].template || null;
- events.emit('log', 'Adding ' + platform + ' project...');
-
- return getCreateArgs(platDetails, projectRoot, cfg, template_dir, opts);
- } else if (cmd == 'update') {
- if (!platformAlreadyAdded) {
- throw new CordovaError('Platform "' + platform + '" is not yet added. See `' +
- cordova_util.binname + ' platform list`.');
- }
- events.emit('log', 'Updating ' + platform + ' project...');
-
- // CB-6976 Windows Universal Apps. Special case to upgrade from windows8 to windows platform
- if (platform == 'windows8' && !fs.existsSync(path.join(projectRoot, 'platforms', 'windows'))) {
- var platformPathWindows = path.join(projectRoot, 'platforms', 'windows');
- fs.renameSync(platformPath, platformPathWindows);
- platform = 'windows';
- platformPath = platformPathWindows;
- }
- // Call the platform's update script.
- var args = [platformPath];
- if (opts.link) {
- args.push('--link');
- }
- return args;
+ if (cmd == 'add') {
+ if (platformAlreadyAdded) {
+ throw new CordovaError('Platform ' + platform + ' already added.');
}
- }).then(function(args) {
- var bin = path.join(platDetails.libDir, 'bin', cmd == 'add' ? 'create' : 'update');
- var copts = { stdio: 'inherit', chmod: true };
- if ('spawnoutput' in opts) {
- copts = { stdio: opts.spawnoutput };
+
+ // Remove the <platform>.json file from the plugins directory, so we start clean (otherwise we
+ // can get into trouble not installing plugins if someone deletes the platform folder but
+ // <platform>.json still exists).
+ removePlatformPluginsJson(projectRoot, target);
+ } else if (cmd == 'update') {
+ if (!platformAlreadyAdded) {
+ throw new CordovaError('Platform "' + platform + '" is not yet added. See `' +
+ cordova_util.binname + ' platform list`.');
}
- return superspawn.spawn(bin, args, copts);
- }).then(function() {
- var platform_www = path.join(projectRoot, 'platforms', platform, 'platform_www');
- copy_cordova_js(projectRoot, platform);
+ // CB-6976 Windows Universal Apps. Special case to upgrade from windows8 to windows platform
+ if (platform == 'windows8' && !fs.existsSync(path.join(projectRoot, 'platforms', 'windows'))) {
+ var platformPathWindows = path.join(projectRoot, 'platforms', 'windows');
+ fs.renameSync(platformPath, platformPathWindows);
+ platform = 'windows';
+ platformPath = platformPathWindows;
+ }
+ }
- // only want to copy cordova-js-src once, when the platform is added
- if (!fs.existsSync(path.join(platform_www, 'cordova-js-src'))) {
- copy_cordovajs_src(projectRoot, platform, platDetails.libDir);
+ var cordovaProject = {
+ root: projectRoot,
+ projectConfig: cfg,
+ locations: {
+ www: path.join(projectRoot, 'www'),
+ platforms: path.join(projectRoot, 'platforms'),
+ configXml: path.join(projectRoot, 'config.xml')
}
- }).then(function () {
+ };
+
+ var options = {
+ // We need to pass a platformDetails into update/create
+ // since PlatformApiPoly needs to know something about
+ // platform, it is going to create.
+ platformDetails: platDetails,
+ link: opts.link
+ };
+
+ if (config_json && config_json.lib && config_json.lib[platform] &&
+ config_json.lib[platform].template) {
+ options.customTemplate = config_json.lib[platform].template;
+ }
+
+ events.emit('log', (cmd === 'add' ? 'Adding ' : 'Updating ') + platform + ' project...');
+
+ var PlatformApi;
+ try {
+ // Try to get PlatformApi class from platform
+ PlatformApi = require(path.resolve(platDetails.libDir, 'bin/PlatformApi'));
+ } catch (err) {
+ PlatformApi = require('../platforms/PlatformApiPoly');
+ }
+
+ var promise = cmd === 'add' ?
+ PlatformApi.createPlatform :
+ PlatformApi.updatePlatform;
+
+ return promise(cordovaProject, options)
+ .then(function () {
// Call prepare for the current platform.
var prepOpts = {
platforms :[platform],
@@ -597,37 +606,6 @@ function hostSupports(platform) {
return false;
}
-// Returns a promise.
-function getCreateArgs(platDetails, projectRoot, cfg, template_dir, opts) {
- var output = path.join(projectRoot, 'platforms', platDetails.platform);
-
- var args = [];
- if (/android|ios/.exec(platDetails.platform) && semver.gt(platDetails.version, '3.3.0')) {
- args.push('--cli');
- }
-
- var pkg = cfg.packageName().replace(/[^\w.]/g,'_');
- // CB-6992 it is necessary to normalize characters
- // because node and shell scripts handles unicode symbols differently
- // We need to normalize the name to NFD form since iOS uses NFD unicode form
- var name = platDetails.platform == 'ios' ? unorm.nfd(cfg.name()) : cfg.name();
- args.push(output, pkg, name);
-
- var activityName = cfg.android_activityName();
- if (activityName && platDetails.platform === 'android' && semver.gte(platDetails.version, '4.0.0-dev')) {
- activityName = activityName.replace(/\W/g, '');
- args.push('--activity-name', activityName);
- }
-
- if (template_dir) {
- args.push(template_dir);
- }
- if (opts.link) {
- args.push('--link');
- }
- return args;
-}
-
function installPluginsForNewPlatform(platform, projectRoot, opts) {
// Install all currently installed plugins into this new platform.
var plugins_dir = path.join(projectRoot, 'plugins');
@@ -669,29 +647,6 @@ function installPluginsForNewPlatform(platform, projectRoot, opts) {
}, Q());
}
-// Copy the cordova.js file to platforms/<platform>/platform_www/
-// The www dir is nuked on each prepare so we keep cordova.js in platform_www
-function copy_cordova_js(projectRoot, platform) {
- var platformPath = path.join(projectRoot, 'platforms', platform);
- var parser = platforms.getPlatformProject(platform, platformPath);
- var platform_www = path.join(platformPath, 'platform_www');
- shell.mkdir('-p', platform_www);
- shell.cp('-f', path.join(parser.www_dir(), 'cordova.js'), path.join(platform_www, 'cordova.js'));
-}
-
-// Copy cordova-js-src directory into platform_www directory.
-// We need these files to build cordova.js if using browserify method.
-function copy_cordovajs_src(projectRoot, platform, platLib) {
- var platformPath = path.join(projectRoot, 'platforms', platform);
- var parser = platforms.getPlatformProject(platform, platformPath);
- var platform_www = path.join(platformPath, 'platform_www');
- var cordovaJsSrcPath = parser.cordovajs_src_path(platLib);
- //only exists for platforms that have shipped cordova-js-src directory
- if(fs.existsSync(cordovaJsSrcPath)) {
- shell.cp('-rf', cordovaJsSrcPath, platform_www);
- }
-}
-
// Remove <platform>.json file from plugins directory.
function removePlatformPluginsJson(projectRoot, target) {
var plugins_json = path.join(projectRoot, 'plugins', target + '.json');
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/cordova/plugin.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/plugin.js b/cordova-lib/src/cordova/plugin.js
index 0f90de2..f49205a 100644
--- a/cordova-lib/src/cordova/plugin.js
+++ b/cordova-lib/src/cordova/plugin.js
@@ -30,7 +30,8 @@ var cordova_util = require('./util'),
plugman = require('../plugman/plugman'),
pluginMapper = require('cordova-registry-mapper').newToOld,
events = require('../events'),
- metadata = require('../plugman/util/metadata');
+ metadata = require('../plugman/util/metadata'),
+ chainMap = require('../util/promise-util').Q_chainmap;
// Returns a promise.
module.exports = function plugin(command, targets, opts) {
@@ -134,14 +135,23 @@ module.exports = function plugin(command, targets, opts) {
// Fetch the plugin first.
events.emit('verbose', 'Calling plugman.fetch on plugin "' + target + '"');
- return plugman.raw.fetch(target, pluginPath, { searchpath: searchPath, noregistry: opts.noregistry, link: opts.link,
- pluginInfoProvider: pluginInfoProvider, variables: opts.cli_variables,
- is_top_level: true });
+ var fetchOptions = {
+ searchpath: searchPath,
+ noregistry: opts.noregistry,
+ 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(dir){
+ .then(function(pluginInfo){
// save to config.xml
- if(saveToConfigXmlOn(config_json,opts)){
- var pluginInfo = pluginInfoProvider.get(dir);
+ if(saveToConfigXmlOn(config_json, opts)){
var attributes = {};
attributes.name = pluginInfo.id;
@@ -149,77 +159,48 @@ module.exports = function plugin(command, targets, opts) {
var src = parseSource(target, opts);
attributes.spec = src ? src : '~' + pluginInfo.version;
- var variables = [];
- if (opts.cli_variables) {
- for (var varname in opts.cli_variables) {
- if (opts.cli_variables.hasOwnProperty(varname)) {
- variables.push({name: varname, value: opts.cli_variables[varname]});
- }
- }
- }
+ var variables = Object.keys(opts.cli_variables || [])
+ .map(function (variableName) {
+ return {name: variableName, value: opts.cli_variables[variableName]};
+ });
+
cfg.removePlugin(pluginInfo.id);
cfg.addPlugin(attributes, variables);
cfg.write();
events.emit('results', 'Saved plugin info for "' + pluginInfo.id + '" to config.xml');
}
- return dir;
+ return pluginInfo;
})
- .then(function(dir) {
+ .then(function(pluginInfo) {
// Validate top-level required variables
- var pluginVariables = pluginInfoProvider.get(dir).getPreferences();
- var requiredVariables = [];
-
- for(var i in pluginVariables) {
- var v = pluginVariables[i];
+ var pluginVariables = pluginInfo.getPreferences();
+ var missingVariables = Object.keys(pluginVariables)
+ .filter(function (variableName) {
// discard variables with default value
- if (!v) {
- requiredVariables.push(i);
- }
- }
-
- opts.cli_variables = opts.cli_variables || {};
- var missingVariables = requiredVariables.filter(function (v) {
- return !(v in opts.cli_variables);
+ return !(pluginVariables[variableName] || opts.cli_variables[variableName]);
});
if (missingVariables.length) {
- shell.rm('-rf', dir);
+ shell.rm('-rf', pluginInfo.dir);
var msg = 'Variable(s) missing (use: --variable ' + missingVariables.join('=value --variable ') + '=value).';
return Q.reject(new CordovaError(msg));
}
+
// Iterate (in serial!) over all platforms in the project and install the plugin.
- return platformList.reduce(function(soFar, platform) {
- return soFar.then(function() {
- 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
- },
- tokens,
- key,
- i;
-
- // TODO: Remove this. CLI vars are passed as part of the opts object after "nopt" refactoring.
- // Keeping for now for compatibility for API users.
- //parse variables into cli_variables
- for (i=0; i< opts.options.length; i++) {
- if (opts.options[i] === '--variable' && typeof opts.options[++i] === 'string') {
- tokens = opts.options[i].split('=');
- key = tokens.shift().toUpperCase();
- if (/^[\w-_]+$/.test(key)) {
- options.cli_variables[key] = tokens.join('=');
- }
- }
- }
-
- events.emit('verbose', 'Calling plugman.install on plugin "' + dir + '" for platform "' + platform + '" with options "' + JSON.stringify(options) + '"');
- return plugman.raw.install(platform, platformRoot, path.basename(dir), pluginPath, options);
- });
- }, Q());
+ 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
+ };
+
+ 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);
+ });
});
}, Q()); // end Q.all
}).then(function() {
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/cordova/prepare.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/prepare.js b/cordova-lib/src/cordova/prepare.js
index 9e27833..4125bb3 100644
--- a/cordova-lib/src/cordova/prepare.js
+++ b/cordova-lib/src/cordova/prepare.js
@@ -19,201 +19,64 @@
var cordova_util = require('./util'),
ConfigParser = require('../configparser/ConfigParser'),
- path = require('path'),
platforms = require('../platforms/platforms'),
- fs = require('fs'),
- shell = require('shelljs'),
- et = require('elementtree'),
HooksRunner = require('../hooks/HooksRunner'),
- events = require('../events'),
Q = require('q'),
- plugman = require('../plugman/plugman'),
- PlatformMunger = require('../plugman/util/config-changes').PlatformMunger,
- PlatformJson = require('../plugman/util/PlatformJson'),
restore = require('./restore-util'),
+ path = require('path'),
+ browserify = require('../plugman/browserify'),
config = require('./config');
-
-var PluginInfoProvider = require('../PluginInfoProvider');
-
// Returns a promise.
exports = module.exports = prepare;
function prepare(options) {
var projectRoot = cordova_util.cdProjectRoot();
- var xml = cordova_util.projectConfig(projectRoot);
var config_json = config.read(projectRoot);
-
- if (!options) {
- options = {
- verbose: false,
- platforms: [],
- options: []
- };
- }
-
- options.searchpath = options.searchpath || config_json.plugin_search_path;
+ options = options || { verbose: false, platforms: [], options: [] };
var hooksRunner = new HooksRunner(projectRoot);
return hooksRunner.fire('before_prepare', options)
.then(function(){
- return restore.installPlatformsFromConfigXML(options.platforms);
- })
- .then(function(){
- options = cordova_util.preProcessOptions(options);
- var paths = options.platforms.map(function(p) {
- var platform_path = path.join(projectRoot, 'platforms', p);
- var parser = platforms.getPlatformProject(p, platform_path);
- return parser.www_dir();
- });
- options.paths = paths;
+ var platformsToRestore = options && options.platforms || [];
+ return restore.installPlatformsFromConfigXML(platformsToRestore);
})
.then(function() {
- var pluginInfoProvider = new PluginInfoProvider();
-
+ options = cordova_util.preProcessOptions(options);
+ options.searchpath = options.searchpath || config_json.plugin_search_path;
// Iterate over each added platform
return Q.all(options.platforms.map(function(platform) {
- var platformPath = path.join(projectRoot, 'platforms', platform);
-
- var parser = platforms.getPlatformProject(platform, platformPath);
- var defaults_xml_path = path.join(platformPath, 'cordova', 'defaults.xml');
- // If defaults.xml is present, overwrite platform config.xml with
- // it Otherwise save whatever is there as defaults so it can be
- // restored or copy project config into platform if none exists.
- if (fs.existsSync(defaults_xml_path)) {
- shell.cp('-f', defaults_xml_path, parser.config_xml());
- events.emit('verbose', 'Generating config.xml from defaults for platform "' + platform + '"');
- } else {
- if(fs.existsSync(parser.config_xml())){
- shell.cp('-f', parser.config_xml(), defaults_xml_path);
- }else{
- shell.cp('-f', xml, parser.config_xml());
+ // TODO: this need to be replaced by real projectInfo
+ // instance for current project.
+ var project = {
+ root: projectRoot,
+ projectConfig: new ConfigParser(cordova_util.projectConfig(projectRoot)),
+ locations: {
+ plugins: path.join(projectRoot, 'plugins'),
+ www: cordova_util.projectWww(projectRoot)
}
- }
-
- var stagingPath = path.join(platformPath, '.staging');
- if (fs.existsSync(stagingPath)) {
- events.emit('log', 'Deleting now-obsolete intermediate directory: ' + stagingPath);
- shell.rm('-rf', stagingPath);
- }
-
- // Replace the existing web assets with the app master versions
- parser.update_www();
-
- // Call plugman --prepare for this platform. sets up js-modules appropriately.
- var plugins_dir = path.join(projectRoot, 'plugins');
- events.emit('verbose', 'Calling plugman.prepare for platform "' + platform + '"');
-
- if (options.browserify) {
- plugman.prepare = require('../plugman/prepare-browserify');
- }
-
- return plugman.prepare(platformPath, platform, plugins_dir, null, true, pluginInfoProvider)
+ };
+
+ // platformApi prepare takes care of all functionality
+ // which previously had been executed by cordova.prepare:
+ // - reset config.xml and then merge changes from project's one,
+ // - update www directory from project's one and merge assets from platform_www,
+ // - reapply config changes, made by plugins,
+ // - update platform's project
+ // Please note that plugins' changes, such as installes js files, assets and
+ // config changes is not being reinstalled on each prepare.
+ var platformApi = platforms.getPlatformApi(platform);
+ return platformApi.prepare(project)
.then(function () {
- // Remove cordova-js-src from application www directory
- // otherwise it will be included into resultant app bundle
- var cordovaJsSrcPath = path.join(platformPath, 'www/cordova-js-src');
- if(fs.existsSync(cordovaJsSrcPath)) {
- shell.rm('-rf', cordovaJsSrcPath);
- }
- }).then(function () {
- // Make sure that config changes for each existing plugin is in place
- var platformJson = PlatformJson.load(plugins_dir, platform);
- var munger = new PlatformMunger(platform, platformPath, plugins_dir, platformJson, pluginInfoProvider);
- munger.reapply_global_munge();
- munger.save_all();
-
- // Update platform config.xml based on top level config.xml
- var cfg = new ConfigParser(xml);
- var platform_cfg = new ConfigParser(parser.config_xml());
- exports._mergeXml(cfg.doc.getroot(), platform_cfg.doc.getroot(), platform, true);
-
- // CB-6976 Windows Universal Apps. For smooth transition and to prevent mass api failures
- // we allow using windows8 tag for new windows platform
- if (platform == 'windows') {
- exports._mergeXml(cfg.doc.getroot(), platform_cfg.doc.getroot(), 'windows8', true);
- }
-
- platform_cfg.write();
-
- return parser.update_project(cfg);
+ if (options.browserify)
+ return browserify(project, platformApi);
});
- })).then(function() {
- return hooksRunner.fire('after_prepare', 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);
});
}
-
-var BLACKLIST = ['platform', 'feature','plugin','engine'];
-var SINGLETONS = ['content', 'author'];
-function mergeXml(src, dest, platform, clobber) {
- // Do nothing for blacklisted tags.
- if (BLACKLIST.indexOf(src.tag) != -1) return;
-
- //Handle attributes
- Object.getOwnPropertyNames(src.attrib).forEach(function (attribute) {
- if (clobber || !dest.attrib[attribute]) {
- dest.attrib[attribute] = src.attrib[attribute];
- }
- });
- //Handle text
- if (src.text && (clobber || !dest.text)) {
- dest.text = src.text;
- }
- //Handle platform
- if (platform) {
- src.findall('platform[@name="' + platform + '"]').forEach(function (platformElement) {
- platformElement.getchildren().forEach(mergeChild);
- });
- }
-
- //Handle children
- src.getchildren().forEach(mergeChild);
-
- function mergeChild (srcChild) {
- var srcTag = srcChild.tag,
- destChild = new et.Element(srcTag),
- foundChild,
- query = srcTag + '',
- shouldMerge = true;
-
- if (BLACKLIST.indexOf(srcTag) === -1) {
- if (SINGLETONS.indexOf(srcTag) !== -1) {
- foundChild = dest.find(query);
- if (foundChild) {
- destChild = foundChild;
- dest.remove(destChild);
- }
- } else {
- //Check for an exact match and if you find one don't add
- Object.getOwnPropertyNames(srcChild.attrib).forEach(function (attribute) {
- query += '[@' + attribute + '="' + srcChild.attrib[attribute] + '"]';
- });
- var foundChildren = dest.findall(query);
- for(var i = 0; i < foundChildren.length; i++) {
- foundChild = foundChildren[i];
- if (foundChild && textMatch(srcChild, foundChild) && (Object.keys(srcChild.attrib).length==Object.keys(foundChild.attrib).length)) {
- destChild = foundChild;
- dest.remove(destChild);
- shouldMerge = false;
- break;
- }
- }
- }
-
- mergeXml(srcChild, destChild, platform, clobber && shouldMerge);
- dest.append(destChild);
- }
- }
-}
-
-// Expose for testing.
-exports._mergeXml = mergeXml;
-
-
-function textMatch(elm1, elm2) {
- var text1 = elm1.text ? elm1.text.replace(/\s+/, '') : '',
- text2 = elm2.text ? elm2.text.replace(/\s+/, '') : '';
- return (text1 === '' || text1 === text2);
-}
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/cordova/requirements.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/requirements.js b/cordova-lib/src/cordova/requirements.js
index 46a7284..a0fa79b 100644
--- a/cordova-lib/src/cordova/requirements.js
+++ b/cordova-lib/src/cordova/requirements.js
@@ -18,51 +18,31 @@
*/
var cordova_util = require('./util');
-var events = require('../events');
-var path = require('path');
var Q = require('q');
var CordovaError = require('../CordovaError');
+var knownPlatforms = require('../platforms/platforms');
/**
* Runs requirements check against platforms specified in 'platfoms' argument
*
- * @param {String[]} platforms List of platforms for requirements check. If none, all
- * platforms, added to project will be checked
+ * @param {String[]} platforms List of platforms for requirements check. If
+ * none, all platforms, added to project will be checked
*
- * @return {Promise} Promise fullfilled with map of platforms and requirements
- * check results for each platform
+ * @return {Promise<Object>} Promise fullfilled with map of platforms and
+ * requirements check results for each platform.
*/
module.exports = function check_reqs(platforms) {
platforms = cordova_util.preProcessOptions(platforms).platforms;
- var projectRoot = cordova_util.isCordova();
- var platformsDir = path.join(projectRoot, 'platforms');
- var platformChecks = platforms.map(function (platform) {
- var modulePath = path.join(platformsDir, platform, 'cordova', 'lib', 'check_reqs');
- try {
- events.emit('verbose', 'Checking requirements for ' + platform + ' platform');
- return require(modulePath).check_all();
- } catch (e) {
- var errorMsg = 'Failed to check requirements for ' + platform + ' platform. ' +
- 'check_reqs module is missing for platform. Skipping it...';
- return Q.reject(errorMsg);
- }
- });
-
- var checks = {};
-
- return Q.allSettled(platformChecks)
+ return Q.allSettled(platforms.map(function (platform) {
+ return knownPlatforms.getPlatformApi(platform).requirements();
+ }))
.then(function (settledChecks) {
-
- settledChecks.forEach(function (settledCheck, idx) {
+ return settledChecks.reduce(function (result, settledCheck, idx) {
var platformName = platforms[idx];
- var result = settledCheck.state === 'fulfilled' ?
+ result[platformName] = settledCheck.state === 'fulfilled' ?
settledCheck.value :
new CordovaError(settledCheck.reason);
-
- checks[platformName] = result;
- });
-
- return checks;
+ }, {});
});
};
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/cordova/run.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/run.js b/cordova-lib/src/cordova/run.js
index b5c1e27..b739580 100644
--- a/cordova-lib/src/cordova/run.js
+++ b/cordova-lib/src/cordova/run.js
@@ -17,12 +17,12 @@
under the License.
*/
-var cordova_util = require('./util'),
- path = require('path'),
- HooksRunner = require('../hooks/HooksRunner'),
- events = require('../events'),
- superspawn = require('./superspawn'),
- Q = require('q');
+var cordova_util = require('./util'),
+ HooksRunner = require('../hooks/HooksRunner'),
+ events = require('../events'),
+ Q = require('q'),
+ platform_lib = require('../platforms/platforms');
+
// Returns a promise.
module.exports = function run(options) {
@@ -37,8 +37,9 @@ module.exports = function run(options) {
}).then(function() {
// Deploy in parallel (output gets intermixed though...)
return Q.all(options.platforms.map(function(platform) {
- var cmd = path.join(projectRoot, 'platforms', platform, 'cordova', 'run');
- return superspawn.spawn(cmd, options.options, { printCommand: true, stdio: 'inherit', chmod: true });
+ return platform_lib
+ .getPlatformApi(platform)
+ .run(options.options);
}));
}).then(function() {
return hooksRunner.fire('after_run', options);
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/cordova/serve.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/serve.js b/cordova-lib/src/cordova/serve.js
index a187bb8..274f8e0 100644
--- a/cordova-lib/src/cordova/serve.js
+++ b/cordova-lib/src/cordova/serve.js
@@ -63,7 +63,6 @@ function processUrlPath(urlPath, request, response, do302, do404, serveFile) {
}
var firstSegment = /\/(.*?)\//.exec(urlPath);
- var parser;
if (!firstSegment) {
doRoot();
@@ -77,8 +76,9 @@ function processUrlPath(urlPath, request, response, do302, do404, serveFile) {
// Strip the platform out of the path.
urlPath = urlPath.slice(platformId.length + 1);
+ var platformApi;
try {
- parser = platforms.getPlatformProject(platformId, path.join(projectRoot, 'platforms', platformId));
+ platformApi = platforms.getPlatformApi(platformId);
} catch (e) {
do404();
return;
@@ -87,12 +87,12 @@ function processUrlPath(urlPath, request, response, do302, do404, serveFile) {
var filePath = null;
if (urlPath == '/config.xml') {
- filePath = parser.config_xml();
+ filePath = platformApi.getPlatformInfo().configXml;
} else if (urlPath == '/project.json') {
- processAddRequest(request, response, platformId, projectRoot);
+ processAddRequest(request, response, platformApi);
return;
} else if (/^\/www\//.test(urlPath)) {
- filePath = path.join(parser.www_dir(), urlPath.slice(5));
+ filePath = path.join(platformApi.getPlatformInfo().locations.www, urlPath.slice(5));
} else if (/^\/+[^\/]*$/.test(urlPath)) {
do302('/' + platformId + '/www/');
return;
@@ -125,12 +125,11 @@ function calculateMd5(fileName) {
return md5sum.digest('hex');
}
-function processAddRequest(request, response, platformId, projectRoot) {
- var parser = platforms.getPlatformProject(platformId, path.join(projectRoot, 'platforms', platformId));
- var wwwDir = parser.www_dir();
+function processAddRequest(request, response, platformApi) {
+ var wwwDir = platformApi.getPlatformInfo().locations.www;
var payload = {
- 'configPath': '/' + platformId + '/config.xml',
- 'wwwPath': '/' + platformId + '/www',
+ 'configPath': '/' + platformApi.platform + '/config.xml',
+ 'wwwPath': '/' + platformApi.platform + '/www',
'wwwFileList': shell.find(wwwDir)
.filter(function(a) { return !fs.statSync(a).isDirectory() && !/(^\.)|(\/\.)/.test(a); })
.map(function(a) { return {'path': a.slice(wwwDir.length), 'etag': '' + calculateMd5(a)}; })
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/cordova/targets.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/targets.js b/cordova-lib/src/cordova/targets.js
index ed0d40b..2f5566e 100644
--- a/cordova-lib/src/cordova/targets.js
+++ b/cordova-lib/src/cordova/targets.js
@@ -49,14 +49,11 @@ module.exports = function targets(options) {
var projectRoot = cordova_util.cdProjectRoot();
options = cordova_util.preProcessOptions(options);
- // Remove --list from parameters
- options.options.splice(options.options.indexOf('--list'), 1);
-
var result = Q();
options.platforms.forEach(function(platform) {
- if (options.options.indexOf('--device') >= 0) {
+ if (options.options.device) {
result = result.then(displayDevices.bind(null, projectRoot, platform, options.options));
- } else if(options.options.indexOf('--emulator') >= 0) {
+ } else if(options.options.emulator) {
result = result.then(displayVirtualDevices.bind(null, projectRoot, platform, options.options));
} else {
result = result.then(displayDevices.bind(null, projectRoot, platform, options.options))
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/src/cordova/util.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/util.js b/cordova-lib/src/cordova/util.js
index 0231ec0..c177689 100644
--- a/cordova-lib/src/cordova/util.js
+++ b/cordova-lib/src/cordova/util.js
@@ -233,7 +233,7 @@ function preProcessOptions (inputOptions) {
}
result.verbose = result.verbose || false;
result.platforms = result.platforms || [];
- result.options = result.options || [];
+ result.options = result.options || {};
var projectRoot = this.isCordova();
@@ -248,11 +248,8 @@ function preProcessOptions (inputOptions) {
result.platforms = projectPlatforms;
}
- var buildConfigFound = result.options.some(function (option) {
- return option.indexOf('--buildConfig') === 0;
- });
- if (!buildConfigFound && fs.existsSync(path.join(projectRoot, 'build.json'))) {
- result.options.push('--buildConfig=' + path.join(projectRoot, 'build.json'));
+ if (!result.options.buildConfig && fs.existsSync(path.join(projectRoot, 'build.json'))) {
+ result.options.buildConfig = path.join(projectRoot, 'build.json');
}
return result;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org
[4/5] cordova-lib git commit: CB-9597 Initial Implementation of
PlatformApiPoly
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-plugman/install-browserify.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/install-browserify.spec.js b/cordova-lib/spec-plugman/install-browserify.spec.js
deleted file mode 100644
index 6d94eee..0000000
--- a/cordova-lib/spec-plugman/install-browserify.spec.js
+++ /dev/null
@@ -1,519 +0,0 @@
-// /**
-// 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.
-// */
-
-/* jshint sub:true */
-
-var install = require('../src/plugman/install'),
- actions = require('../src/plugman/util/action-stack'),
- PlatformJson = require('../src/plugman/util/PlatformJson'),
- events = require('../src/events'),
- plugman = require('../src/plugman/plugman'),
- platforms = require('../src/plugman/platforms/common'),
- common = require('./common'),
- fs = require('fs'),
- os = require('os'),
- path = require('path'),
- shell = require('shelljs'),
- child_process = require('child_process'),
- semver = require('semver'),
- Q = require('q'),
- spec = __dirname,
- done = false,
- srcProject = path.join(spec, 'projects', 'android_install'),
- temp_dir = path.join(os.tmpdir(), 'plugman-test'),
- project = path.join(temp_dir, 'android_install'),
- plugins_dir = path.join(spec, 'plugins'),
- plugins_install_dir = path.join(project, 'cordova', 'plugins'),
- plugins = {
- 'org.test.plugins.dummyplugin' : path.join(plugins_dir, 'org.test.plugins.dummyplugin'),
- 'com.cordova.engine' : path.join(plugins_dir, 'com.cordova.engine'),
- 'com.cordova.engine-android' : path.join(plugins_dir, 'com.cordova.engine-android'),
- 'org.test.plugins.childbrowser' : path.join(plugins_dir, 'org.test.plugins.childbrowser'),
- 'com.adobe.vars' : path.join(plugins_dir, 'com.adobe.vars'),
- 'org.test.defaultvariables' : path.join(plugins_dir, 'org.test.defaultvariables'),
- 'A' : path.join(plugins_dir, 'dependencies', 'A'),
- 'B' : path.join(plugins_dir, 'dependencies', 'B'),
- 'C' : path.join(plugins_dir, 'dependencies', 'C'),
- 'F' : path.join(plugins_dir, 'dependencies', 'F'),
- 'G' : path.join(plugins_dir, 'dependencies', 'G')
- },
- promise,
- results = {},
- dummy_id = 'org.test.plugins.dummyplugin',
- superspawn = require('../src/cordova/superspawn');
-
-
-// Pre-crete the temp dir, without it the test fails.
-shell.mkdir('-p', temp_dir);
-
-function installPromise(f) {
- f.then(function(res) { done = true; }, function(err) { done = err; });
-}
-
-var existsSync = fs.existsSync;
-
-// Mocked functions for tests
-var fake = {
- 'existsSync' : {
- 'noPlugins' : function(path){
- // fake installed plugin directories as 'not found'
- if( path.slice(-5) !== '.json' && path.indexOf(plugins_install_dir) >= 0) {
- return false;
- }
-
- return existsSync(path);
- }
- },
- 'fetch' : {
- 'dependencies' : function(id, dir) {
- if(id == plugins['A'])
- return Q(id); // full path to plugin
-
- return Q( path.join(plugins_dir, 'dependencies', id) );
- }
- }
-};
-
-describe('start', function() {
- var prepare, prepareBrowserify, config_queue_add, proc, actions_push, ca, emit;
-
- beforeEach(function() {
- prepare = spyOn(plugman, 'prepare');
- prepareBrowserify = spyOn(plugman, 'prepareBrowserify');
- config_queue_add = spyOn(PlatformJson.prototype, 'addInstalledPluginToPrepareQueue');
- proc = spyOn(actions.prototype, 'process').andReturn( Q(true) );
- actions_push = spyOn(actions.prototype, 'push');
- ca = spyOn(actions.prototype, 'createAction');
- });
- it('start', function() {
- shell.rm('-rf', project);
- shell.cp('-R', path.join(srcProject, '*'), project);
-
- done = false;
- promise = Q()
- .then(
- function(){ return install('android', project, plugins['org.test.plugins.dummyplugin'], plugins_install_dir, { browserify: true }); }
- ).then(
- function(){
- results['actions_callCount'] = actions_push.callCount;
- results['actions_create'] = ca.argsForCall[0];
- results['config_add'] = config_queue_add.argsForCall[0];
-
- return Q();
- }
- ).then(
- function(){
- return install('android', project, plugins['com.cordova.engine'], plugins_install_dir, { browserify: true }); }
- ).then(
- function(){
- emit = spyOn(events, 'emit');
- return install('android', project, plugins['org.test.plugins.childbrowser'], plugins_install_dir, { browserify: true });
- }
- ).then(
- function(){
- return install('android', project, plugins['com.adobe.vars'], plugins_install_dir, { browserify: true, cli_variables:{API_KEY:'batman'} });
- }
- ).then(
- function(){
- done = true;
- results['prepareCount'] = prepareBrowserify.callCount;
- results['emit_results'] = [];
-
- for(var i in emit.calls) {
- if(emit.calls[i].args[0] === 'results')
- results['emit_results'].push(emit.calls[i].args[1]);
- }
-
- events.emit('verbose', '***** DONE START *****');
- }
- ).fail(
- function(error) {
- expect(error).toEqual({});
- }
- );
- waitsFor(function() { return done; }, 'promise never resolved', 2000);
- });
-});
-
-describe('install', function() {
- var chmod, exec, add_to_queue, prepare, cp, rm, fetchSpy;
- var spawnSpy;
-
- beforeEach(function() {
- prepare = spyOn(plugman, 'prepare').andReturn( Q(true) );
- spyOn(plugman, 'prepareBrowserify');
- exec = spyOn(child_process, 'exec').andCallFake(function(cmd, cb) {
- cb(false, '', '');
- });
- spawnSpy = spyOn(superspawn, 'spawn').andReturn(Q('3.1.0'));
- spyOn(fs, 'mkdirSync').andReturn(true);
- spyOn(shell, 'mkdir').andReturn(true);
- spyOn(platforms, 'copyFile').andReturn(true);
-
- fetchSpy = spyOn(plugman.raw, 'fetch').andReturn( Q( plugins['com.cordova.engine'] ) );
- chmod = spyOn(fs, 'chmodSync').andReturn(true);
- spyOn(fs, 'writeFileSync').andReturn(true);
- cp = spyOn(shell, 'cp').andReturn(true);
- rm = spyOn(shell, 'rm').andReturn(true);
- add_to_queue = spyOn(PlatformJson.prototype, 'addInstalledPluginToPrepareQueue');
- done = false;
- });
-
- describe('success', function() {
- it('should call prepare after a successful install', function() {
- expect(results['prepareCount']).toBe(4);
- });
-
- it('should emit a results event with platform-agnostic <info>', function() {
- // org.test.plugins.childbrowser
- expect(results['emit_results'][0]).toBe('No matter what platform you are installing to, this notice is very important.');
- });
- it('should emit a results event with platform-specific <info>', function() {
- // org.test.plugins.childbrowser
- expect(results['emit_results'][1]).toBe('Please make sure you read this because it is very important to complete the installation of your plugin.');
- });
- it('should interpolate variables into <info> tags', function() {
- // VariableBrowser
- expect(results['emit_results'][2]).toBe('Remember that your api key is batman!');
- });
-
- it('should call fetch if provided plugin cannot be resolved locally', function() {
- fetchSpy.andReturn( Q( plugins['org.test.plugins.dummyplugin'] ) );
- spyOn(fs, 'existsSync').andCallFake( fake['existsSync']['noPlugins'] );
-
- runs(function() {
- installPromise(install('android', project, 'CLEANYOURSHORTS', plugins_dir, { browserify: true } ));
- });
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(done).toBe(true);
- expect(fetchSpy).toHaveBeenCalled();
- });
- });
-
- it('should call the config-changes module\'s add_installed_plugin_to_prepare_queue method after processing an install', function() {
- expect(results['config_add']).toEqual([dummy_id, {}, true]);
- });
- it('should queue up actions as appropriate for that plugin and call process on the action stack',
- function() {
- expect(results['actions_callCount']).toEqual(6);
- expect(results['actions_create']).toEqual([jasmine.any(Function), [jasmine.any(Object), path.join(plugins_install_dir, dummy_id), dummy_id, jasmine.any(Object)], jasmine.any(Function), [jasmine.any(Object), dummy_id, jasmine.any(Object)]]);
- });
-
- it('should check version if plugin has engine tag', function(){
- var satisfies = spyOn(semver, 'satisfies').andReturn(true);
- exec.andCallFake(function(cmd, cb) {
- cb(null, '2.5.0\n');
- });
-
- runs(function() {
- installPromise( install('android', project, plugins['com.cordova.engine'], plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(satisfies).toHaveBeenCalledWith('2.5.0','>=2.3.0');
- });
- });
- it('should check version and munge it a little if it has "rc" in it so it plays nice with semver (introduce a dash in it)', function() {
- var satisfies = spyOn(semver, 'satisfies').andReturn(true);
- exec.andCallFake(function(cmd, cb) {
- cb(null, '3.0.0rc1\n');
- });
-
- runs(function() {
- installPromise( install('android', project, plugins['com.cordova.engine'], plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(satisfies).toHaveBeenCalledWith('3.0.0-rc1','>=2.3.0');
- });
- });
- it('should check specific platform version over cordova version if specified', function() {
- var spy = spyOn(semver, 'satisfies').andReturn(true);
- exec.andCallFake(function(cmd, cb) {
- cb(null, '3.1.0\n');
- });
- fetchSpy.andReturn( Q( plugins['com.cordova.engine-android'] ) );
-
- runs(function() {
- installPromise( install('android', project, plugins['com.cordova.engine-android'], plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(spy).toHaveBeenCalledWith('3.1.0','>=3.1.0');
- });
- });
- it('should check platform sdk version if specified', function() {
- var spy = spyOn(semver, 'satisfies').andReturn(true);
- fetchSpy.andReturn( Q( plugins['com.cordova.engine-android'] ) );
- exec.andCallFake(function(cmd, cb) {
- cb(null, '18\n');
- });
-
- runs(function() {
- installPromise( install('android', project, 'com.cordova.engine-android', plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- // <engine name="cordova" VERSION=">=3.0.0"/>
- // <engine name="cordova-android" VERSION=">=3.1.0"/>
- // <engine name="android-sdk" VERSION=">=18"/>
-
- expect(spy.calls.length).toBe(3);
- expect(spy.calls[0].args).toEqual([ '18.0.0', '>=3.0.0' ]);
- expect(spy.calls[1].args).toEqual([ '18.0.0', '>=3.1.0' ]);
- expect(spy.calls[2].args).toEqual([ '18.0.0','>=18' ]);
- });
- });
- it('should check engine versions', function() {
- var spy = spyOn(semver, 'satisfies').andReturn(true);
- fetchSpy.andReturn( Q( plugins['com.cordova.engine'] ) );
-
- runs(function() {
- installPromise( install('android', project, plugins['com.cordova.engine'], plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- // <engine name="cordova" version=">=2.3.0"/>
- // <engine name="cordova-plugman" version=">=0.10.0" />
- // <engine name="mega-fun-plugin" version=">=1.0.0" scriptSrc="megaFunVersion" platform="*" />
- // <engine name="mega-boring-plugin" version=">=3.0.0" scriptSrc="megaBoringVersion" platform="ios|android" />
-
- var plugmanVersion = require('../package.json').version;
- plugmanVersion = plugmanVersion.replace(/-dev$/, '');
-
- expect(spy.calls.length).toBe(4);
- expect(spy.calls[0].args).toEqual([ null, '>=2.3.0' ]);
- expect(spy.calls[1].args).toEqual([ plugmanVersion, '>=0.10.0' ]);
- expect(spy.calls[2].args).toEqual([ null, '>=1.0.0' ]);
- expect(spy.calls[3].args).toEqual([ null, '>=3.0.0' ]);
- });
- });
- it('should not check custom engine version that is not supported for platform', function() {
- var spy = spyOn(semver, 'satisfies').andReturn(true);
- runs(function() {
- installPromise( install('blackberry10', project, plugins['com.cordova.engine'], plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(spy).not.toHaveBeenCalledWith('','>=3.0.0');
- });
- });
-
- describe('with dependencies', function() {
- var emit;
- beforeEach(function() {
- spyOn(fs, 'existsSync').andCallFake( fake['existsSync']['noPlugins'] );
- fetchSpy.andCallFake( fake['fetch']['dependencies'] );
- emit = spyOn(events, 'emit');
- exec.andCallFake(function(cmd, cb) {
- cb(null, '9.0.0\n');
- });
- });
-
- it('should install any dependent plugins if missing', function() {
- runs(function() {
- installPromise( install('android', project, plugins['A'], plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- // Look for 'Installing plugin ...' in events
- var install = common.spy.getInstall(emit);
-
- expect(install).toEqual([
- 'Install start for "C" on android.',
- 'Install start for "D" on android.',
- 'Install start for "A" on android.'
- ]);
- });
- });
-
- it('should install any dependent plugins from registry when url is not defined', function() {
- // Plugin A depends on C & D
- runs(function() {
- installPromise( install('android', project, plugins['A'], plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- // TODO: this is same test as above? Need test other dependency with url=?
- var install = common.spy.getInstall(emit);
-
- expect(install).toEqual([
- 'Install start for "C" on android.',
- 'Install start for "D" on android.',
- 'Install start for "A" on android.'
- ]);
- });
- });
-
- it('should process all dependent plugins with alternate routes to the same plugin', function() {
- // Plugin F depends on A, C, D and E
- runs(function () {
- installPromise(install('android', project, plugins['F'], plugins_install_dir, { browserify: true }));
- });
- waitsFor(function () { return done; }, 'install promise never resolved', 200);
- runs(function () {
- var install = common.spy.getInstall(emit);
-
- expect(install).toEqual([
- 'Install start for "C" on android.',
- 'Install start for "D" on android.',
- 'Install start for "A" on android.',
- 'Install start for "D" on android.',
- 'Install start for "F" on android.'
- ]);
- });
- });
-
- it('should throw if there is a cyclic dependency', function() {
- runs(function () {
- installPromise( install('android', project, plugins['G'], plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function () { return done; }, 'install promise never resolved', 200);
- runs(function () {
- common.spy.getInstall(emit);
-
- expect(done.message).toEqual('Cyclic dependency from G to H');
- });
- });
-
- it('install subdir relative to top level plugin if no fetch meta', function() {
- runs(function () {
- installPromise(install('android', project, plugins['B'], plugins_install_dir, { browserify: true }));
- });
- waitsFor(function () { return done; }, 'install promise never resolved', 200);
- runs(function () {
- var install = common.spy.getInstall(emit);
-
- expect(install).toEqual([
- 'Install start for "D" on android.',
- 'Install start for "E" on android.',
- 'Install start for "B" on android.'
- ]);
- });
- });
-
- it('install uses meta data (if available) of top level plugin source', function() {
- // Fake metadata so plugin 'B' appears from 'meta/B'
- var meta = require('../src/plugman/util/metadata');
- spyOn(meta, 'get_fetch_metadata').andCallFake(function(){
- return {
- source: {type: 'dir', url: path.join(plugins['B'], '..', 'meta')}
- };
- });
-
- runs(function () {
- installPromise(install('android', project, plugins['B'], plugins_install_dir, { browserify: true }));
- });
- waitsFor(function () { return done; }, 'install promise never resolved', 200);
- runs(function () {
- var install = common.spy.getInstall(emit);
-
- expect(install).toEqual([
- 'Install start for "D" on android.',
- 'Install start for "E" on android.',
- 'Install start for "B" on android.'
- ]);
-
- var copy = common.spy.startsWith(emit, 'Copying from');
- expect(copy.length).toBe(3);
- expect(copy[0].indexOf(path.normalize('meta/D')) > 0).toBe(true);
- expect(copy[1].indexOf(path.normalize('meta/subdir/E')) > 0).toBe(true);
- });
- });
- });
-
- });
-
- describe('failure', function() {
- it('should throw if platform is unrecognized', function() {
- runs(function() {
- installPromise( install('atari', project, 'SomePlugin', plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(''+done).toContain('atari not supported.');
- });
- });
- it('should throw if variables are missing', function() {
- runs(function() {
- installPromise( install('android', project, plugins['com.adobe.vars'], plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function(){ return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(''+done).toContain('Variable(s) missing: API_KEY');
- });
- });
- it('should not throw exception on default variables', function() {
- runs(function() {
- installPromise( install('android', project, plugins['org.test.defaultvariables'], plugins_install_dir, { browserify: true , cli_variables:{API_KEY:'del7a' }}) );
- });
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(''+done).toEqual('true');
- });
- });
- it('should throw if git is not found on the path and a remote url is requested', function() {
- spyOn(fs, 'existsSync').andCallFake( fake['existsSync']['noPlugins'] );
- fetchSpy.andCallThrough();
- spyOn(shell, 'which').andReturn(null);
- runs(function() {
- installPromise( install('android', project, 'https://git-wip-us.apache.org/repos/asf/cordova-plugin-camera.git', plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function(){ return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(''+done).toContain('"git" command line tool is not installed: make sure it is accessible on your PATH.');
- });
- });
- it('should not fail if plugin version is less than the minimum requirement. Instead skip.', function(){
- spyOn(semver, 'satisfies').andReturn(false);
- exec.andCallFake(function(cmd, cb) {
- cb(null, '0.0.1\n');
- });
- runs(function() {
- installPromise( install('android', project, plugins['com.cordova.engine'], plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function(){ return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(''+done).toMatch(true);
- });
- });
- });
-
-});
-
-// When run using 'npm test', the removal of temp_dir is causing
-// tests in 'install.spec.js' to fail.
-
-// describe('end', function() {
-
-// it('end', function() {
-// done = false;
-
-// promise.fin(function(err){
-// if(err)
-// events.emit('error', err);
-
-// shell.rm('-rf', temp_dir);
-// done = true;
-// });
-
-// waitsFor(function() { return done; }, 'promise never resolved', 500);
-// });
-// });
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-plugman/install.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/install.spec.js b/cordova-lib/spec-plugman/install.spec.js
index c50e907..6da5767 100644
--- a/cordova-lib/spec-plugman/install.spec.js
+++ b/cordova-lib/spec-plugman/install.spec.js
@@ -21,6 +21,8 @@
var install = require('../src/plugman/install'),
actions = require('../src/plugman/util/action-stack'),
+ xmlHelpers = require('../src/util/xml-helpers'),
+ et = require('elementtree'),
PlatformJson = require('../src/plugman/util/PlatformJson'),
events = require('../src/events'),
plugman = require('../src/plugman/plugman'),
@@ -55,7 +57,6 @@ var install = require('../src/plugman/install'),
},
promise,
results = {},
- dummy_id = 'org.test.plugins.dummyplugin',
superspawn = require('../src/cordova/superspawn');
@@ -90,15 +91,38 @@ var fake = {
}
};
+var TEST_XML = '<?xml version="1.0" encoding="UTF-8"?>\n' +
+ '<widget xmlns = "http://www.w3.org/ns/widgets"\n' +
+ ' xmlns:cdv = "http://cordova.apache.org/ns/1.0"\n' +
+ ' id = "io.cordova.hellocordova"\n' +
+ ' version = "0.0.1">\n' +
+ ' <name>Hello Cordova</name>\n' +
+ ' <description>\n' +
+ ' A sample Apache Cordova application that responds to the deviceready event.\n' +
+ ' </description>\n' +
+ ' <author href="http://cordova.io" email="dev@cordova.apache.org">\n' +
+ ' Apache Cordova Team\n' +
+ ' </author>\n' +
+ ' <content src="index.html" />\n' +
+ ' <access origin="*" />\n' +
+ ' <preference name="fullscreen" value="true" />\n' +
+ ' <preference name="webviewbounce" value="true" />\n' +
+ '</widget>\n';
+
describe('start', function() {
- var prepare, config_queue_add, proc, actions_push, ca, emit;
+ var config_queue_add, proc, actions_push, ca, emit;
beforeEach(function() {
- prepare = spyOn(plugman, 'prepare');
config_queue_add = spyOn(PlatformJson.prototype, 'addInstalledPluginToPrepareQueue');
proc = spyOn(actions.prototype, 'process').andReturn( Q(true) );
actions_push = spyOn(actions.prototype, 'push');
ca = spyOn(actions.prototype, 'createAction');
+
+ var origParseElementtreeSync = xmlHelpers.parseElementtreeSync.bind(xmlHelpers);
+ spyOn(xmlHelpers, 'parseElementtreeSync').andCallFake(function(path) {
+ if (/config.xml$/.test(path)) return new et.ElementTree(et.XML(TEST_XML));
+ return origParseElementtreeSync(path);
+ });
});
it('start', function() {
shell.rm('-rf', project);
@@ -107,7 +131,9 @@ describe('start', function() {
done = false;
promise = Q()
.then(
- function(){ return install('android', project, plugins['org.test.plugins.dummyplugin']); }
+ function(){
+ return install('android', project, plugins['org.test.plugins.dummyplugin']);
+ }
).then(
function(){
results['actions_callCount'] = actions_push.callCount;
@@ -134,7 +160,6 @@ describe('start', function() {
).then(
function(){
done = true;
- results['prepareCount'] = prepare.callCount;
results['emit_results'] = [];
for(var i in emit.calls) {
@@ -154,11 +179,10 @@ describe('start', function() {
});
describe('install', function() {
- var chmod, exec, add_to_queue, prepare, cp, rm, fetchSpy;
+ var chmod, exec, add_to_queue, cp, rm, fetchSpy;
var spawnSpy;
beforeEach(function() {
- prepare = spyOn(plugman, 'prepare').andReturn( Q(true) );
exec = spyOn(child_process, 'exec').andCallFake(function(cmd, cb) {
cb(false, '', '');
@@ -178,10 +202,6 @@ describe('install', function() {
});
describe('success', function() {
- it('should call prepare after a successful install', function() {
- expect(results['prepareCount']).toBe(5);
- });
-
it('should emit a results event with platform-agnostic <info>', function() {
// org.test.plugins.childbrowser
expect(results['emit_results'][0]).toBe('No matter what platform you are installing to, this notice is very important.');
@@ -194,7 +214,6 @@ describe('install', function() {
// VariableBrowser
expect(results['emit_results'][2]).toBe('Remember that your api key is batman!');
});
-
it('should call fetch if provided plugin cannot be resolved locally', function() {
fetchSpy.andReturn( Q( plugins['org.test.plugins.dummyplugin'] ) );
spyOn(fs, 'existsSync').andCallFake( fake['existsSync']['noPlugins'] );
@@ -209,102 +228,80 @@ describe('install', function() {
});
});
- it('should call the config-changes module\'s add_installed_plugin_to_prepare_queue method after processing an install', function() {
- expect(results['config_add']).toEqual([dummy_id, {}, true]);
- });
- it('should queue up actions as appropriate for that plugin and call process on the action stack',
- function() {
- expect(results['actions_callCount']).toEqual(6);
- expect(results['actions_create']).toEqual([jasmine.any(Function), [jasmine.any(Object), path.join(plugins_install_dir, dummy_id), dummy_id, jasmine.any(Object)], jasmine.any(Function), [jasmine.any(Object), dummy_id, jasmine.any(Object)]]);
- });
-
- it('should check version if plugin has engine tag', function(){
- var satisfies = spyOn(semver, 'satisfies').andReturn(true);
- exec.andCallFake(function(cmd, cb) {
- cb(null, '2.5.0\n');
- });
-
- runs(function() {
- installPromise( install('android', project, plugins['com.cordova.engine']) );
- });
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(satisfies).toHaveBeenCalledWith('2.5.0','>=2.3.0');
- });
- });
- it('should check version and munge it a little if it has "rc" in it so it plays nice with semver (introduce a dash in it)', function() {
- var satisfies = spyOn(semver, 'satisfies').andReturn(true);
- exec.andCallFake(function(cmd, cb) {
- cb(null, '3.0.0rc1\n');
- });
-
- runs(function() {
- installPromise( install('android', project, plugins['com.cordova.engine']) );
- });
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(satisfies).toHaveBeenCalledWith('3.0.0-rc1','>=2.3.0');
- });
- });
- it('should check specific platform version over cordova version if specified', function() {
- var spy = spyOn(semver, 'satisfies').andReturn(true);
- exec.andCallFake(function(cmd, cb) {
- cb(null, '3.1.0\n');
- });
- fetchSpy.andReturn( Q( plugins['com.cordova.engine-android'] ) );
-
- runs(function() {
- installPromise( install('android', project, plugins['com.cordova.engine-android']) );
- });
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(spy).toHaveBeenCalledWith('3.1.0','>=3.1.0');
+ describe('engine versions', function () {
+ var fail, satisfies;
+ beforeEach(function () {
+ fail = jasmine.createSpy('fail');
+ satisfies = spyOn(semver, 'satisfies').andReturn(true);
+ spyOn(PlatformJson.prototype, 'isPluginInstalled').andReturn(false);
+ });
+
+ it('should check version if plugin has engine tag', function(done){
+ exec.andCallFake(function(cmd, cb) { cb(null, '2.5.0\n'); });
+ install('android', project, plugins['com.cordova.engine'])
+ .fail(fail)
+ .fin(function () {
+ expect(satisfies).toHaveBeenCalledWith('2.5.0','>=2.3.0');
+ done();
+ });
});
- });
- it('should check platform sdk version if specified', function() {
- var spy = spyOn(semver, 'satisfies').andReturn(true);
- fetchSpy.andReturn( Q( plugins['com.cordova.engine-android'] ) );
- exec.andCallFake(function(cmd, cb) {
- cb(null, '18\n');
+ it('should check version and munge it a little if it has "rc" in it so it plays nice with semver (introduce a dash in it)', function(done) {
+ exec.andCallFake(function(cmd, cb) { cb(null, '3.0.0rc1\n'); });
+ install('android', project, plugins['com.cordova.engine'])
+ .fail(fail)
+ .fin(function () {
+ expect(satisfies).toHaveBeenCalledWith('3.0.0-rc1','>=2.3.0');
+ done();
+ });
});
-
- runs(function() {
- installPromise( install('android', project, 'com.cordova.engine-android') );
+ it('should check specific platform version over cordova version if specified', function(done) {
+ exec.andCallFake(function(cmd, cb) { cb(null, '3.1.0\n'); });
+ install('android', project, plugins['com.cordova.engine-android'])
+ .fail(fail)
+ .fin(function() {
+ expect(satisfies).toHaveBeenCalledWith('3.1.0','>=3.1.0');
+ done();
+ });
});
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- // <engine name="cordova" VERSION=">=3.0.0"/>
- // <engine name="cordova-android" VERSION=">=3.1.0"/>
- // <engine name="android-sdk" VERSION=">=18"/>
-
- expect(spy.calls.length).toBe(3);
- expect(spy.calls[0].args).toEqual([ '18.0.0', '>=3.0.0' ]);
- expect(spy.calls[1].args).toEqual([ '18.0.0', '>=3.1.0' ]);
- expect(spy.calls[2].args).toEqual([ '18.0.0','>=18' ]);
+ it('should check platform sdk version if specified', function(done) {
+ exec.andCallFake(function(cmd, cb) { cb(null, '18\n'); });
+ install('android', project, plugins['com.cordova.engine-android'])
+ .fail(fail)
+ .fin(function() {
+ expect(satisfies.calls.length).toBe(3);
+ // <engine name="cordova" VERSION=">=3.0.0"/>
+ expect(satisfies.calls[0].args).toEqual([ '18.0.0', '>=3.0.0' ]);
+ // <engine name="cordova-android" VERSION=">=3.1.0"/>
+ expect(satisfies.calls[1].args).toEqual([ '18.0.0', '>=3.1.0' ]);
+ // <engine name="android-sdk" VERSION=">=18"/>
+ expect(satisfies.calls[2].args).toEqual([ '18.0.0','>=18' ]);
+ done();
+ });
});
- });
- it('should check engine versions', function() {
- var spy = spyOn(semver, 'satisfies').andReturn(true);
- fetchSpy.andReturn( Q( plugins['com.cordova.engine'] ) );
-
- runs(function() {
- installPromise( install('android', project, plugins['com.cordova.engine']) );
+ it('should check engine versions', function(done) {
+ install('android', project, plugins['com.cordova.engine'])
+ .fail(fail)
+ .fin(function() {
+ var plugmanVersion = require('../package.json').version.replace('-dev', '');
+ expect(satisfies.calls.length).toBe(4);
+ // <engine name="cordova" version=">=2.3.0"/>
+ expect(satisfies.calls[0].args).toEqual([ null, '>=2.3.0' ]);
+ // <engine name="cordova-plugman" version=">=0.10.0" />
+ expect(satisfies.calls[1].args).toEqual([ plugmanVersion, '>=0.10.0' ]);
+ // <engine name="mega-fun-plugin" version=">=1.0.0" scriptSrc="megaFunVersion" platform="*" />
+ expect(satisfies.calls[2].args).toEqual([ null, '>=1.0.0' ]);
+ // <engine name="mega-boring-plugin" version=">=3.0.0" scriptSrc="megaBoringVersion" platform="ios|android" />
+ expect(satisfies.calls[3].args).toEqual([ null, '>=3.0.0' ]);
+ done();
+ });
});
- waitsFor(function() { return done; }, 'install promise never resolved', 200);
- runs(function() {
- // <engine name="cordova" version=">=2.3.0"/>
- // <engine name="cordova-plugman" version=">=0.10.0" />
- // <engine name="mega-fun-plugin" version=">=1.0.0" scriptSrc="megaFunVersion" platform="*" />
- // <engine name="mega-boring-plugin" version=">=3.0.0" scriptSrc="megaBoringVersion" platform="ios|android" />
-
- var plugmanVersion = require('../package.json').version;
- plugmanVersion = plugmanVersion.replace(/-dev$/, '');
-
- expect(spy.calls.length).toBe(4);
- expect(spy.calls[0].args).toEqual([ null, '>=2.3.0' ]);
- expect(spy.calls[1].args).toEqual([ plugmanVersion, '>=0.10.0' ]);
- expect(spy.calls[2].args).toEqual([ null, '>=1.0.0' ]);
- expect(spy.calls[3].args).toEqual([ null, '>=3.0.0' ]);
+ it('should not check custom engine version that is not supported for platform', function(done) {
+ install('blackberry10', project, plugins['com.cordova.engine'])
+ .then(fail)
+ .fail(function () {
+ expect(satisfies).not.toHaveBeenCalledWith('','>=3.0.0');
+ })
+ .fin(done);
});
});
it('should not check custom engine version that is not supported for platform', function() {
@@ -440,7 +437,6 @@ describe('install', function() {
});
});
});
-
});
describe('failure', function() {
@@ -453,13 +449,17 @@ describe('install', function() {
expect(''+done).toContain('atari not supported.');
});
});
- it('should throw if variables are missing', function() {
- runs(function() {
- installPromise( install('android', project, plugins['com.adobe.vars']) );
- });
- waitsFor(function(){ return done; }, 'install promise never resolved', 200);
- runs(function() {
- expect(''+done).toContain('Variable(s) missing: API_KEY');
+ it('should throw if variables are missing', function(done) {
+ var success = jasmine.createSpy('success');
+ spyOn(PlatformJson.prototype, 'isPluginInstalled').andReturn(false);
+ install('android', project, plugins['com.adobe.vars'])
+ .then(success)
+ .fail(function (err) {
+ expect(err).toContain('Variable(s) missing: API_KEY');
+ })
+ .fin(function () {
+ expect(success).not.toHaveBeenCalled();
+ done();
});
});
it('should throw if git is not found on the path and a remote url is requested', function() {
@@ -488,10 +488,8 @@ describe('install', function() {
});
});
});
-
});
-
describe('end', function() {
it('end', function() {
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-plugman/prepare.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/prepare.spec.js b/cordova-lib/spec-plugman/prepare.spec.js
deleted file mode 100644
index c3ff707..0000000
--- a/cordova-lib/spec-plugman/prepare.spec.js
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- 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 prepare = require('../src/plugman/prepare'),
- common = require('../src/plugman/platforms/common'),
- fs = require('fs'),
- path = require('path'),
- shell = require('shelljs'),
- config_changes = require('../src/plugman/util/config-changes'),
- PlatformJson = require('../src/plugman/util/PlatformJson'),
- temp = __dirname,
- plugins_dir = path.join(temp, 'plugins');
-
-describe('prepare', function() {
- var proc, platform_json, write, mkdir, rm;
- beforeEach(function() {
- rm = spyOn(shell, 'rm');
- mkdir = spyOn(shell, 'mkdir');
- proc = spyOn(config_changes, 'process');
- platform_json = spyOn(PlatformJson, 'load').andReturn(new PlatformJson(null, null, {installed_plugins:{},dependent_plugins:{},prepare_queue:{uninstalled:[]}}));
- write = spyOn(fs, 'writeFileSync');
- });
- it('should create cordova_plugins.js file in a custom www directory', function() {
- var custom_www = path.join(temp, 'assets', 'custom_www'),
- js = path.join(temp, 'assets', 'custom_www', 'cordova_plugins.js');
- prepare(temp, 'android', plugins_dir, custom_www);
- expect(write).toHaveBeenCalledWith(js, jasmine.any(String), 'utf-8');
- });
- describe('handling of js-modules', function() {
- var copySpy;
- beforeEach(function() {
- copySpy = spyOn(common, 'copyFile');
- platform_json.andReturn(new PlatformJson(null, null, {
- installed_plugins: {plugin_one: '', plugin_two: ''},
- dependent_plugins: {}, prepare_queue: {uninstalled:[]}
- }));
- });
- describe('uninstallation/removal', function() {
- var existsSync;
- beforeEach(function() {
- existsSync = spyOn(fs, 'existsSync').andReturn(true);
- platform_json.andReturn(new PlatformJson(null, null, {installed_plugins:{},dependent_plugins:{},prepare_queue:{uninstalled:[{
- plugin:'nickelback',
- id:'nickelback',
- topLevel:true
- }]}}));
- });
- it('should remove any www/plugins directories related to plugins being queued for removal', function() {
- prepare(temp, 'android', plugins_dir);
- expect(rm).toHaveBeenCalledWith('-rf', path.join(temp, 'assets', 'www', 'plugins', 'nickelback'));
- });
- });
- });
- it('should call into config-changes\' process method to do config processing', function() {
- prepare(temp, 'android', plugins_dir);
- expect(proc).toHaveBeenCalledWith(plugins_dir, temp, 'android', jasmine.any(Object), jasmine.any(Object));
- });
-});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-plugman/projects/wp8/config.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/wp8/config.xml b/cordova-lib/spec-plugman/projects/wp8/config.xml
new file mode 100644
index 0000000..c08b522
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/wp8/config.xml
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="io.cordova.cordovaapp" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+ <name>CordovaApp</name>
+ <description>
+ A sample Apache Cordova application that responds to the deviceready event.
+ </description>
+ <author email="dev@cordova.apache.org" href="http://cordova.io">
+ Apache Cordova Team
+ </author>
+ <content src="index.html" />
+ <access origin="*" />
+</widget>
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-plugman/uninstall-browserify.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/uninstall-browserify.spec.js b/cordova-lib/spec-plugman/uninstall-browserify.spec.js
deleted file mode 100644
index d68b0a6..0000000
--- a/cordova-lib/spec-plugman/uninstall-browserify.spec.js
+++ /dev/null
@@ -1,315 +0,0 @@
-/**
- 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.
-*/
-
-/* jshint sub:true */
-
-var uninstall = require('../src/plugman/uninstall'),
- install = require('../src/plugman/install'),
- actions = require('../src/plugman/util/action-stack'),
- PlatformJson = require('../src/plugman/util/PlatformJson'),
- events = require('../src/events'),
- plugman = require('../src/plugman/plugman'),
- common = require('./common'),
- fs = require('fs'),
- path = require('path'),
- shell = require('shelljs'),
- Q = require('q'),
- spec = __dirname,
- done = false,
- srcProject = path.join(spec, 'projects', 'android_uninstall'),
- project = path.join(spec, 'projects', 'android_uninstall.test'),
- project2 = path.join(spec, 'projects', 'android_uninstall.test2'),
-
- plugins_dir = path.join(spec, 'plugins'),
- plugins_install_dir = path.join(project, 'cordova', 'plugins'),
- plugins_install_dir2 = path.join(project2, 'cordova', 'plugins'),
-
- plugins = {
- 'org.test.plugins.dummyplugin' : path.join(plugins_dir, 'org.test.plugins.dummyplugin'),
- 'A' : path.join(plugins_dir, 'dependencies', 'A'),
- 'C' : path.join(plugins_dir, 'dependencies', 'C')
- },
- promise,
- dummy_id = 'org.test.plugins.dummyplugin';
-
-function uninstallPromise(f) {
- return f.then(function() { done = true; }, function(err) { done = err; });
-}
-
-describe('start', function() {
-
- it('start', function() {
- shell.rm('-rf', project);
- shell.rm('-rf', project2);
- shell.cp('-R', path.join(srcProject, '*'), project);
- shell.cp('-R', path.join(srcProject, '*'), project2);
-
- done = false;
- promise = Q()
- .then(
- function(){ return install('android', project, plugins['org.test.plugins.dummyplugin'], plugins_install_dir, { browserify: true }); }
- ).then(
- function(){ return install('android', project, plugins['A'], plugins_install_dir, { browserify: true }); }
- ).then(
- function(){ return install('android', project2, plugins['C'], plugins_install_dir2, { browserify: true }); }
- ).then(
- function(){ return install('android', project2, plugins['A'], plugins_install_dir2, { browserify: true }); }
- ).then(
- function(){ done = true; }
- ).fail(function(err) {
- done = err.stack;
- });
- waitsFor(function() { return done; }, 'promise never resolved', 5000);
- runs(function() {
- expect(done).toBe(true);
- });
- });
-});
-
-describe('uninstallPlatform', function() {
- var proc, prepare, prepareBrowserify, actions_push, add_to_queue, c_a, rm;
- var fsWrite;
-
- beforeEach(function() {
- proc = spyOn(actions.prototype, 'process').andReturn(Q());
- actions_push = spyOn(actions.prototype, 'push');
- c_a = spyOn(actions.prototype, 'createAction');
- prepare = spyOn(plugman, 'prepare');
- prepareBrowserify = spyOn(plugman, 'prepareBrowserify');
- fsWrite = spyOn(fs, 'writeFileSync').andReturn(true);
- rm = spyOn(shell, 'rm').andReturn(true);
- spyOn(shell, 'cp').andReturn(true);
- add_to_queue = spyOn(PlatformJson.prototype, 'addUninstalledPluginToPrepareQueue');
- done = false;
- });
- describe('success', function() {
- it('should call prepare after a successful uninstall', function() {
- runs(function() {
- uninstallPromise(uninstall.uninstallPlatform('android', project, dummy_id, plugins_install_dir, { browserify: true }));
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- expect(prepareBrowserify).toHaveBeenCalled();
- });
- });
- it('should call the config-changes module\'s add_uninstalled_plugin_to_prepare_queue method after processing an install', function() {
- runs(function() {
- uninstallPromise(uninstall.uninstallPlatform('android', project, dummy_id, plugins_install_dir, { browserify: true }));
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- expect(add_to_queue).toHaveBeenCalledWith(dummy_id, true);
- });
- });
- it('should queue up actions as appropriate for that plugin and call process on the action stack', function() {
- runs(function() {
- uninstallPromise(uninstall.uninstallPlatform('android', project, dummy_id, plugins_install_dir, { browserify: true }));
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- expect(actions_push.calls.length).toEqual(6);
- expect(proc).toHaveBeenCalled();
- });
- });
-
- describe('with dependencies', function() {
- var emit;
- beforeEach(function() {
- emit = spyOn(events, 'emit');
- });
- it('should uninstall "dangling" dependencies', function() {
- runs(function() {
- uninstallPromise(uninstall.uninstallPlatform('android', project, 'A', plugins_install_dir, { browserify: true }));
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- expect(emit).toHaveBeenCalledWith('log', 'Uninstalling 2 dependent plugins.');
- });
- });
- });
- });
-
- describe('failure', function() {
- it('should throw if platform is unrecognized', function() {
- runs(function() {
- uninstallPromise( uninstall.uninstallPlatform('atari', project, 'SomePlugin', plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- expect(''+done).toContain('atari not supported.');
- });
- });
- it('should throw if plugin is missing', function() {
- runs(function() {
- uninstallPromise( uninstall.uninstallPlatform('android', project, 'SomePluginThatDoesntExist', plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- expect(''+done).toContain('Plugin "SomePluginThatDoesntExist" not found. Already uninstalled?');
- });
- });
- });
-});
-
-describe('uninstallPlugin', function() {
- var rm, fsWrite, rmstack = [], emit;
-
- beforeEach(function() {
- fsWrite = spyOn(fs, 'writeFileSync').andReturn(true);
- rm = spyOn(shell, 'rm').andCallFake(function(f,p) { rmstack.push(p); return true; });
- rmstack = [];
- emit = spyOn(events, 'emit');
- done = false;
- });
- describe('with dependencies', function() {
-
- it('should delete all dependent plugins', function() {
- runs(function() {
- uninstallPromise( uninstall.uninstallPlugin('A', plugins_install_dir, {browserify: true}) );
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- var del = common.spy.getDeleted(emit);
-
- expect(del).toEqual([
- 'Deleted "C"',
- 'Deleted "D"',
- 'Deleted "A"'
- ]);
- });
- });
-
- it('should fail if plugin is a required dependency', function() {
- runs(function() {
- uninstallPromise( uninstall.uninstallPlugin('C', plugins_install_dir, {browserify: true}) );
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- expect(done.message).toBe('"C" is required by (A) and cannot be removed (hint: use -f or --force)');
- });
- });
-
- it('allow forcefully removing a plugin', function() {
- runs(function() {
- uninstallPromise( uninstall.uninstallPlugin('C', plugins_install_dir, {browserify: true, force: true}) );
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- expect(done).toBe(true);
- var del = common.spy.getDeleted(emit);
- expect(del).toEqual(['Deleted "C"']);
- });
- });
-
- it('never remove top level plugins if they are a dependency', function() {
- runs(function() {
- uninstallPromise( uninstall.uninstallPlugin('A', plugins_install_dir2, {browserify: true}) );
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- var del = common.spy.getDeleted(emit);
-
- expect(del).toEqual([
- 'Deleted "D"',
- 'Deleted "A"'
- ]);
- });
- });
- });
-});
-
-describe('uninstall', function() {
- var fsWrite, rm, add_to_queue;
-
- beforeEach(function() {
- fsWrite = spyOn(fs, 'writeFileSync').andReturn(true);
- rm = spyOn(shell, 'rm').andReturn(true);
- add_to_queue = spyOn(PlatformJson.prototype, 'addUninstalledPluginToPrepareQueue');
- done = false;
- });
- describe('success', function() {
- it('should call the config-changes module\'s add_uninstalled_plugin_to_prepare_queue method after processing an install', function() {
- runs(function() {
- uninstallPromise( uninstall('android', project, plugins['org.test.plugins.dummyplugin'], plugins_install_dir, { browserify: true }) );
- });
- waitsFor(function() { return done; }, 'promise never resolved', 500);
- runs(function() {
- expect(add_to_queue).toHaveBeenCalledWith(dummy_id, true);
- });
- });
- });
-
- describe('failure', function() {
- it('should throw if platform is unrecognized', function() {
- runs(function() {
- uninstallPromise(uninstall('atari', project, 'SomePlugin', plugins_install_dir, { browserify: true }));
- });
- waitsFor(function() { return done; }, 'promise never resolved', 500);
- runs(function() {
- expect(''+done).toContain('atari not supported.');
- });
- });
- it('should throw if plugin is missing', function() {
- runs(function() {
- uninstallPromise(uninstall('android', project, 'SomePluginThatDoesntExist', plugins_install_dir, { browserify: true }));
- });
- waitsFor(function() { return done; }, 'promise never resolved', 500);
- runs(function() {
- expect(''+done).toContain('Plugin "SomePluginThatDoesntExist" not found. Already uninstalled?');
- });
- });
- });
-});
-
-describe('end', function() {
-
- it('end', function() {
- done = false;
-
- promise.then(
- function(){
- return uninstall('android', project, plugins['org.test.plugins.dummyplugin'], plugins_install_dir, { browserify: true });
- }
- ).then(
- function(){
- // Fails... A depends on
- return uninstall('android', project, plugins['C'], plugins_install_dir, { browserify: true });
- }
- ).fail(
- function(err) {
- expect(err.message).toBe('The plugin \'C\' is required by (A), skipping uninstallation.');
- }
- ).then(
- function(){
- // dependencies on C,D ... should this only work with --recursive? prompt user..?
- return uninstall('android', project, plugins['A'], plugins_install_dir, { browserify: true });
- }
- ).fin(function(err){
- if(err)
- plugman.emit('error', err);
-
- shell.rm('-rf', project);
- shell.rm('-rf', project2);
- done = true;
- });
-
- waitsFor(function() { return done; }, 'promise never resolved', 1500);
- });
-});
-
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-plugman/uninstall.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/uninstall.spec.js b/cordova-lib/spec-plugman/uninstall.spec.js
index 264d8b9..63f1ff2 100644
--- a/cordova-lib/spec-plugman/uninstall.spec.js
+++ b/cordova-lib/spec-plugman/uninstall.spec.js
@@ -22,10 +22,12 @@
var uninstall = require('../src/plugman/uninstall'),
install = require('../src/plugman/install'),
actions = require('../src/plugman/util/action-stack'),
- PlatformJson = require('../src/plugman/util/PlatformJson'),
events = require('../src/events'),
plugman = require('../src/plugman/plugman'),
common = require('./common'),
+ platforms = require('../src/platforms/platforms'),
+ xmlHelpers = require('../src/util/xml-helpers'),
+ et = require('elementtree'),
fs = require('fs'),
path = require('path'),
shell = require('shelljs'),
@@ -50,11 +52,34 @@ var uninstall = require('../src/plugman/uninstall'),
promise,
dummy_id = 'org.test.plugins.dummyplugin';
+var TEST_XML = '<?xml version="1.0" encoding="UTF-8"?>\n' +
+ '<widget xmlns = "http://www.w3.org/ns/widgets"\n' +
+ ' xmlns:cdv = "http://cordova.apache.org/ns/1.0"\n' +
+ ' id = "io.cordova.hellocordova"\n' +
+ ' version = "0.0.1">\n' +
+ ' <name>Hello Cordova</name>\n' +
+ ' <description>\n' +
+ ' A sample Apache Cordova application that responds to the deviceready event.\n' +
+ ' </description>\n' +
+ ' <author href="http://cordova.io" email="dev@cordova.apache.org">\n' +
+ ' Apache Cordova Team\n' +
+ ' </author>\n' +
+ ' <content src="index.html" />\n' +
+ ' <access origin="*" />\n' +
+ '</widget>\n';
+
function uninstallPromise(f) {
return f.then(function() { done = true; }, function(err) { done = err; });
}
describe('start', function() {
+ beforeEach(function () {
+ var origParseElementtreeSync = xmlHelpers.parseElementtreeSync.bind(xmlHelpers);
+ spyOn(xmlHelpers, 'parseElementtreeSync').andCallFake(function(path) {
+ if (/config.xml$/.test(path)) return new et.ElementTree(et.XML(TEST_XML));
+ return origParseElementtreeSync(path);
+ });
+ });
it('start', function() {
shell.rm('-rf', project, project2, project3);
@@ -89,48 +114,29 @@ describe('start', function() {
});
describe('uninstallPlatform', function() {
- var proc, prepare, actions_push, add_to_queue, c_a, rm;
+ var proc, rm;
var fsWrite;
beforeEach(function() {
proc = spyOn(actions.prototype, 'process').andReturn(Q());
- actions_push = spyOn(actions.prototype, 'push');
- c_a = spyOn(actions.prototype, 'createAction');
- prepare = spyOn(plugman, 'prepare');
fsWrite = spyOn(fs, 'writeFileSync').andReturn(true);
rm = spyOn(shell, 'rm').andReturn(true);
spyOn(shell, 'cp').andReturn(true);
- add_to_queue = spyOn(PlatformJson.prototype, 'addUninstalledPluginToPrepareQueue');
done = false;
});
describe('success', function() {
- it('should call prepare after a successful uninstall', function() {
- runs(function() {
- uninstallPromise(uninstall.uninstallPlatform('android', project, dummy_id));
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- expect(prepare).toHaveBeenCalled();
- });
- });
- it('should call the config-changes module\'s add_uninstalled_plugin_to_prepare_queue method after processing an install', function() {
- runs(function() {
- uninstallPromise(uninstall.uninstallPlatform('android', project, dummy_id));
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- expect(add_to_queue).toHaveBeenCalledWith(dummy_id, true);
- });
- });
- it('should queue up actions as appropriate for that plugin and call process on the action stack', function() {
- runs(function() {
- uninstallPromise(uninstall.uninstallPlatform('android', project, dummy_id));
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- expect(actions_push.calls.length).toEqual(6);
- expect(proc).toHaveBeenCalled();
- });
+
+ it('should get PlatformApi instance for platform and invoke its\' removePlugin method', function(done) {
+ var platformApi = { removePlugin: jasmine.createSpy('removePlugin').andReturn(Q()) };
+ var getPlatformApi = spyOn(platforms, 'getPlatformApi').andReturn(platformApi);
+
+ uninstall.uninstallPlatform('android', project, dummy_id)
+ .then(function() {
+ expect(getPlatformApi).toHaveBeenCalledWith('android', project);
+ expect(platformApi.removePlugin).toHaveBeenCalled();
+ }, function(err) {
+ expect(err).toBeUndefined();
+ }).fin(done);
});
describe('with dependencies', function() {
@@ -255,25 +261,13 @@ describe('uninstallPlugin', function() {
});
describe('uninstall', function() {
- var fsWrite, rm, add_to_queue;
+ var fsWrite, rm;
beforeEach(function() {
fsWrite = spyOn(fs, 'writeFileSync').andReturn(true);
rm = spyOn(shell, 'rm').andReturn(true);
- add_to_queue = spyOn(PlatformJson.prototype, 'addUninstalledPluginToPrepareQueue');
done = false;
});
- describe('success', function() {
- it('should call the config-changes module\'s add_uninstalled_plugin_to_prepare_queue method after processing an install', function() {
- runs(function() {
- uninstallPromise( uninstall('android', project, plugins['org.test.plugins.dummyplugin']) );
- });
- waitsFor(function() { return done; }, 'promise never resolved', 200);
- runs(function() {
- expect(add_to_queue).toHaveBeenCalledWith(dummy_id, true);
- });
- });
- });
describe('failure', function() {
it('should throw if platform is unrecognized', function() {
@@ -298,29 +292,20 @@ describe('uninstall', function() {
});
describe('end', function() {
-
it('end', function() {
done = false;
- promise.then(
- function(){
- return uninstall('android', project, plugins['org.test.plugins.dummyplugin']);
- }
- ).then(
- function(){
- // Fails... A depends on
- return uninstall('android', project, plugins['C']);
- }
- ).fail(
- function(err) {
- expect(err.stack).toMatch(/The plugin 'C' is required by \(A\), skipping uninstallation./);
- }
- ).then(
- function(){
- // dependencies on C,D ... should this only work with --recursive? prompt user..?
- return uninstall('android', project, plugins['A']);
- }
- ).fin(function(err){
+ promise.then(function(){
+ return uninstall('android', project, plugins['org.test.plugins.dummyplugin']);
+ }).then(function(){
+ // Fails... A depends on
+ return uninstall('android', project, plugins['C']);
+ }).fail(function(err) {
+ expect(err.stack).toMatch(/The plugin 'C' is required by \(A\), skipping uninstallation./);
+ }).then(function(){
+ // dependencies on C,D ... should this only work with --recursive? prompt user..?
+ return uninstall('android', project, plugins['A']);
+ }).fin(function(err){
if(err)
plugman.emit('error', err);
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07271a5c/cordova-lib/spec-plugman/util/action-stack.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/util/action-stack.spec.js b/cordova-lib/spec-plugman/util/action-stack.spec.js
index 5eb4847..c0677ea 100644
--- a/cordova-lib/spec-plugman/util/action-stack.spec.js
+++ b/cordova-lib/spec-plugman/util/action-stack.spec.js
@@ -37,9 +37,9 @@ describe('action-stack', function() {
stack.push(stack.createAction(second_spy, second_args, function(){}, []));
stack.push(stack.createAction(third_spy, third_args, function(){}, []));
stack.process('android', android_one_project);
- expect(first_spy).toHaveBeenCalledWith(first_args[0], jasmine.any(Object));
- expect(second_spy).toHaveBeenCalledWith(second_args[0], jasmine.any(Object));
- expect(third_spy).toHaveBeenCalledWith(third_args[0], jasmine.any(Object));
+ expect(first_spy).toHaveBeenCalledWith(first_args[0]);
+ expect(second_spy).toHaveBeenCalledWith(second_args[0]);
+ expect(third_spy).toHaveBeenCalledWith(third_args[0]);
});
it('should revert processed actions if an exception occurs', function() {
spyOn(console, 'log');
@@ -66,11 +66,11 @@ describe('action-stack', function() {
runs(function() {
expect(error).toEqual(process_err);
// first two actions should have been called, but not the third
- expect(first_spy).toHaveBeenCalledWith(first_args[0], jasmine.any(Object));
- expect(second_spy).toHaveBeenCalledWith(second_args[0], jasmine.any(Object));
- expect(third_spy).not.toHaveBeenCalledWith(third_args[0], jasmine.any(Object));
+ expect(first_spy).toHaveBeenCalledWith(first_args[0]);
+ expect(second_spy).toHaveBeenCalledWith(second_args[0]);
+ expect(third_spy).not.toHaveBeenCalledWith(third_args[0]);
// first reverter should have been called after second action exploded
- expect(first_reverter).toHaveBeenCalledWith(first_reverter_args[0], jasmine.any(Object));
+ expect(first_reverter).toHaveBeenCalledWith(first_reverter_args[0]);
});
});
});
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org