You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2013/07/30 04:11:04 UTC
git commit: [CB-4373] First pass at ios frameworks being handled in
prepare stage.
Updated Branches:
refs/heads/frameworks [created] 00ece4c51
[CB-4373] First pass at ios frameworks being handled in prepare stage.
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugman/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugman/commit/00ece4c5
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugman/tree/00ece4c5
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugman/diff/00ece4c5
Branch: refs/heads/frameworks
Commit: 00ece4c51d436e03bc250c123f1d3c511ebcdb77
Parents: 266c74f
Author: Fil Maj <ma...@gmail.com>
Authored: Mon Jul 29 19:11:00 2013 -0700
Committer: Fil Maj <ma...@gmail.com>
Committed: Mon Jul 29 19:11:00 2013 -0700
----------------------------------------------------------------------
spec/integration.spec.js | 85 ----------------
spec/platforms/ios.spec.js | 31 ------
src/install.js | 7 +-
src/platforms/ios.js | 14 +--
src/util/config-changes.js | 209 +++++++++++++++++++++++++++-------------
src/util/fs.js | 34 -------
6 files changed, 144 insertions(+), 236 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/00ece4c5/spec/integration.spec.js
----------------------------------------------------------------------
diff --git a/spec/integration.spec.js b/spec/integration.spec.js
deleted file mode 100644
index 54b578e..0000000
--- a/spec/integration.spec.js
+++ /dev/null
@@ -1,85 +0,0 @@
-var plugman = require('../plugman'),
- path = require('path'),
- fs = require('fs'),
- shell = require('shelljs'),
- temp = path.join(__dirname, "..", ".tmp"),
- plugins_dir = path.join(temp, 'plugins');
-
-describe("integration", function () {
- beforeEach(function () {
- if ( !fs.existsSync(temp)) {
- shell.mkdir("-p", temp);
- }
- });
- describe("local non-root depdencies", function () {
- var project_src = path.join(__dirname, "projects", "android_one", "*"),
- plugin_src = path.join(__dirname, "plugins", "dependencies", "B"),
- project_dir = path.join(temp, "android");
-
- beforeEach(function () {
- shell.cp("-rf", project_src, project_dir);
- });
-
- it("should install dependencies from github", function () {
- var flag = false,
- installData;
-
- runs(function () {
- plugman.install('android', project_dir, plugin_src, plugins_dir, {}, function (error) {
- expect(error).not.toBeDefined();
- flag = true;
- });
- });
- waitsFor(function () { return flag; }, "plugman install to finish", 10000);
- runs(function () {
- installData = require(path.join(plugins_dir, "android.json"));
- expect(installData.installed_plugins).toEqual({ 'B': { PACKAGE_NAME: 'com.alunny.childapp'}});
- expect(installData.dependent_plugins).toEqual({
- 'D' : { PACKAGE_NAME: 'com.alunny.childapp'},
- 'E': { PACKAGE_NAME: 'com.alunny.childapp'}
- });
- });
- //Cleanup
- this.after(function () {
- shell.rm("-rf", project_dir);
- });
- });
- });
-
- describe("blackberry10", function () {
- var project_src = path.join(__dirname, "projects", "blackberry10", "*"),
- plugin_src = path.join(__dirname, "plugins", "Contacts"),
- project_dir = path.join(temp, "blackberry10");
-
- beforeEach(function () {
- shell.cp("-rf", project_src, project_dir);
- });
-
- it("should install dependencies from github", function () {
- var flag = false,
- installData;
-
- runs(function () {
- plugman.install('blackberry10', project_dir, plugin_src, plugins_dir, {}, function (error) {
- expect(error).not.toBeDefined();
- flag = true;
- });
- });
- waitsFor(function () { return flag; }, "plugman install to finish", 10000);
- runs(function () {
- installData = require(path.join(plugins_dir, "blackberry10.json"));
- expect(installData.installed_plugins).toEqual({ 'org.apache.cordova.core.contacts': { PACKAGE_NAME: 'cordovaExample'}});
- expect(installData.dependent_plugins).toEqual({
- 'com.blackberry.utils' : { PACKAGE_NAME: 'cordovaExample'},
- 'org.apache.cordova.blackberry10.pimlib': { PACKAGE_NAME: 'cordovaExample'}
- });
- });
- //Cleanup
- this.after(function () {
- shell.rm("-rf", project_dir);
- shell.rm("-rf", temp);
- });
- });
- });
-
-});
http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/00ece4c5/spec/platforms/ios.spec.js
----------------------------------------------------------------------
diff --git a/spec/platforms/ios.spec.js b/spec/platforms/ios.spec.js
index 3c34b8f..a19af13 100644
--- a/spec/platforms/ios.spec.js
+++ b/spec/platforms/ios.spec.js
@@ -240,24 +240,6 @@ describe('ios project handler', function() {
expect(spy).toHaveBeenCalledWith('-R', path.join(dummyplugin, 'src', 'ios', 'DummyPlugin.bundle'), path.join(temp, 'SampleApp', 'Resources'));
});
});
-
- describe('of <framework> elements', function() {
- beforeEach(function() {
- shell.cp('-rf', ios_config_xml_project, temp);
- });
- it('should call into xcodeproj\'s addFramework with weak false by default' ,function() {
- var frameworks = copyArray(valid_frameworks).filter(function(f) { return f.attrib.weak == undefined; });
- var spy = spyOn(proj_files.xcode, 'addFramework');
- ios.framework.install(frameworks[0], dummyplugin, temp, proj_files);
- expect(spy).toHaveBeenCalledWith(path.join('src', 'ios', 'libsqlite3.dylib').replace(/\\/g, '/'), {weak:false});
- });
- it('should pass in whether the framework is weak or not to xcodeproj.addFramework', function() {
- var frameworks = copyArray(valid_frameworks).filter(function(f) { return f.attrib.weak != undefined; });;
- var spy = spyOn(proj_files.xcode, 'addFramework');
- ios.framework.install(frameworks[0], dummyplugin, temp, proj_files);
- expect(spy).toHaveBeenCalledWith(path.join('src', 'ios', 'libsqlite3.dylib').replace(/\\/g, '/'), {weak:true});
- });
- });
});
describe('uninstallation', function() {
@@ -349,18 +331,5 @@ describe('ios project handler', function() {
expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Resources', 'DummyPlugin.bundle'));
});
});
-
- describe('of <framework> elements', function() {
- beforeEach(function() {
- shell.cp('-rf', ios_config_xml_project, temp);
- });
- it('should call into xcodeproj\'s removeFramework' ,function() {
- var frameworks = copyArray(valid_frameworks).filter(function(f) { return f.attrib.weak == undefined; });
- var spy = spyOn(proj_files.xcode, 'removeFramework');
-
- ios.framework.uninstall(frameworks[0], temp, proj_files);
- expect(spy).toHaveBeenCalledWith(path.join('src', 'ios', 'libsqlite3.dylib').replace(/\\/g, '/'));
- });
- });
});
});
http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/00ece4c5/src/install.js
----------------------------------------------------------------------
diff --git a/src/install.js b/src/install.js
index c3e125f..556ac7e 100644
--- a/src/install.js
+++ b/src/install.js
@@ -254,8 +254,7 @@ function handleInstall(actions, plugin_id, plugin_et, platform, project_dir, plu
var sourceFiles = platformTag.findall('./source-file'),
headerFiles = platformTag.findall('./header-file'),
resourceFiles = platformTag.findall('./resource-file'),
- libFiles = platformTag.findall('./lib-file'),
- frameworks = platformTag.findall('./framework');
+ libFiles = platformTag.findall('./lib-file');
assets = assets.concat(platformTag.findall('./asset'));
// queue up native stuff
@@ -271,10 +270,6 @@ function handleInstall(actions, plugin_id, plugin_et, platform, project_dir, plu
actions.push(actions.createAction(handler["resource-file"].install, [resource, plugin_dir, project_dir], handler["resource-file"].uninstall, [resource, project_dir]));
});
- frameworks && frameworks.forEach(function(framework) {
- actions.push(actions.createAction(handler["framework"].install, [framework, plugin_dir, project_dir], handler["framework"].uninstall, [framework, project_dir]));
- });
-
libFiles && libFiles.forEach(function(lib) {
actions.push(actions.createAction(handler["lib-file"].install, [lib, plugin_dir, project_dir], handler["lib-file"].uninstall, [lib, project_dir]));
});
http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/00ece4c5/src/platforms/ios.js
----------------------------------------------------------------------
diff --git a/src/platforms/ios.js b/src/platforms/ios.js
index eea59b3..278746f 100644
--- a/src/platforms/ios.js
+++ b/src/platforms/ios.js
@@ -18,7 +18,7 @@
*/
var path = require('path')
- , fs = require('../util/fs') // use existsSync in 0.6.x
+ , fs = require('fs')
, glob = require('glob')
, xcode = require('xcode')
, plist = require('plist')
@@ -115,18 +115,6 @@ module.exports = {
shell.rm('-rf', destFile);
}
},
- "framework":{
- install:function(framework_el, plugin_dir, project_dir, project) {
- var src = framework_el.attrib['src'],
- weak = framework_el.attrib['weak'];
- var opt = { weak: (weak == undefined || weak == null || weak != 'true' ? false : true ) };
- project.xcode.addFramework(src, opt);
- },
- uninstall:function(framework_el, project_dir, project) {
- var src = framework_el.attrib['src'];
- project.xcode.removeFramework(src);
- }
- },
parseIOSProjectFiles:function(project_dir) {
// grab and parse pbxproj
// we don't want CordovaLib's xcode project
http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/00ece4c5/src/util/config-changes.js
----------------------------------------------------------------------
diff --git a/src/util/config-changes.js b/src/util/config-changes.js
index 4a4d7ac..36dfe4b 100644
--- a/src/util/config-changes.js
+++ b/src/util/config-changes.js
@@ -17,6 +17,19 @@
*
*/
+/*
+ * This module deals with shared configuration / dependency "stuff". That is:
+ * - XML configuration files such as config.xml or AndroidManifest.xml.
+ * - plist files in iOS
+ * - pbxproj files in iOS
+ * Essentially, any type of shared resources that we need to handle with awareness
+ * of how potentially multiple plugins depend on a single shared resource, should be
+ * handled in this module.
+ *
+ * The implementation uses an object as a hash table, with "leaves" of the table tracking
+ * reference counts.
+ */
+
var fs = require('fs'),
path = require('path'),
glob = require('glob'),
@@ -24,6 +37,7 @@ var fs = require('fs'),
bplist = require('bplist-parser'),
et = require('elementtree'),
xml_helpers = require('./../util/xml-helpers'),
+ ios_parser = require('./../platforms/ios'),
plist_helpers = require('./../util/plist-helpers');
function checkPlatform(platform) {
@@ -102,6 +116,23 @@ module.exports = {
munge['plugins-plist'][key] = value;
}
});
+ // note down pbxproj framework munges in special section of munge obj
+ var frameworks = platformTag.findall('framework');
+ frameworks.forEach(function(f) {
+ if (!munge['framework']) {
+ munge['framework'] = {};
+ }
+ var file = f.attrib['src'];
+ var weak = f.attrib['weak'];
+ weak = (weak == undefined || weak == null || weak != 'true' ? 'false' : 'true');
+ if (!munge['framework'][file]) {
+ munge['framework'][file] = {};
+ }
+ if (!munge['framework'][file][weak]) {
+ munge['framework'][file][weak] = 0;
+ }
+ munge['framework'][file][weak] += 1;
+ });
}
changes.forEach(function(change) {
@@ -142,28 +173,40 @@ module.exports = {
// global munge looks at all plugins' changes to config files
var global_munge = platform_config.config_munge;
+ var plistObj, pbxproj;
+ if (platform == 'ios') {
+ if (global_munge['plugins-plist'] && config_munge['plugins-plist']) {
+ var plistfile = glob.sync(path.join(project_dir, '**', '{PhoneGap,Cordova}.plist'));
+ if (plistfile.length > 0) {
+ plistfile = plistfile[0];
+ // determine if this is a binary or ascii plist and choose the parser
+ // this is temporary until binary support is added to node-plist
+ var pl = (isBinaryPlist(plistfile) ? bplist : plist);
+ plistObj = pl.parseFileSync(plistfile);
+ }
+ }
+ if (global_munge['framework'] && config_munge['framework']) {
+ pbxproj = ios_parser.parseIOSProjectFiles(project_dir);
+ }
+ }
+
// Traverse config munge and decrement global munge
Object.keys(config_munge).forEach(function(file) {
if (file == 'plugins-plist' && platform == 'ios') {
+ // Handle plist files in ios
if (global_munge[file]) {
Object.keys(config_munge[file]).forEach(function(key) {
- if (global_munge[file][key]) {
- // prune from old plist if exists
- var plistfile = glob.sync(path.join(project_dir, '**', '{PhoneGap,Cordova}.plist'));
- if (plistfile.length > 0) {
- plistfile = plistfile[0];
- // determine if this is a binary or ascii plist and choose the parser
- // this is temporary until binary support is added to node-plist
- var pl = (isBinaryPlist(plistfile) ? bplist : plist);
- var plistObj = pl.parseFileSync(plistfile);
- delete plistObj.Plugins[key];
- fs.writeFileSync(plistfile, plist.build(plistObj));
- }
+ if (global_munge[file][key] && plistObj) {
+ delete plistObj.Plugins[key];
+ // TODO: don't write out on every change, do it once.
+ fs.writeFileSync(plistfile, plist.build(plistObj));
delete global_munge[file][key];
}
});
}
} else if (global_munge[file]) {
+ // Handle arbitrary XML/pbxproj changes
+ var is_framework = (platform == 'ios' && file == 'framework');
Object.keys(config_munge[file]).forEach(function(selector) {
if (global_munge[file][selector]) {
Object.keys(config_munge[file][selector]).forEach(function(xml_child) {
@@ -172,28 +215,36 @@ module.exports = {
global_munge[file][selector][xml_child] -= 1;
}
if (global_munge[file][selector][xml_child] === 0) {
- // this xml child is no longer necessary, prune it
- // config.xml referenced in ios config changes refer to the project's config.xml, which we need to glob for.
- var filepath = resolveConfigFilePath(project_dir, platform, file);
- if (fs.existsSync(filepath)) {
- if (path.extname(filepath) == '.xml') {
- var xml_to_prune = [et.XML(xml_child)];
- var doc = xml_helpers.parseElementtreeSync(filepath);
- if (xml_helpers.pruneXML(doc, xml_to_prune, selector)) {
- // were good, write out the file!
- fs.writeFileSync(filepath, doc.write({indent: 4}), 'utf-8');
- } else {
- // uh oh
- throw new Error('pruning xml at selector "' + selector + '" from "' + filepath + '" during config uninstall went bad :(');
- }
- } else {
- // plist file
- var pl = (isBinaryPlist(filepath) ? bplist : plist);
- var plistObj = pl.parseFileSync(filepath);
- if (plist_helpers.prunePLIST(plistObj, xml_child, selector)) {
- fs.writeFileSync(filepath, plist.build(plistObj));
+ if (is_framework) {
+ // this is a .framework reference in ios files
+ pbxproj.xcode.removeFramework(selector); // in this case the 2nd-level key is the src attrib of <framework> els
+ // TODO: dont write on every loop eh
+ fs.writeFileSync(pbxproj.pbx, pbxproj.xcode.writeSync());
+ } else {
+ // this xml child is no longer necessary, prune it
+ // config.xml referenced in ios config changes refer to the project's config.xml, which we need to glob for.
+ var filepath = resolveConfigFilePath(project_dir, platform, file);
+ if (fs.existsSync(filepath)) {
+ if (path.extname(filepath) == '.xml') {
+ var xml_to_prune = [et.XML(xml_child)];
+ var doc = xml_helpers.parseElementtreeSync(filepath);
+ if (xml_helpers.pruneXML(doc, xml_to_prune, selector)) {
+ // were good, write out the file!
+ // TODO: don't write out on every change, do it once.
+ fs.writeFileSync(filepath, doc.write({indent: 4}), 'utf-8');
+ } else {
+ // uh oh
+ throw new Error('pruning xml at selector "' + selector + '" from "' + filepath + '" during config uninstall went bad :(');
+ }
} else {
- throw new Error('grafting to plist "' + filepath + '" during config install went bad :(');
+ // plist file
+ var pl = (isBinaryPlist(filepath) ? bplist : plist);
+ var plistObj = pl.parseFileSync(filepath);
+ if (plist_helpers.prunePLIST(plistObj, xml_child, selector)) {
+ fs.writeFileSync(filepath, plist.build(plistObj));
+ } else {
+ throw new Error('grafting to plist "' + filepath + '" during config install went bad :(');
+ }
}
}
}
@@ -226,30 +277,43 @@ module.exports = {
var config_munge = module.exports.generate_plugin_config_munge(plugin_dir, platform, project_dir, plugin_vars);
// global munge looks at all plugins' changes to config files
var global_munge = platform_config.config_munge;
+
+ var pbxproj, plistObj;
+ if (platform == 'ios') {
+ if (config_munge['plugins-plist']) {
+ var plistfile = glob.sync(path.join(project_dir, '**', '{PhoneGap,Cordova}.plist'));
+ if (plistfile.length > 0) {
+ plistfile = plistfile[0];
+ // determine if this is a binary or ascii plist and choose the parser
+ // this is temporary until binary support is added to node-plist
+ var pl = (isBinaryPlist(plistfile) ? bplist : plist);
+ plistObj = pl.parseFileSync(plistfile);
+ }
+ }
+ if (config_munge['framework']) {
+ pbxproj = ios_parser.parseIOSProjectFiles(project_dir);
+ }
+ }
// Traverse config munge and decrement global munge
Object.keys(config_munge).forEach(function(file) {
if (!global_munge[file]) {
global_munge[file] = {};
}
+ var is_framework = (platform == 'ios' && file == 'framework');
Object.keys(config_munge[file]).forEach(function(selector) {
+ // Handle plist files on ios.
if (file == 'plugins-plist' && platform == 'ios') {
var key = selector;
- if (!global_munge[file][key]) {
+ if (!global_munge[file][key] && plistObj) {
// this key does not exist, so add it to plist
global_munge[file][key] = config_munge[file][key];
- var plistfile = glob.sync(path.join(project_dir, '**', '{PhoneGap,Cordova}.plist'));
- if (plistfile.length > 0) {
- plistfile = plistfile[0];
- // determine if this is a binary or ascii plist and choose the parser
- // this is temporary until binary support is added to node-plist
- var pl = (isBinaryPlist(plistfile) ? bplist : plist);
- var plistObj = pl.parseFileSync(plistfile);
- plistObj.Plugins[key] = config_munge[file][key];
- fs.writeFileSync(plistfile, plist.build(plistObj));
- }
+ plistObj.Plugins[key] = config_munge[file][key];
+ // TODO: dont write on every loop eh
+ fs.writeFileSync(plistfile, plist.build(plistObj));
}
} else {
+ // Handle arbitrary XML OR pbxproj framework stuff
if (!global_munge[file][selector]) {
global_munge[file][selector] = {};
}
@@ -261,33 +325,44 @@ module.exports = {
global_munge[file][selector][xml_child] += 1;
}
if (global_munge[file][selector][xml_child] == 1) {
- // this xml child is new, graft it (only if config file exists)
- // config file may be in a place not exactly specified in the target
- var filepath = resolveConfigFilePath(project_dir, platform, file);
- if (fs.existsSync(filepath)) {
- // look at ext and do proper config change based on file type
- if (path.extname(filepath) == '.xml') {
- var xml_to_graft = [et.XML(xml_child)];
- var doc = xml_helpers.parseElementtreeSync(filepath);
- if (xml_helpers.graftXML(doc, xml_to_graft, selector)) {
- // were good, write out the file!
- fs.writeFileSync(filepath, doc.write({indent: 4}), 'utf-8');
+ if (is_framework) {
+ var src = selector; // 2nd-level leaves are src path
+ // xml_child in this case is whether the framework should use weak or not
+ var opt = {weak: (xml_child != 'true' ? false : true)};
+ pbxproj.xcode.addFramework(src, opt);
+ // TODO: dont write on every loop eh
+ fs.writeFileSync(pbxproj.pbx, pbxproj.xcode.writeSync());
+ } else {
+ // this xml child is new, graft it (only if config file exists)
+ // config file may be in a place not exactly specified in the target
+ var filepath = resolveConfigFilePath(project_dir, platform, file);
+ if (fs.existsSync(filepath)) {
+ // look at ext and do proper config change based on file type
+ if (path.extname(filepath) == '.xml') {
+ var xml_to_graft = [et.XML(xml_child)];
+ // TODO: could parse the filepath once per unique target instead of on every change
+ var doc = xml_helpers.parseElementtreeSync(filepath);
+ if (xml_helpers.graftXML(doc, xml_to_graft, selector)) {
+ // were good, write out the file!
+ fs.writeFileSync(filepath, doc.write({indent: 4}), 'utf-8');
+ } else {
+ // uh oh
+ throw new Error('grafting xml at selector "' + selector + '" from "' + filepath + '" during config install went bad :(');
+ }
} else {
- // uh oh
- throw new Error('grafting xml at selector "' + selector + '" from "' + filepath + '" during config install went bad :(');
+ // plist file
+ var pl = (isBinaryPlist(filepath) ? bplist : plist);
+ // TODO: could parse the filepath once per unique target instead of on every change
+ var plistObj = pl.parseFileSync(filepath);
+ if (plist_helpers.graftPLIST(plistObj, xml_child, selector)) {
+ fs.writeFileSync(filepath, plist.build(plistObj));
+ } else {
+ throw new Error('grafting to plist "' + filepath + '" during config install went bad :(');
+ }
}
} else {
- // plist file
- var pl = (isBinaryPlist(filepath) ? bplist : plist);
- var plistObj = pl.parseFileSync(filepath);
- if (plist_helpers.graftPLIST(plistObj, xml_child, selector)) {
- fs.writeFileSync(filepath, plist.build(plistObj));
- } else {
- throw new Error('grafting to plist "' + filepath + '" during config install went bad :(');
- }
+ // TODO: ignore if file doesnt exist?
}
- } else {
- // ignore if file doesnt exist
}
}
});
http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/00ece4c5/src/util/fs.js
----------------------------------------------------------------------
diff --git a/src/util/fs.js b/src/util/fs.js
deleted file mode 100644
index 3d9f374..0000000
--- a/src/util/fs.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *
- * Copyright 2013 Anis Kadri
- *
- * Licensed 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 fs = require('fs');
-
-// polyfill for Node 0.6.x
-if (!fs.existsSync) {
- fs.existsSync = function (path) {
- try {
- fs.statSync(path);
- return true;
- } catch (e) {
- return false;
- }
- }
-}
-
-module.exports = fs;