mirror of
https://github.com/apache/cordova-android.git
synced 2026-05-30 00:00:04 +08:00
CB-11138 Bump cordova-common to 1.2.0
This commit is contained in:
+1
@@ -186,6 +186,7 @@ ConfigParser.prototype = {
|
||||
staticResources.forEach(function (elt) {
|
||||
var res = {};
|
||||
res.src = elt.attrib.src;
|
||||
res.target = elt.attrib.target || undefined;
|
||||
res.density = elt.attrib['density'] || elt.attrib[that.cdvNamespacePrefix+':density'] || elt.attrib['gap:density'];
|
||||
res.platform = elt.platform || null; // null means icon represents default icon (shared between platforms)
|
||||
res.width = +elt.attrib.width || undefined;
|
||||
|
||||
+17
@@ -152,6 +152,23 @@ CordovaLogger.prototype.setLevel = function (logLevel) {
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adjusts the current logger level according to the passed options.
|
||||
*
|
||||
* @param {Object|Array} opts An object or args array with options
|
||||
*
|
||||
* @return {CordovaLogger} Current instance, to allow calls chaining.
|
||||
*/
|
||||
CordovaLogger.prototype.adjustLevel = function (opts) {
|
||||
if (opts.verbose || (Array.isArray(opts) && opts.indexOf('--verbose') !== -1)) {
|
||||
this.setLevel('verbose');
|
||||
} else if (opts.silent || (Array.isArray(opts) && opts.indexOf('--silent') !== -1)) {
|
||||
this.setLevel('error');
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaches logger to EventEmitter instance provided.
|
||||
*
|
||||
|
||||
+124
@@ -91,6 +91,38 @@ PlatformJson.prototype.addPlugin = function(pluginId, variables, isTopLevel) {
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @chaining
|
||||
* Generates and adds metadata for provided plugin into associated <platform>.json file
|
||||
*
|
||||
* @param {PluginInfo} pluginInfo A pluginInfo instance to add metadata from
|
||||
* @returns {this} Current PlatformJson instance to allow calls chaining
|
||||
*/
|
||||
PlatformJson.prototype.addPluginMetadata = function (pluginInfo) {
|
||||
|
||||
var installedModules = this.root.modules || [];
|
||||
|
||||
var installedPaths = installedModules.map(function (installedModule) {
|
||||
return installedModule.file;
|
||||
});
|
||||
|
||||
var modulesToInstall = pluginInfo.getJsModules(this.platform)
|
||||
.map(function (module) {
|
||||
return new ModuleMetadata(pluginInfo.id, module);
|
||||
})
|
||||
.filter(function (metadata) {
|
||||
// Filter out modules which are already added to metadata
|
||||
return installedPaths.indexOf(metadata.file) === -1;
|
||||
});
|
||||
|
||||
this.root.modules = installedModules.concat(modulesToInstall);
|
||||
|
||||
this.root.plugin_metadata = this.root.plugin_metadata || {};
|
||||
this.root.plugin_metadata[pluginInfo.id] = pluginInfo.version;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
PlatformJson.prototype.removePlugin = function(pluginId, isTopLevel) {
|
||||
var pluginsList = isTopLevel ?
|
||||
this.root.installed_plugins :
|
||||
@@ -101,6 +133,35 @@ PlatformJson.prototype.removePlugin = function(pluginId, isTopLevel) {
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @chaining
|
||||
* Removes metadata for provided plugin from associated file
|
||||
*
|
||||
* @param {PluginInfo} pluginInfo A PluginInfo instance to which modules' metadata
|
||||
* we need to remove
|
||||
*
|
||||
* @returns {this} Current PlatformJson instance to allow calls chaining
|
||||
*/
|
||||
PlatformJson.prototype.removePluginMetadata = function (pluginInfo) {
|
||||
var modulesToRemove = pluginInfo.getJsModules(this.platform)
|
||||
.map(function (jsModule) {
|
||||
return ['plugins', pluginInfo.id, jsModule.src].join('/');
|
||||
});
|
||||
|
||||
var installedModules = this.root.modules || [];
|
||||
this.root.modules = installedModules
|
||||
.filter(function (installedModule) {
|
||||
// Leave only those metadatas which 'file' is not in removed modules
|
||||
return (modulesToRemove.indexOf(installedModule.file) === -1);
|
||||
});
|
||||
|
||||
if (this.root.plugin_metadata) {
|
||||
delete this.root.plugin_metadata[pluginInfo.id];
|
||||
}
|
||||
|
||||
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});
|
||||
};
|
||||
@@ -125,6 +186,39 @@ PlatformJson.prototype.makeTopLevel = function(pluginId) {
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a metadata for all installed plugins and js modules. The resultant
|
||||
* string is ready to be written to 'cordova_plugins.js'
|
||||
*
|
||||
* @returns {String} cordova_plugins.js contents
|
||||
*/
|
||||
PlatformJson.prototype.generateMetadata = function () {
|
||||
return [
|
||||
'cordova.define(\'cordova/plugin_list\', function(require, exports, module) {',
|
||||
'module.exports = ' + JSON.stringify(this.root.modules, null, 4) + ';',
|
||||
'module.exports.metadata = ',
|
||||
'// TOP OF METADATA',
|
||||
JSON.stringify(this.root.plugin_metadata, null, 4) + ';',
|
||||
'// BOTTOM OF METADATA',
|
||||
'});' // Close cordova.define.
|
||||
].join('\n');
|
||||
};
|
||||
|
||||
/**
|
||||
* @chaining
|
||||
* Generates and then saves metadata to specified file. Doesn't check if file exists.
|
||||
*
|
||||
* @param {String} destination File metadata will be written to
|
||||
* @return {PlatformJson} PlatformJson instance
|
||||
*/
|
||||
PlatformJson.prototype.generateAndSaveMetadata = function (destination) {
|
||||
var meta = this.generateMetadata();
|
||||
shelljs.mkdir('-p', path.dirname(destination));
|
||||
fs.writeFileSync(destination, meta, 'utf-8');
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
// convert a munge from the old format ([file][parent][xml] = count) to the current one
|
||||
function fix_munge(root) {
|
||||
root.prepare_queue = root.prepare_queue || {installed:[], uninstalled:[]};
|
||||
@@ -151,5 +245,35 @@ function fix_munge(root) {
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @class ModuleMetadata
|
||||
*
|
||||
* Creates a ModuleMetadata object that represents module entry in 'cordova_plugins.js'
|
||||
* file at run time
|
||||
*
|
||||
* @param {String} pluginId Plugin id where this module installed from
|
||||
* @param (JsModule|Object) jsModule A js-module entry from PluginInfo class to generate metadata for
|
||||
*/
|
||||
function ModuleMetadata (pluginId, jsModule) {
|
||||
|
||||
if (!pluginId) throw new TypeError('pluginId argument must be a valid plugin id');
|
||||
if (!jsModule.src && !jsModule.name) throw new TypeError('jsModule argument must contain src or/and name properties');
|
||||
|
||||
this.id = pluginId + '.' + ( jsModule.name || jsModule.src.match(/([^\/]+)\.js/)[1] );
|
||||
this.file = ['plugins', pluginId, jsModule.src].join('/');
|
||||
this.pluginId = pluginId;
|
||||
|
||||
if (jsModule.clobbers && jsModule.clobbers.length > 0) {
|
||||
this.clobbers = jsModule.clobbers.map(function(o) { return o.target; });
|
||||
}
|
||||
if (jsModule.merges && jsModule.merges.length > 0) {
|
||||
this.merges = jsModule.merges.map(function(o) { return o.target; });
|
||||
}
|
||||
if (jsModule.runs) {
|
||||
this.runs = true;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PlatformJson;
|
||||
|
||||
|
||||
+6
-10
@@ -43,18 +43,14 @@ function PluginInfo(dirname) {
|
||||
// <preference> tag
|
||||
// Example: <preference name="API_KEY" />
|
||||
// Used to require a variable to be specified via --variable when installing the plugin.
|
||||
// returns { key : default | null}
|
||||
self.getPreferences = getPreferences;
|
||||
function getPreferences(platform) {
|
||||
var arprefs = _getTags(self._et, 'preference', platform, _parsePreference);
|
||||
|
||||
var prefs= {};
|
||||
for(var i in arprefs)
|
||||
{
|
||||
var pref=arprefs[i];
|
||||
prefs[pref.preference]=pref.default;
|
||||
}
|
||||
// returns { key : default | null}
|
||||
return prefs;
|
||||
return _getTags(self._et, 'preference', platform, _parsePreference)
|
||||
.reduce(function (preferences, pref) {
|
||||
preferences[pref.preference] = pref.default;
|
||||
return preferences;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function _parsePreference(prefTag) {
|
||||
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
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 ActionStack = require('./ActionStack');
|
||||
var PlatformJson = require('./PlatformJson');
|
||||
var CordovaError = require('./CordovaError/CordovaError');
|
||||
var PlatformMunger = require('./ConfigChanges/ConfigChanges').PlatformMunger;
|
||||
var PluginInfoProvider = require('./PluginInfo/PluginInfoProvider');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @class PluginManager
|
||||
* Represents an entity for adding/removing plugins for platforms
|
||||
*
|
||||
* @param {String} platform Platform name
|
||||
* @param {Object} locations - Platform files and directories
|
||||
* @param {IDEProject} ideProject The IDE project to add/remove plugin changes to/from
|
||||
*/
|
||||
function PluginManager(platform, locations, ideProject) {
|
||||
this.platform = platform;
|
||||
this.locations = locations;
|
||||
this.project = ideProject;
|
||||
|
||||
var platformJson = PlatformJson.load(locations.root, platform);
|
||||
this.munger = new PlatformMunger(platform, locations.root, platformJson, new PluginInfoProvider());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @constructs PluginManager
|
||||
* A convenience shortcut to new PluginManager(...)
|
||||
*
|
||||
* @param {String} platform Platform name
|
||||
* @param {Object} locations - Platform files and directories
|
||||
* @param {IDEProject} ideProject The IDE project to add/remove plugin changes to/from
|
||||
* @returns new PluginManager instance
|
||||
*/
|
||||
PluginManager.get = function(platform, locations, ideProject) {
|
||||
return new PluginManager(platform, locations, ideProject);
|
||||
};
|
||||
|
||||
PluginManager.INSTALL = 'install';
|
||||
PluginManager.UNINSTALL = 'uninstall';
|
||||
|
||||
module.exports = PluginManager;
|
||||
|
||||
/**
|
||||
* Describes and implements common plugin installation/uninstallation routine. The flow is the following:
|
||||
* * Validate and set defaults for options. Note that options are empty by default. Everything
|
||||
* needed for platform IDE project must be passed from outside. Plugin variables (which
|
||||
* are the part of the options) also must be already populated with 'PACKAGE_NAME' variable.
|
||||
* * Collect all plugin's native and web files, get installers/uninstallers and process
|
||||
* all these via ActionStack.
|
||||
* * Save the IDE project, so the changes made by installers are persisted.
|
||||
* * Generate config changes munge for plugin and apply it to all required files
|
||||
* * Generate metadata for plugin and plugin modules and save it to 'cordova_plugins.js'
|
||||
*
|
||||
* @param {PluginInfo} plugin A PluginInfo structure representing plugin to install
|
||||
* @param {Object} [options={}] An installation options. It is expected but is not necessary
|
||||
* that options would contain 'variables' inner object with 'PACKAGE_NAME' field set by caller.
|
||||
*
|
||||
* @returns {Promise} Returns a Q promise, either resolved in case of success, rejected otherwise.
|
||||
*/
|
||||
PluginManager.prototype.doOperation = function (operation, plugin, options) {
|
||||
if (operation !== PluginManager.INSTALL && operation !== PluginManager.UNINSTALL)
|
||||
return Q.reject(new CordovaError('The parameter is incorrect. The opeation must be either "add" or "remove"'));
|
||||
|
||||
if (!plugin || plugin.constructor.name !== 'PluginInfo')
|
||||
return Q.reject(new CordovaError('The parameter is incorrect. The first parameter should be a PluginInfo instance'));
|
||||
|
||||
// Set default to empty object to play safe when accesing properties
|
||||
options = options || {};
|
||||
|
||||
var self = this;
|
||||
var actions = new ActionStack();
|
||||
|
||||
// gather all files need to be handled during operation ...
|
||||
plugin.getFilesAndFrameworks(this.platform)
|
||||
.concat(plugin.getAssets(this.platform))
|
||||
.concat(plugin.getJsModules(this.platform))
|
||||
// ... put them into stack ...
|
||||
.forEach(function(item) {
|
||||
var installer = self.project.getInstaller(item.itemType);
|
||||
var uninstaller = self.project.getUninstaller(item.itemType);
|
||||
var actionArgs = [item, plugin, self.project, options];
|
||||
|
||||
var action;
|
||||
if (operation === PluginManager.INSTALL) {
|
||||
action = actions.createAction.apply(actions, [installer, actionArgs, uninstaller, actionArgs]);
|
||||
} else /* op === PluginManager.UNINSTALL */{
|
||||
action = actions.createAction.apply(actions, [uninstaller, actionArgs, installer, actionArgs]);
|
||||
}
|
||||
actions.push(action);
|
||||
});
|
||||
|
||||
// ... and run through the action stack
|
||||
return actions.process(this.platform)
|
||||
.then(function () {
|
||||
if (self.project.write) {
|
||||
self.project.write();
|
||||
}
|
||||
|
||||
if (operation === PluginManager.INSTALL) {
|
||||
// Ignore passed `is_top_level` option since platform itself doesn't know
|
||||
// anything about managing dependencies - it's responsibility of caller.
|
||||
self.munger.add_plugin_changes(plugin, options.variables, /*is_top_level=*/true, /*should_increment=*/true);
|
||||
self.munger.platformJson.addPluginMetadata(plugin);
|
||||
} else {
|
||||
self.munger.remove_plugin_changes(plugin, /*is_top_level=*/true);
|
||||
self.munger.platformJson.removePluginMetadata(plugin);
|
||||
}
|
||||
|
||||
// Save everything (munge and plugin/modules metadata)
|
||||
self.munger.save_all();
|
||||
|
||||
var metadata = self.munger.platformJson.generateMetadata();
|
||||
fs.writeFileSync(path.join(self.locations.www, 'cordova_plugins.js'), metadata, 'utf-8');
|
||||
|
||||
// CB-11022 save plugin metadata to both www and platform_www if options.usePlatformWww is specified
|
||||
if (options.usePlatformWww) {
|
||||
fs.writeFileSync(path.join(self.locations.platformWww, 'cordova_plugins.js'), metadata, 'utf-8');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
PluginManager.prototype.addPlugin = function (plugin, installOptions) {
|
||||
return this.doOperation(PluginManager.INSTALL, plugin, installOptions);
|
||||
};
|
||||
|
||||
PluginManager.prototype.removePlugin = function (plugin, uninstallOptions) {
|
||||
return this.doOperation(PluginManager.UNINSTALL, plugin, uninstallOptions);
|
||||
};
|
||||
+8
-1
@@ -42,7 +42,14 @@ module.exports.forwardEventsTo = function (eventEmitter) {
|
||||
if (!(eventEmitter instanceof EventEmitter))
|
||||
throw new Error('Cordova events could be redirected to another EventEmitter instance only');
|
||||
|
||||
EVENTS_RECEIVER = eventEmitter;
|
||||
// CB-10940 Skipping forwarding to self to avoid infinite recursion.
|
||||
// This is the case when the modules are npm-linked.
|
||||
if (this !== eventEmitter) {
|
||||
EVENTS_RECEIVER = eventEmitter;
|
||||
} else {
|
||||
// Reset forwarding if we are subscribing to self
|
||||
EVENTS_RECEIVER = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
var emit = INSTANCE.emit;
|
||||
|
||||
+26
-3
@@ -194,7 +194,7 @@ function findInsertIdx(children, after) {
|
||||
}
|
||||
|
||||
var BLACKLIST = ['platform', 'feature','plugin','engine'];
|
||||
var SINGLETONS = ['content', 'author'];
|
||||
var SINGLETONS = ['content', 'author', 'name'];
|
||||
function mergeXml(src, dest, platform, clobber) {
|
||||
// Do nothing for blacklisted tags.
|
||||
if (BLACKLIST.indexOf(src.tag) != -1) return;
|
||||
@@ -209,6 +209,9 @@ function mergeXml(src, dest, platform, clobber) {
|
||||
if (src.text && (clobber || !dest.text)) {
|
||||
dest.text = src.text;
|
||||
}
|
||||
//Handle children
|
||||
src.getchildren().forEach(mergeChild);
|
||||
|
||||
//Handle platform
|
||||
if (platform) {
|
||||
src.findall('platform[@name="' + platform + '"]').forEach(function (platformElement) {
|
||||
@@ -216,8 +219,8 @@ function mergeXml(src, dest, platform, clobber) {
|
||||
});
|
||||
}
|
||||
|
||||
//Handle children
|
||||
src.getchildren().forEach(mergeChild);
|
||||
//Handle duplicate preference tags (by name attribute)
|
||||
removeDuplicatePreferences(dest);
|
||||
|
||||
function mergeChild (srcChild) {
|
||||
var srcTag = srcChild.tag,
|
||||
@@ -254,6 +257,26 @@ function mergeXml(src, dest, platform, clobber) {
|
||||
dest.append(destChild);
|
||||
}
|
||||
}
|
||||
|
||||
function removeDuplicatePreferences(xml) {
|
||||
// reduce preference tags to a hashtable to remove dupes
|
||||
var prefHash = xml.findall('preference[@name][@value]').reduce(function(previousValue, currentValue) {
|
||||
previousValue[ currentValue.attrib.name ] = currentValue.attrib.value;
|
||||
return previousValue;
|
||||
}, {});
|
||||
|
||||
// remove all preferences
|
||||
xml.findall('preference[@name][@value]').forEach(function(pref) {
|
||||
xml.remove(pref);
|
||||
});
|
||||
|
||||
// write new preferences
|
||||
Object.keys(prefHash).forEach(function(key, index) {
|
||||
var element = et.SubElement(xml, 'preference');
|
||||
element.set('name', key);
|
||||
element.set('value', this[key]);
|
||||
}, prefHash);
|
||||
}
|
||||
}
|
||||
|
||||
// Expose for testing.
|
||||
|
||||
Reference in New Issue
Block a user