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/06/03 20:50:02 UTC
[2/2] git commit: CB-6698: Support library references for Android via
the framework tag
CB-6698: Support library references for Android via the framework tag
Project: http://git-wip-us.apache.org/repos/asf/cordova-lib/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-lib/commit/513967db
Tree: http://git-wip-us.apache.org/repos/asf/cordova-lib/tree/513967db
Diff: http://git-wip-us.apache.org/repos/asf/cordova-lib/diff/513967db
Branch: refs/heads/master
Commit: 513967dbc8f983ebfe08ba7b96cfc4211ffd7515
Parents: 71e7ba3
Author: Martin Bektchiev <ma...@telerik.com>
Authored: Tue May 27 14:53:19 2014 +0300
Committer: Mark Koudritsky <ka...@gmail.com>
Committed: Tue Jun 3 14:44:03 2014 -0400
----------------------------------------------------------------------
cordova-lib/npm-shrinkwrap.json | 3 +
cordova-lib/package.json | 49 ++++----
.../spec-plugman/platforms/android.spec.js | 91 +++++++++++++++
.../spec-plugman/util/action-stack.spec.js | 14 +--
cordova-lib/src/plugman/install.js | 2 +-
cordova-lib/src/plugman/platforms/android.js | 115 ++++++++++++++++++-
cordova-lib/src/plugman/platforms/ios.js | 2 +-
cordova-lib/src/plugman/util/config-changes.js | 22 ++--
8 files changed, 252 insertions(+), 46 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/513967db/cordova-lib/npm-shrinkwrap.json
----------------------------------------------------------------------
diff --git a/cordova-lib/npm-shrinkwrap.json b/cordova-lib/npm-shrinkwrap.json
index 2debb81..3e53081 100644
--- a/cordova-lib/npm-shrinkwrap.json
+++ b/cordova-lib/npm-shrinkwrap.json
@@ -464,6 +464,9 @@
}
}
},
+ "properties-parser": {
+ "from": "git://github.com/mbektchiev/node-properties-parser#cordova-lib"
+ },
"q": {
"version": "0.9.7",
"from": "q@~0.9"
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/513967db/cordova-lib/package.json
----------------------------------------------------------------------
diff --git a/cordova-lib/package.json b/cordova-lib/package.json
index 77344bd..fda29d6 100644
--- a/cordova-lib/package.json
+++ b/cordova-lib/package.json
@@ -8,36 +8,37 @@
"url": "git://git-wip-us.apache.org/repos/asf/cordova-lib.git"
},
"bugs": {
- "url" : "https://issues.apache.org/jira/browse/CB",
- "email" : "dev@cordova.apache.org"
+ "url": "https://issues.apache.org/jira/browse/CB",
+ "email": "dev@cordova.apache.org"
},
"main": "cordova-lib.js",
"engines": {
"node": ">=0.9.9"
},
- "engineStrict":true,
+ "engineStrict": true,
"dependencies": {
- "glob": "3.2.x",
+ "bplist-parser": "0.0.x",
+ "dep-graph": "1.1.0",
"elementtree": "0.1.5",
- "xcode": "0.6.6",
+ "glob": "3.2.x",
+ "mime": "~1.2.11",
+ "npm": "1.3.4",
+ "npmconf": "0.1.x",
+ "osenv": "0.0.x",
"plist-with-patches": "0.5.x",
- "bplist-parser": "0.0.x",
- "shelljs": "0.1.x",
- "underscore":"1.4.4",
- "dep-graph":"1.1.0",
- "semver": "2.0.x",
+ "properties-parser": "git://github.com/mbektchiev/node-properties-parser",
"q": "~0.9",
- "npm": "1.3.4",
"rc": "0.3.0",
- "tar": "0.1.x",
"request": "2.22.0",
- "npmconf": "0.1.x",
- "mime": "~1.2.11",
- "osenv": "0.0.x"
+ "semver": "2.0.x",
+ "shelljs": "0.1.x",
+ "tar": "0.1.x",
+ "underscore": "1.4.4",
+ "xcode": "0.6.6"
},
"devDependencies": {
"temp": "0.6.x",
- "jasmine-node": "~1"
+ "jasmine-node": "~1"
},
"scripts": {
"test": "jasmine-node --color spec-plugman spec-cordova"
@@ -136,26 +137,26 @@
"email": "stevengill97@gmail.com"
},
{
- "name":"Jesse",
- "email":"purplecabbage@gmail.com"
+ "name": "Jesse",
+ "email": "purplecabbage@gmail.com"
},
{
- "name":"Anis Kadri"
+ "name": "Anis Kadri"
},
{
- "name":"Ryan Willoughby"
+ "name": "Ryan Willoughby"
},
{
- "name":"Brett Rudd"
+ "name": "Brett Rudd"
},
{
- "name":"Shazron Abdullah"
+ "name": "Shazron Abdullah"
},
{
- "name":"Steve Gill"
+ "name": "Steve Gill"
},
{
- "name":"Jesse MacFadyen"
+ "name": "Jesse MacFadyen"
}
]
}
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/513967db/cordova-lib/spec-plugman/platforms/android.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/platforms/android.spec.js b/cordova-lib/spec-plugman/platforms/android.spec.js
index 1bacc27..df11ec7 100644
--- a/cordova-lib/spec-plugman/platforms/android.spec.js
+++ b/cordova-lib/spec-plugman/platforms/android.spec.js
@@ -6,6 +6,7 @@ var android = require('../../src/plugman/platforms/android'),
shell = require('shelljs'),
et = require('elementtree'),
os = require('osenv'),
+ _ = require('underscore'),
temp = path.join(os.tmpdir(), 'plugman'),
plugins_dir = path.join(temp, 'cordova', 'plugins'),
xml_helpers = require('../../src/util/xml-helpers'),
@@ -113,6 +114,75 @@ describe('android project handler', function() {
}).toThrow('"' + target + '" already exists!');
});
});
+ describe('of <framework> elements', function() {
+ afterEach(function() {
+ android.purgeProjectFileCache(temp);
+ });
+ it('should update the main and library projects', function() {
+ var frameworkElement = { attrib: { src: "LibraryPath", custom: true } };
+ var subDir = path.resolve(temp, frameworkElement.attrib.src);
+ var mainProjectPropsFile = path.resolve(temp, "project.properties");
+ var subProjectPropsFile = path.resolve(subDir, "project.properties");
+
+ var existsSync = spyOn( fs, 'existsSync').andReturn(true);
+ var writeFileSync = spyOn(fs, 'writeFileSync');
+ var readFileSync = spyOn(fs, 'readFileSync').andCallFake(function (file) {
+ if (path.normalize(file) === mainProjectPropsFile) {
+ return '#Some comment\ntarget=android-19\nandroid.library.reference.1=ExistingLibRef1\nandroid.library.reference.2=ExistingLibRef2';
+ } else if (path.normalize(file) === subProjectPropsFile) {
+ return '#Some comment\ntarget=android-17\nandroid.library=true';
+ } else {
+ throw new Error("Trying to read from an unexpected file " + file);
+ }
+ })
+ var exec = spyOn(shell, 'exec');
+
+ android['framework'].install(frameworkElement, dummyplugin, temp);
+ android.parseProjectFile(temp).write();
+
+ expect(_.any(writeFileSync.argsForCall, function (callArgs) {
+ return callArgs[0] === mainProjectPropsFile && callArgs[1].indexOf('\nandroid.library.reference.3=LibraryPath\n') > -1;
+ })).toBe(true, 'Reference to library not added');
+ expect(_.any(writeFileSync.argsForCall, function (callArgs) {
+ return callArgs[0] === subProjectPropsFile && callArgs[1].indexOf('\ntarget=android-19\n') > -1;
+ })).toBe(true, 'target SDK version not copied to library');
+ expect(exec).toHaveBeenCalledWith('android update lib-project --path ' + subDir);
+ });
+ it('with custom=false should update the main and library projects', function() {
+ var frameworkElement = { attrib: { src: "extras/android/support/v7/appcompat" } };
+ var subDir = path.resolve("~/android-sdk", frameworkElement.attrib.src);
+ var localPropsFile = path.resolve(temp, "local.properties");
+ var mainProjectPropsFile = path.resolve(temp, "project.properties");
+ var subProjectPropsFile = path.resolve(subDir, "project.properties");
+
+ var existsSync = spyOn( fs, 'existsSync').andReturn(true);
+ var writeFileSync = spyOn(fs, 'writeFileSync');
+ var readFileSync = spyOn(fs, 'readFileSync').andCallFake(function (file) {
+ if (path.normalize(file) === mainProjectPropsFile) {
+ return '#Some comment\ntarget=android-19\nandroid.library.reference.1=ExistingLibRef1\nandroid.library.reference.2=ExistingLibRef2';
+ } else if (path.normalize(file) === subProjectPropsFile) {
+ return '#Some comment\ntarget=android-17\nandroid.library=true';
+ } else if (path.normalize(file) === localPropsFile) {
+ return "sdk.dir=~/android-sdk";
+ } else {
+ throw new Error("Trying to read from an unexpected file " + file);
+ }
+ })
+ var exec = spyOn(shell, 'exec');
+
+ android['framework'].install(frameworkElement, dummyplugin, temp);
+ android.parseProjectFile(temp).write();
+
+ var relativePath = android.getRelativeLibraryPath(temp, subDir);
+ expect(_.any(writeFileSync.argsForCall, function (callArgs) {
+ return callArgs[0] === mainProjectPropsFile && callArgs[1].indexOf('\nandroid.library.reference.3=' + relativePath + '\n') > -1;
+ })).toBe(true, 'Reference to library not added');
+ expect(_.any(writeFileSync.argsForCall, function (callArgs) {
+ return callArgs[0] === subProjectPropsFile && callArgs[1].indexOf('\ntarget=android-19\n') > -1;
+ })).toBe(true, 'target SDK version not copied to library');
+ expect(exec).toHaveBeenCalledWith('android update lib-project --path ' + subDir);
+ });
+ });
});
describe('uninstallation', function() {
@@ -152,5 +222,26 @@ describe('android project handler', function() {
});
});
});
+ describe('of <framework> elements', function() {
+ it('should remove library reference from the main project', function() {
+ var frameworkElement = { attrib: { src: "LibraryPath" } };
+ var sub_dir = path.resolve(temp, frameworkElement.attrib.src);
+ var mainProjectProps = path.resolve(temp, "project.properties");
+ var existsSync = spyOn( fs, 'existsSync').andReturn(true);
+ var writeFileSync = spyOn(fs, 'writeFileSync');
+ var readFileSync = spyOn(fs, 'readFileSync').andCallFake(function (file) {
+ if (path.normalize(file) === mainProjectProps)
+ return '#Some comment\ntarget=android-19\nandroid.library.reference.1=ExistingLibRef1\nandroid.library.reference.2=LibraryPath\nandroid.library.reference.3=ExistingLibRef2\n';
+ })
+ var exec = spyOn(shell, 'exec');
+
+ android['framework'].uninstall(frameworkElement, temp);
+ android.parseProjectFile(temp).write();
+
+ expect(_.any(writeFileSync.argsForCall, function (callArgs) {
+ return callArgs[0] === mainProjectProps && callArgs[1].indexOf('\nandroid.library.reference.2=ExistingLibRef2\n') > -1;
+ })).toBe(true, 'Reference to library not removed');
+ });
+ });
});
});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/513967db/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 ef59164..b55ce73 100644
--- a/cordova-lib/spec-plugman/util/action-stack.spec.js
+++ b/cordova-lib/spec-plugman/util/action-stack.spec.js
@@ -18,9 +18,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', 'blah');
- expect(first_spy).toHaveBeenCalledWith(first_args[0]);
- expect(second_spy).toHaveBeenCalledWith(second_args[0]);
- expect(third_spy).toHaveBeenCalledWith(third_args[0]);
+ 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));
});
it('should revert processed actions if an exception occurs', function() {
spyOn(console, 'log');
@@ -47,11 +47,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]);
- expect(second_spy).toHaveBeenCalledWith(second_args[0]);
- expect(third_spy).not.toHaveBeenCalledWith(third_args[0]);
+ 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));
// first reverter should have been called after second action exploded
- expect(first_reverter).toHaveBeenCalledWith(first_reverter_args[0]);
+ expect(first_reverter).toHaveBeenCalledWith(first_reverter_args[0], jasmine.any(Object));
});
});
});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/513967db/cordova-lib/src/plugman/install.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/install.js b/cordova-lib/src/plugman/install.js
index d779989..2fbbe50 100644
--- a/cordova-lib/src/plugman/install.js
+++ b/cordova-lib/src/plugman/install.js
@@ -493,7 +493,7 @@ function handleInstall(actions, pluginInfo, platform, project_dir, plugins_dir,
var sourceFiles = platformTag.findall('./source-file'),
headerFiles = platformTag.findall('./header-file'),
resourceFiles = platformTag.findall('./resource-file'),
- frameworkFiles = platformTag.findall('./framework[@custom="true"]'), // CB-5238 adding only custom frameworks
+ frameworkFiles = platformTag.findall('./framework'),
libFiles = platformTag.findall('./lib-file');
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/513967db/cordova-lib/src/plugman/platforms/android.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/platforms/android.js b/cordova-lib/src/plugman/platforms/android.js
index 0147d08..e105c5b 100644
--- a/cordova-lib/src/plugman/platforms/android.js
+++ b/cordova-lib/src/plugman/platforms/android.js
@@ -21,7 +21,11 @@ var fs = require('fs') // use existsSync in 0.6.x
, path = require('path')
, common = require('./common')
, events = require('../events')
- , xml_helpers = require(path.join(__dirname, '..', '..', 'util', 'xml-helpers'));
+ , xml_helpers = require(path.join(__dirname, '..', '..', 'util', 'xml-helpers'))
+ , properties_parser = require('properties-parser')
+ , shell = require('shelljs');
+
+var projectFileCache = {};
module.exports = {
www_dir:function(project_dir) {
@@ -80,10 +84,115 @@ module.exports = {
},
"framework": {
install:function(source_el, plugin_dir, project_dir, plugin_id) {
- events.emit('verbose', 'framework.install is not supported for android');
+ var src = source_el.attrib.src;
+ var custom = source_el.attrib.custom;
+ if (!src) throw new Error('src not specified in framework element');
+
+ events.emit('verbose', "Installing Android library: " + src);
+ var parent = source_el.attrib.parent;
+ var parentDir = parent ? path.resolve(project_dir, parent) : project_dir;
+ var subDir;
+ if (custom) {
+ subDir = path.resolve(project_dir, src);
+ } else {
+ var localProperties = properties_parser.createEditor(path.resolve(project_dir, "local.properties"));
+ subDir = path.resolve(localProperties.get("sdk.dir"), src);
+ }
+ var projectConfig = module.exports.parseProjectFile(project_dir);
+ projectConfig.addSubProject(parentDir, subDir);
},
uninstall:function(source_el, project_dir, plugin_id) {
- events.emit('verbose', 'framework.uninstall is not supported for android');
+ var src = source_el.attrib.src;
+ if (!src) throw new Error('src not specified in framework element');
+
+ events.emit('verbose', "Uninstalling Android library: " + src);
+ var parent = source_el.attrib.parent;
+ var parentDir = parent ? path.resolve(project_dir, parent) : project_dir;
+ var subDir = path.resolve(project_dir, src);
+ var projectConfig = module.exports.parseProjectFile(project_dir);
+ projectConfig.removeSubProject(parentDir, subDir);
}
+ },
+ parseProjectFile: function(project_dir){
+ if (!projectFileCache[project_dir]) {
+ projectFileCache[project_dir] = {
+ propertiesEditors: {},
+ subProjectDirs : {},
+ addSubProject: function(parentDir, subDir) {
+ var subProjectFile = path.resolve(subDir, "project.properties");
+ if (!fs.existsSync(subProjectFile)) throw new Error('cannot find "' + subProjectFile + '" referenced in <framework>');
+
+ var parentProjectFile = path.resolve(parentDir, "project.properties");
+ var parentProperties = this._getPropertiesFile(parentProjectFile);
+ addLibraryReference(parentProperties, module.exports.getRelativeLibraryPath(parentDir, subDir));
+
+ var subProperties = this._getPropertiesFile(subProjectFile);
+ subProperties.set("target", parentProperties.get("target"));
+
+ this.subProjectDirs[subDir] = true;
+ this._dirty = true;
+ },
+ removeSubProject: function(parentDir, subDir) {
+ var parentProjectFile = path.resolve(parentDir, "project.properties");
+ var parentProperties = this._getPropertiesFile(parentProjectFile);
+ removeLibraryReference(parentProperties, module.exports.getRelativeLibraryPath(parentDir, subDir));
+ delete this.subProjectDirs[subDir];
+ this._dirty = true;
+ },
+ write: function () {
+ if (!this._dirty) return;
+
+ for (var filename in this.propertiesEditors) {
+ fs.writeFileSync(filename, this.propertiesEditors[filename].toString());
+ }
+
+ for (var sub_dir in this.subProjectDirs)
+ {
+ shell.exec("android update lib-project --path " + sub_dir);
+ }
+ this._dirty = false;
+ },
+ _dirty : false,
+ _getPropertiesFile: function (filename) {
+ if (!this.propertiesEditors[filename])
+ this.propertiesEditors[filename] = properties_parser.createEditor(filename);
+
+ return this.propertiesEditors[filename];
+ }
+ };
+ }
+
+ return projectFileCache[project_dir];
+ },
+ purgeProjectFileCache:function(project_dir) {
+ delete projectFileCache[project_dir];
+ },
+ getRelativeLibraryPath: function (parentDir, subDir) {
+ var libraryPath = path.relative(parentDir, subDir);
+ return (path.sep == '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
}
};
+
+function addLibraryReference(projectProperties, libraryPath) {
+ var i = 1;
+ while (projectProperties.get("android.library.reference." + i))
+ i++;
+
+ projectProperties.set("android.library.reference." + i, libraryPath);
+}
+
+function removeLibraryReference(projectProperties, libraryPath) {
+ var i = 1;
+ var currentLib;
+ while (currentLib = projectProperties.get("android.library.reference." + i)) {
+ if (currentLib === libraryPath) {
+ while (currentLib = projectProperties.get("android.library.reference." + (i + 1))) {
+ projectProperties.set("android.library.reference." + i, currentLib);
+ i++;
+ }
+ projectProperties.set("android.library.reference." + i);
+ break;
+ }
+ i++;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/513967db/cordova-lib/src/plugman/platforms/ios.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/platforms/ios.js b/cordova-lib/src/plugman/platforms/ios.js
index 4f570c3..1c5d8ea 100644
--- a/cordova-lib/src/plugman/platforms/ios.js
+++ b/cordova-lib/src/plugman/platforms/ios.js
@@ -125,7 +125,7 @@ module.exports = {
custom = framework_el.attrib['custom'],
srcFile = path.resolve(plugin_dir, src),
targetDir = path.resolve(project.plugins_dir, plugin_id, path.basename(src));
- if (!custom) throw new Error('cannot add non custom frameworks.');
+ if (!custom) return; //non-custom frameworks are processed in config-changes.js
if (!fs.existsSync(srcFile)) throw new Error('cannot find "' + srcFile + '" ios <framework>');
if (fs.existsSync(targetDir)) throw new Error('target destination "' + targetDir + '" already exists');
shell.mkdir('-p', path.dirname(targetDir));
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/513967db/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 bc24a7f..8e3b614 100644
--- a/cordova-lib/src/plugman/util/config-changes.js
+++ b/cordova-lib/src/plugman/util/config-changes.js
@@ -305,16 +305,18 @@ function generate_plugin_config_munge(plugin_dir, vars) {
// note down pbxproj framework munges in special section of munge obj
// CB-5238 this is only for systems frameworks
- var frameworks = platformTag.findall('framework');
- frameworks.forEach(function(f) {
- var custom = f.attrib['custom'];
- if(!custom) {
- var file = f.attrib['src'];
- var weak = ('true' == f.attrib['weak']).toString();
-
- deep_add(munge, 'framework', file, { xml: weak, count: 1 });
- }
- });
+ if (self.platform === 'ios') {
+ var frameworks = platformTag.findall('framework');
+ frameworks.forEach(function (f) {
+ var custom = f.attrib['custom'];
+ if (!custom) {
+ var file = f.attrib['src'];
+ var weak = ('true' == f.attrib['weak']).toString();
+
+ deep_add(munge, 'framework', file, { xml: weak, count: 1 });
+ }
+ });
+ }
}
changes.forEach(function(change) {