You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ka...@apache.org on 2014/05/30 04:46:10 UTC
git commit: Extend PluginInfo to parse more of plugin.xml
Repository: cordova-lib
Updated Branches:
refs/heads/master 39327db7d -> 24bf10d52
Extend PluginInfo to parse more of plugin.xml
Project: http://git-wip-us.apache.org/repos/asf/cordova-lib/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-lib/commit/24bf10d5
Tree: http://git-wip-us.apache.org/repos/asf/cordova-lib/tree/24bf10d5
Diff: http://git-wip-us.apache.org/repos/asf/cordova-lib/diff/24bf10d5
Branch: refs/heads/master
Commit: 24bf10d52c53fd2cd8eb6acdac715aa1a77a5024
Parents: 39327db
Author: Mark Koudritsky <ka...@gmail.com>
Authored: Thu May 22 16:23:14 2014 -0400
Committer: Mark Koudritsky <ka...@gmail.com>
Committed: Thu May 29 22:39:44 2014 -0400
----------------------------------------------------------------------
cordova-lib/spec-cordova/PluginInfo.spec.js | 13 +-
cordova-lib/src/PluginInfo.js | 237 +++++++++++++++++++++--
2 files changed, 229 insertions(+), 21 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/24bf10d5/cordova-lib/spec-cordova/PluginInfo.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/PluginInfo.spec.js b/cordova-lib/spec-cordova/PluginInfo.spec.js
index 4bc16bb..239d4fa 100644
--- a/cordova-lib/spec-cordova/PluginInfo.spec.js
+++ b/cordova-lib/spec-cordova/PluginInfo.spec.js
@@ -27,12 +27,23 @@ var pluginsDir = path.join(__dirname, 'fixtures', 'plugins');
describe('PluginInfo', function () {
it('should read a plugin.xml file', function () {
- var p;
+ var p, prefs, assets, deps, configFiles, infos, srcFiles;
+ var headerFiles, libFiles, resourceFiles;
expect(function () {
p = new PluginInfo.PluginInfo(path.join(pluginsDir, 'ChildBrowser'));
+ prefs = p.getPreferences('android');
+ assets = p.getAssets('android');
+ deps = p.getDependencies('android');
+ configFiles = p.getConfigFiles('android');
+ infos = p.getInfo('android');
+ srcFiles = p.getSourceFiles('android');
+ headerFiles = p.getHeaderFiles('android');
+ libFiles = p.getLibFiles('android');
+ resourceFiles = p.getResourceFiles('android');
}).not.toThrow();
expect(p).toBeDefined();
expect(p.name).toEqual('Child Browser');
+ // TODO: Add some expectations for results of getSomething.
});
it('should throw when there is no plugin.xml file', function () {
expect(function () {
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/24bf10d5/cordova-lib/src/PluginInfo.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/PluginInfo.js b/cordova-lib/src/PluginInfo.js
index 95a579c..1a2fc8d 100644
--- a/cordova-lib/src/PluginInfo.js
+++ b/cordova-lib/src/PluginInfo.js
@@ -22,16 +22,17 @@ A class for holidng the information currently stored in plugin.xml
It should also be able to answer questions like whether the plugin
is compatible with a given engine version.
-For now it's a stub to be gradually extended.
TODO (kamrik): refactor this to use no fs sync fnctions and return promises.
*/
-/* jshint node:true, laxcomma:true */
+/* jshint node:true, laxcomma:true, laxbreak:true, sub:true, strict: false */
-var path = require('path'),
- fs = require('fs'),
- _ = require('underscore'),
- xml_helpers = require('./util/xml-helpers');
+var path = require('path')
+ , fs = require('fs')
+ , _ = require('underscore')
+ , xml_helpers = require('./util/xml-helpers')
+ , CordovaError = require('./CordovaError')
+ ;
// Exports
exports.PluginInfo = PluginInfo;
@@ -41,13 +42,178 @@ exports.loadPluginsDir = loadPluginsDir;
function PluginInfo(dirname) {
var self = this;
- var filepath = path.join(dirname, 'plugin.xml');
- if (!fs.existsSync(filepath)) {
+ // METHODS
+ // Defined inside the constructor to avoid the "this" binding problems.
+
+ // <preference> tag
+ // Example: <preference name="API_KEY" />
+ // Used to require a variable to be specified via --variable when installing the plugin.
+ self.getPreferences = getPreferences;
+ function getPreferences(platform) {
+ var prefs = _getTags(self._et, 'preference', platform, _parsePreference);
+ return prefs;
+ }
+
+ function _parsePreference(prefTag) {
+ var pref = prefTag.attrib.name.toUpperCase();
+ return pref;
+ }
+
+ // <asset>
+ self.getAssets = getAssets;
+ function getAssets(platform) {
+ var assets = _getTags(self._et, 'asset', platform, _parseAsset);
+ return assets;
+ }
+
+ function _parseAsset(tag) {
+ var src = tag.attrib.src;
+ var target = tag.attrib.target;
+
+ if ( !src || !target) {
+ var msg =
+ 'Malformed <asset> tag. Both "src" and "target" attributes'
+ + 'must be specified in\n'
+ + self.filepath
+ ;
+ throw new Error(msg);
+ }
+
+ var asset = { src: src, target: target };
+ return asset;
+ }
+
+
+ // <dependency>
+ // Example:
+ // <dependency id="com.plugin.id"
+ // url="https://github.com/myuser/someplugin"
+ // commit="428931ada3891801"
+ // subdir="some/path/here" />
+ self.getDependencies = getDependencies;
+ function getDependencies(platform) {
+ var deps = _getTags(
+ self._et,
+ 'dependency',
+ platform,
+ _parseDependency
+ );
+ return deps;
+ }
+
+ function _parseDependency(tag) {
+ var dep =
+ { id : tag.attrib.id
+ , url : tag.attrib.url || ''
+ , subdir : tag.attrib.subdir || ''
+ , commit : tag.attrib.commit
+ };
+
+ dep.git_ref = dep.commit;
+
+ if ( !dep.id ) {
+ var msg =
+ '<dependency> tag is missing id attribute in '
+ + self.filepath
+ ;
+ throw new CordovaError(msg);
+ }
+ return dep;
+ }
+
+
+ // <config-file> tag
+ self.getConfigFiles = getConfigFiles;
+ function getConfigFiles(platform) {
+ var configFiles = _getTags(self._et, 'config-file', platform, _parseConfigFile);
+ return configFiles;
+ }
+
+ function _parseConfigFile(tag) {
+ var configFile =
+ { target : tag.attrib['target']
+ , parent : tag.attrib['parent']
+ , after : tag.attrib['after']
+ , xmls : tag.getchildren()
+ };
+ return configFile;
+ }
+
+ // <info> tags, both global and within a <platform>
+ // TODO (kamrik): Do we ever use <info> under <platform>? Example wanted.
+ self.getInfo = getInfo;
+ function getInfo(platform) {
+ var infos = _getTags(
+ self._et,
+ 'info',
+ platform,
+ function(elem) { return elem.text; }
+ );
+ // Filter out any undefined or empty strings.
+ infos = infos.filter(Boolean);
+ return infos;
+ }
+
+ // <source-file>
+ // Examples:
+ // <source-file src="src/ios/someLib.a" framework="true" />
+ // <source-file src="src/ios/someLib.a" compiler-flags="-fno-objc-arc" />
+ self.getSourceFiles = getSourceFiles;
+ function getSourceFiles(platform) {
+ var sourceFiles = _getTagsInPlatform(self._et, 'source-file', platform, _parseSourceFile);
+ return sourceFiles;
+ }
+
+ function _parseSourceFile(tag) {
+ var srcFile = _.clone(tag.attrib);
+ srcFile.framework = isStrTrue(srcFile.framework);
+ return srcFile;
+ }
+
+ // <header-file>
+ // Example:
+ // <header-file src="CDVFoo.h" />
+ self.getHeaderFiles = getHeaderFiles;
+ function getHeaderFiles(platform) {
+ var headerFiles = _getTagsInPlatform(self._et, 'header-file', platform, cloneAttribs);
+ return headerFiles;
+ }
+
+ // <resource-file>
+ // Example:
+ // <resource-file src="FooPluginStrings.xml" target="res/values/FooPluginStrings.xml" />
+ self.getResourceFiles = getResourceFiles;
+ function getResourceFiles(platform) {
+ var resourceFiles = _getTagsInPlatform(self._et, 'resource-file', platform, cloneAttribs);
+ return resourceFiles;
+ }
+
+ // <lib-file>
+ // Example:
+ // <lib-file src="src/BlackBerry10/native/device/libfoo.so" arch="device" />
+ self.getLibFiles = getLibFiles;
+ function getLibFiles(platform) {
+ var libFiles = _getTagsInPlatform(self._et, 'lib-file', platform, cloneAttribs);
+ return libFiles;
+ }
+
+ // Tell whether there is a <platform> section for the given platform.
+ self.hasPlatformSection = hasPlatformSection;
+ function hasPlatformSection(platform) {
+ var platformTag = pelem.find('./platform[@name="' + platform + '"]');
+ return !!platformTag;
+ }
+ ///// End of PluginInfo methods /////
+
+
+ ///// PluginInfo Constructor logic /////
+ self.filepath = path.join(dirname, 'plugin.xml');
+ if (!fs.existsSync(self.filepath)) {
throw new Error('Could not find plugin info in ' + dirname);
}
- self.path = dirname;
- var et = self._et = xml_helpers.parseElementtreeSync(filepath);
+ self.dir = dirname;
+ var et = self._et = xml_helpers.parseElementtreeSync(self.filepath);
var pelem = et.getroot();
self.id = pelem.attrib.id;
self.version = pelem.attrib.version;
@@ -59,18 +225,38 @@ function PluginInfo(dirname) {
self.repo = pelem.findtext('repo');
self.issue = pelem.findtext('issue');
self.keywords = pelem.findtext('keywords');
- if (self.keywords)
- self.keywords = self.keywords.split(',').map( function(s) { return s.trim() } );
-
- self.deps = {};
- et.findall('dependency').forEach(function (d) {
- self.deps[d.attrib.id] = _.clone(d.attrib);
- // If version is not specified we want '' as default.
- // semver.satisifies(x, '') -> true.
- self.deps[d.attrib.id].version = self.deps[d.attrib.id].version || '';
- });
+ self.info = pelem.findtext('info');
+ if (self.keywords) {
+ self.keywords = self.keywords.split(',').map( function(s) { return s.trim(); } );
+ }
+} // End of PluginInfo constructor.
+
+
+// Helper function used by most of the getSomething methods of PluginInfo.
+// Get all elements of a given name. Both in root and in platform sections
+// for the given platform. If transform is given and is a function, it is
+// applied to each element.
+function _getTags(pelem, tag, platform, transform) {
+ var platformTag = pelem.find('./platform[@name="' + platform + '"]');
+ var tagsInRoot = pelem.findall(tag);
+ tagsInRoot = tagsInRoot || [];
+ var tagsInPlatform = platformTag ? platformTag.findall(tag) : [];
+ var tags = tagsInRoot.concat(tagsInPlatform);
+ if ( typeof transform === 'function' ) {
+ tags = tags.map(transform);
+ }
+ return tags;
}
+// Same as _getTags() but only looks inside a platfrom section.
+function _getTagsInPlatform(pelem, tag, platform, transform) {
+ var platformTag = pelem.find('./platform[@name="' + platform + '"]');
+ var tags = platformTag ? platformTag.findall(tag) : [];
+ if ( typeof transform === 'function' ) {
+ tags = tags.map(transform);
+ }
+ return tags;
+}
// Given a dir containing multiple plugins, create a PluginInfo objec for
// each of them and return as array.
@@ -89,4 +275,15 @@ function loadPluginsDir(dirname) {
plugins.push(p);
});
return plugins;
+}
+
+// Used as the default parser for some elements in plugin.xml
+function cloneAttribs(tag) {
+ return _.clone(tag.attrib);
+}
+
+// Check if x is a string 'true'. Allows for variations in case and
+// leading/trailing white space.
+function isStrTrue(x) {
+ return (typeof x === 'string') && (x.trim().toLowerCase() == 'true');
}
\ No newline at end of file