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 2014/09/05 20:14:19 UTC
[14/50] git commit: CB-7142 Add to for "plugin
restore" command
CB-7142 Add <variable> to <feature> for "plugin restore" command
github: close #63
Project: http://git-wip-us.apache.org/repos/asf/cordova-lib/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-lib/commit/6050e93e
Tree: http://git-wip-us.apache.org/repos/asf/cordova-lib/tree/6050e93e
Diff: http://git-wip-us.apache.org/repos/asf/cordova-lib/diff/6050e93e
Branch: refs/heads/master
Commit: 6050e93ece9dc0521f1e70274f769fe7644f80c9
Parents: 3de053c
Author: motorro <mo...@gmail.com>
Authored: Wed Jul 16 05:43:36 2014 +0400
Committer: Anis Kadri <an...@apache.org>
Committed: Fri Sep 5 11:12:18 2014 -0700
----------------------------------------------------------------------
cordova-lib/spec-cordova/ConfigParser.spec.js | 158 +++++++++++++++++++
cordova-lib/spec-cordova/test-config.xml | 24 ++-
cordova-lib/src/configparser/ConfigParser.js | 96 +++++++++++
.../src/configparser/ConfigParser.spec.js | 99 ------------
cordova-lib/src/cordova/platform.js | 17 +-
cordova-lib/src/cordova/prepare.js | 2 +-
cordova-lib/src/cordova/restore.js | 60 +++----
7 files changed, 325 insertions(+), 131 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/6050e93e/cordova-lib/spec-cordova/ConfigParser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/ConfigParser.spec.js b/cordova-lib/spec-cordova/ConfigParser.spec.js
new file mode 100644
index 0000000..9c8c8e6
--- /dev/null
+++ b/cordova-lib/spec-cordova/ConfigParser.spec.js
@@ -0,0 +1,158 @@
+/**
+ 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'),
+ fs = require('fs'),
+ ConfigParser = require('../src/configparser/ConfigParser'),
+ xml = path.join(__dirname, 'test-config.xml'),
+ xml_contents = fs.readFileSync(xml, 'utf-8');
+
+describe('config.xml parser', function () {
+ var readFile;
+ beforeEach(function() {
+ readFile = spyOn(fs, 'readFileSync').andReturn(xml_contents);
+ });
+
+ it('should create an instance based on an xml file', function() {
+ var cfg;
+ expect(function () {
+ cfg = new ConfigParser(xml);
+ }).not.toThrow();
+ expect(cfg).toBeDefined();
+ expect(cfg.doc).toBeDefined();
+ });
+
+ describe('methods', function() {
+ var cfg;
+ beforeEach(function() {
+ cfg = new ConfigParser(xml);
+ });
+
+ describe('package name / id', function() {
+ it('should get the (default) packagename', function() {
+ expect(cfg.packageName()).toEqual('io.cordova.hellocordova');
+ });
+ it('should allow setting the packagename', function() {
+ cfg.setPackageName('this.is.bat.country');
+ expect(cfg.packageName()).toEqual('this.is.bat.country');
+ });
+ });
+
+ describe('version', function() {
+ it('should get the version', function() {
+ expect(cfg.version()).toEqual('0.0.1');
+ });
+ it('should allow setting the version', function() {
+ cfg.setVersion('2.0.1');
+ expect(cfg.version()).toEqual('2.0.1');
+ });
+ });
+
+ describe('app name', function() {
+ it('should get the (default) app name', function() {
+ expect(cfg.name()).toEqual('Hello Cordova');
+ });
+ it('should allow setting the app name', function() {
+ cfg.setName('this.is.bat.country');
+ expect(cfg.name()).toEqual('this.is.bat.country');
+ });
+ });
+ describe('preference', function() {
+ it('should get value of existing preference', function() {
+ expect(cfg.getPreference('fullscreen')).toEqual('true');
+ });
+ it('should get undefined as non existing preference', function() {
+ expect(cfg.getPreference('zimzooo!')).toEqual(undefined);
+ });
+ });
+ describe('feature',function(){
+ it('should read feature id list', function() {
+ var expectedList = [
+ "org.apache.cordova.featurewithvars",
+ "org.apache.cordova.featurewithurl",
+ "org.apache.cordova.featurewithversion",
+ "org.apache.cordova.featurewithurlandversion",
+ "org.apache.cordova.justafeature"
+ ];
+ var list = cfg.getFeatureIdList();
+ expect(list.length).toEqual(expectedList.length);
+ expectedList.forEach(function(feature){
+ expect(list).toContain(feature);
+ });
+ });
+ it('should read feature given id', function(){
+ var feature = cfg.getFeature("org.apache.cordova.justafeature");
+ expect(feature).toBeDefined();
+ expect(feature.name).toEqual("A simple feature");
+ expect(feature.id).toEqual("org.apache.cordova.justafeature");
+ expect(feature.params).toBeDefined();
+ expect(feature.params.id).toBeDefined();
+ expect(feature.params.id).toEqual("org.apache.cordova.justafeature");
+ });
+ it('should not read feature given undefined id', function(){
+ var feature = cfg.getFeature("org.apache.cordova.undefinedfeature");
+ expect(feature).not.toBeDefined();
+ });
+ it('should read feature with url and set \'url\' param', function(){
+ var feature = cfg.getFeature("org.apache.cordova.featurewithurl");
+ expect(feature.url).toEqual("http://cordova.apache.org/featurewithurl");
+ expect(feature.params).toBeDefined();
+ expect(feature.params.url).toBeDefined();
+ expect(feature.params.url).toEqual("http://cordova.apache.org/featurewithurl");
+ });
+ it('should read feature with version and set \'version\' param', function(){
+ var feature = cfg.getFeature("org.apache.cordova.featurewithversion");
+ expect(feature.version).toEqual("1.1.1");
+ expect(feature.params).toBeDefined();
+ expect(feature.params.version).toBeDefined();
+ expect(feature.params.version).toEqual("1.1.1");
+ });
+ it('should read feature variables', function () {
+ var feature = cfg.getFeature("org.apache.cordova.featurewithvars");
+ expect(feature.variables).toBeDefined();
+ expect(feature.variables.var).toBeDefined();
+ expect(feature.variables.var).toEqual("varvalue");
+ });
+ it('should allow adding a new feature', function(){
+ cfg.addFeature('myfeature');
+ var features = cfg.doc.findall('feature');
+ var featureNames = features.map(function(feature){
+ return feature.attrib.name;
+ });
+ expect(featureNames).toContain('myfeature');
+ });
+ it('should allow adding features with params', function(){
+ cfg.addFeature('afeature', JSON.parse('[{"name":"paraname", "value":"paravalue"}]'));
+ var features = cfg.doc.findall('feature');
+ var feature = (function(){
+ var i = features.length;
+ var f;
+ while (--i >= 0) {
+ f = features[i];
+ if ('afeature' === f.attrib.name) return f;
+ }
+ return undefined;
+ })();
+ expect(feature).toBeDefined();
+ var params = feature.findall('param');
+ expect(params[0].attrib.name).toEqual('paraname');
+ expect(params[0].attrib.value).toEqual('paravalue');
+ });
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/6050e93e/cordova-lib/spec-cordova/test-config.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/test-config.xml b/cordova-lib/spec-cordova/test-config.xml
index 5e01e48..3308ae0 100644
--- a/cordova-lib/spec-cordova/test-config.xml
+++ b/cordova-lib/spec-cordova/test-config.xml
@@ -22,5 +22,27 @@
<icon id="logo" src="logo.png" width="255" height="255" />
<platform name="android">
<icon src="logo-android.png" width="255" height="255" density="mdpi" />
- </platform>
+ </platform>
+
+ <!-- Features -->
+ <feature name="A feature with preference">
+ <param name="id" value="org.apache.cordova.featurewithvars"/>
+ <variable name="var" value="varvalue"/>
+ </feature>
+ <feature name="A feature with url">
+ <param name="id" value="org.apache.cordova.featurewithurl" />
+ <param name="url" value="http://cordova.apache.org/featurewithurl" />
+ </feature>
+ <feature name="A feature with version">
+ <param name="id" value="org.apache.cordova.featurewithversion" />
+ <param name="version" value="1.1.1" />
+ </feature>
+ <feature name="A feature with url and version">
+ <param name="id" value="org.apache.cordova.featurewithurlandversion" />
+ <param name="version" value="1.1.1" />
+ <param name="url" value="http://cordova.apache.org/featurewithurlandversion" />
+ </feature>
+ <feature name="A simple feature">
+ <param name="id" value="org.apache.cordova.justafeature" />
+ </feature>
</widget>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/6050e93e/cordova-lib/src/configparser/ConfigParser.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/configparser/ConfigParser.js b/cordova-lib/src/configparser/ConfigParser.js
index 84de2a6..75f798b 100644
--- a/cordova-lib/src/configparser/ConfigParser.js
+++ b/cordova-lib/src/configparser/ConfigParser.js
@@ -27,6 +27,15 @@ var et = require('elementtree'),
CordovaError = require('../CordovaError'),
fs = require('fs');
+/**
+ * Array of 'feature' params that are set as properties
+ * @type {string[]}
+ */
+var FEATURE_SPECIAL_PARAMS = [
+ 'id',
+ 'url',
+ 'version'
+];
/** Wraps a config.xml file */
function ConfigParser(path) {
@@ -217,6 +226,93 @@ ConfigParser.prototype = {
},
/**
+ * Returns a list of features (IDs)
+ * @return {string[]} Array of feature IDs
+ */
+ getFeatureIdList: function () {
+ var features = this.doc.findall('feature'),
+ feature, idTag, id,
+ result = [];
+
+ // Check for valid features that have IDs set
+ for (var i = 0, l = features.length; i < l; ++i) {
+ feature = features[i];
+ idTag = feature.find('./param[@name="id"]');
+ if (null === idTag) {
+ // Invalid feature
+ continue;
+ }
+ id = idTag.attrib.value;
+ if (!!id) {
+ // Has id and id is non-empty
+ result.push(id);
+ }
+ }
+
+ return result;
+ },
+
+ /**
+ * Gets feature info
+ * @param {string} id Feature id
+ * @returns {Feature} Feature object
+ */
+ getFeature: function(id) {
+ if (!id) {
+ return undefined;
+ }
+ var feature = this.doc.find('./feature/param[@name="id"][@value="' + id + '"]/..');
+ if (null === feature) {
+ return undefined;
+ }
+
+ var result = {};
+ result.id = id;
+ result.name = feature.attrib.name;
+
+ // Iterate params and fill-in 'params' structure
+ // For special cases like 'id', 'url, 'version' - copy to the main space
+ result.params = processChildren (
+ 'param',
+ function(name, value) {
+ if (FEATURE_SPECIAL_PARAMS.indexOf(name) >= 0) {
+ result[name] = value;
+ }
+ }
+ );
+
+ // Iterate preferences
+ result.variables = processChildren('variable');
+
+ return result;
+
+ /**
+ * Processes a set of children
+ * having a pair of 'name' and 'value' attributes
+ * filling in 'output' object
+ * @param {string} xPath Search expression
+ * @param {function} [specialProcessing] Performs some additional actions on each valid element
+ * @return {object} A transformed object
+ */
+ function processChildren (xPath, specialProcessing) {
+ var result = {};
+ var needsProcessing = 'function' === typeof specialProcessing;
+ var nodes = feature.findall(xPath);
+ nodes.forEach(function(param){
+ var name = param.attrib.name;
+ var value = param.attrib.value;
+ if (name) {
+ result[name] = value;
+ if (needsProcessing) {
+ specialProcessing(name, value);
+ }
+ }
+ });
+ return result;
+ }
+ },
+
+ /**
*This does not check for duplicate feature entries
*/
addFeature: function (name, params){
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/6050e93e/cordova-lib/src/configparser/ConfigParser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/configparser/ConfigParser.spec.js b/cordova-lib/src/configparser/ConfigParser.spec.js
deleted file mode 100644
index a1ba102..0000000
--- a/cordova-lib/src/configparser/ConfigParser.spec.js
+++ /dev/null
@@ -1,99 +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 path = require('path'),
- fs = require('fs'),
- ConfigParser = require('../src/cordova/ConfigParser'),
- xml = path.join(__dirname, 'test-config.xml'),
- xml_contents = fs.readFileSync(xml, 'utf-8');
-
-describe('config.xml parser', function () {
- var readFile;
- beforeEach(function() {
- readFile = spyOn(fs, 'readFileSync').andReturn(xml_contents);
- });
-
- it('should create an instance based on an xml file', function() {
- var cfg;
- expect(function () {
- cfg = new ConfigParser(xml);
- }).not.toThrow();
- expect(cfg).toBeDefined();
- expect(cfg.doc).toBeDefined();
- });
-
- describe('methods', function() {
- var cfg;
- beforeEach(function() {
- cfg = new ConfigParser(xml);
- });
-
- describe('package name / id', function() {
- it('should get the (default) packagename', function() {
- expect(cfg.packageName()).toEqual('io.cordova.hellocordova');
- });
- it('should allow setting the packagename', function() {
- cfg.setPackageName('this.is.bat.country');
- expect(cfg.packageName()).toEqual('this.is.bat.country');
- });
- });
-
- describe('version', function() {
- it('should get the version', function() {
- expect(cfg.version()).toEqual('0.0.1');
- });
- it('should allow setting the version', function() {
- cfg.setVersion('2.0.1');
- expect(cfg.version()).toEqual('2.0.1');
- });
- });
-
- describe('app name', function() {
- it('should get the (default) app name', function() {
- expect(cfg.name()).toEqual('Hello Cordova');
- });
- it('should allow setting the app name', function() {
- cfg.setName('this.is.bat.country');
- expect(cfg.name()).toEqual('this.is.bat.country');
- });
- });
- describe('preference', function() {
- it('should get value of existing preference', function() {
- expect(cfg.getPreference('fullscreen')).toEqual('true');
- });
- it('should get undefined as non existing preference', function() {
- expect(cfg.getPreference('zimzooo!')).toEqual(undefined);
- });
- });
- describe('feature',function(){
- it('should allow adding a new feature', function(){
- cfg.addFeature('myfeature');
- var features = cfg.doc.findall('feature');
- expect(features[0].attrib.name).toEqual('myfeature');
- });
- it('should allow adding features with params', function(){
- cfg.addFeature('afeature', JSON.parse('[{"name":"paraname", "value":"paravalue"}]'));
- var features = cfg.doc.findall('feature');
- expect(features[0].attrib.name).toEqual('afeature');
- var params = features[0].findall('param');
- expect(params[0].attrib.name).toEqual('paraname');
- expect(params[0].attrib.value).toEqual('paravalue');
- });
- });
- });
-});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/6050e93e/cordova-lib/src/cordova/platform.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/platform.js b/cordova-lib/src/cordova/platform.js
index 2cb8c2e..7a01783 100644
--- a/cordova-lib/src/cordova/platform.js
+++ b/cordova-lib/src/cordova/platform.js
@@ -454,7 +454,22 @@ function call_into_create(target, projectRoot, cfg, libDir, template_dir, opts)
return plugins.reduce(function(soFar, plugin) {
return soFar.then(function() {
events.emit('verbose', 'Installing plugin "' + plugin + '" following successful platform add of ' + target);
- return plugman.raw.install(target, output, path.basename(plugin), plugins_dir);
+ plugin = path.basename(plugin);
+ var options = (function(){
+ // Get plugin preferences from config features if have any
+ // Pass them as cli_variables to plugman
+ var feature = cfg.getFeature(plugin);
+ var variables = feature && feature.variables;
+ if (!!variables) {
+ events.emit('verbose', 'Found variables for "' + plugin + '". Processing as cli_variables.');
+ return {
+ cli_variables: variables
+ };
+ }
+ return null;
+ })();
+
+ return plugman.raw.install(target, output, plugin, plugins_dir, options);
});
}, Q());
});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/6050e93e/cordova-lib/src/cordova/prepare.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/prepare.js b/cordova-lib/src/cordova/prepare.js
index c69a4d7..09be122 100644
--- a/cordova-lib/src/cordova/prepare.js
+++ b/cordova-lib/src/cordova/prepare.js
@@ -126,7 +126,7 @@ function prepare(options) {
});
}
-var BLACKLIST = ['platform'];
+var BLACKLIST = ['platform', 'feature'];
var SINGLETONS = ['content', 'author'];
function mergeXml(src, dest, platform, clobber) {
// Do nothing for blacklisted tags.
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/6050e93e/cordova-lib/src/cordova/restore.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/restore.js b/cordova-lib/src/cordova/restore.js
index ffd1edc..6e4d262 100644
--- a/cordova-lib/src/cordova/restore.js
+++ b/cordova-lib/src/cordova/restore.js
@@ -60,39 +60,41 @@ function installPlatformsFromConfigXML(cfg){
//returns a Promise
function installPluginsFromConfigXML(cfg) {
//Install plugins that are listed on config.xml
- var pluginsFromConfig = [];
var projectRoot = cordova_util.cdProjectRoot();
var plugins_dir = path.join(projectRoot, 'plugins');
- var features = cfg.doc.findall('feature');
- features.forEach(function(feature){
- var params = feature.findall('param');
- var pluginId = '';
- var pluginVersion = '';
- for (var i = 0; i < params.length; i++) {
- if (params[i].attrib.name === 'id') {
- pluginId = params[i].attrib.value;
- }
- if (params[i].attrib.name === 'version') {
- pluginVersion = params[i].attrib.value;
- }
+ // Get all configured plugins
+ var features = cfg.getFeatureIdList();
+ if (0 === features.length) {
+ return Q.all('No config.xml plugins to install');
+ }
+
+ return features.reduce(function(soFar, featureId) {
+
+ var pluginPath = path.join(plugins_dir, featureId);
+ if (fs.existsSync(pluginPath)) {
+ // Plugin already exists
+ return soFar;
}
- var pluginPath = path.join(plugins_dir,pluginId);
- // contents of the plugins folder takes precedence hence
- // we ignore if the correct version is installed or not.
- if (pluginId !== '' && !fs.existsSync(pluginPath)) {
- if ( pluginVersion !== '') {
- pluginId = pluginId + '@' + pluginVersion;
+
+ return soFar.then(function() {
+ events.emit('log', 'Discovered ' + featureId + ' in config.xml. Installing to the project');
+
+ var feature = cfg.getFeature(featureId);
+
+ // Install from given URL if defined or using a plugin id
+ var installFrom = feature.url;
+ if (!installFrom) {
+ installFrom = feature.id;
+ if (!!feature.version) {
+ installFrom += ('@' + feature.version);
+ }
}
- events.emit('log', 'Discovered ' + pluginId + ' in config.xml. Installing to the project');
- pluginsFromConfig.push(pluginId);
- }
- });
- //Use cli instead of plugman directly ensuring all the hooks
- // to get fired.
- if (pluginsFromConfig.length >0) {
- return plugin('add', pluginsFromConfig);
- }
- return Q.all('No config.xml plugins to install');
+ // Add feature preferences as CLI variables if have any
+ var options = 'undefined' !== typeof feature.variables ? {cli_variables: feature.variables} : null;
+
+ return plugin('add', installFrom, options);
+ });
+ }, Q());
}