cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From <shaz...@apache.org>
Subject ios commit: CB-11790 - Check that Cocoapods is installed by checking `pod install` return code, show help text
Date Mon, 05 Sep 2016 06:31:43 GMT
Repository: cordova-ios
Updated Branches:
  refs/heads/master aa28508d1 -> ad0968667


CB-11790 - Check that Cocoapods is installed by checking `pod install` return code, show help text

Re-factored code to be modular - Podfile and PodsJson are abstractions for the files themselves, and include unit-tests.
The addPlugin/removePlugin code in Api.js uses the two files above now, resulting in cleaner and more maintainable code.

 This closes #253


Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/ad096866
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/ad096866
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/ad096866

Branch: refs/heads/master
Commit: ad0968667e6c75e63b2d86485a949dd6fd095126
Parents: aa28508
Author: Shazron Abdullah <shazron@apache.org>
Authored: Thu Sep 1 18:08:18 2016 -0700
Committer: Shazron Abdullah <shazron@apache.org>
Committed: Sun Sep 4 23:31:23 2016 -0700

----------------------------------------------------------------------
 bin/lib/check_reqs.js                         |  79 ++++++-
 bin/lib/versions.js                           |  20 +-
 bin/templates/scripts/cordova/Api.js          | 234 ++++++++++-----------
 bin/templates/scripts/cordova/lib/Podfile.js  | 178 ++++++++++++++++
 bin/templates/scripts/cordova/lib/PodsJson.js |  96 +++++++++
 bin/templates/scripts/cordova/lib/podMod.js   | 170 ---------------
 tests/spec/unit/Podfile.spec.js               | 101 +++++++++
 tests/spec/unit/PodsJson.spec.js              | 168 +++++++++++++++
 tests/spec/unit/podMod.spec.js                |  87 --------
 9 files changed, 753 insertions(+), 380 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ad096866/bin/lib/check_reqs.js
----------------------------------------------------------------------
diff --git a/bin/lib/check_reqs.js b/bin/lib/check_reqs.js
index 31b1fab..2b578b6 100644
--- a/bin/lib/check_reqs.js
+++ b/bin/lib/check_reqs.js
@@ -19,6 +19,7 @@
 
 var Q     = require('q'),
     shell = require('shelljs'),
+    util = require('util'),
     versions = require('./versions');
 
 var XCODEBUILD_MIN_VERSION = '6.0.0';
@@ -30,6 +31,16 @@ var IOS_DEPLOY_NOT_FOUND_MESSAGE =
     'Please download, build and install version ' + IOS_DEPLOY_MIN_VERSION + ' or greater' +
     ' from https://github.com/phonegap/ios-deploy into your path, or do \'npm install -g ios-deploy\'';
 
+var COCOAPODS_MIN_VERSION = '1.0.1';
+var COCOAPODS_NOT_FOUND_MESSAGE =
+    'Please install version ' + COCOAPODS_MIN_VERSION + ' or greater from https://cocoapods.org/';
+var COCOAPODS_NOT_SYNCED_MESSAGE =
+    'The CocoaPods repo has not been synced yet, this will take a long time (approximately 500MB as of Sept 2016). Please run `pod setup` first to sync the repo.';
+var COCOAPODS_SYNCED_MIN_SIZE = 475; // in megabytes
+var COCOAPODS_SYNC_ERROR_MESSAGE =
+    'The CocoaPods repo has been created, but there appears to be a sync error. The repo size should be at least ' + COCOAPODS_SYNCED_MIN_SIZE + '. Please run `pod setup --verbose` to sync the repo.';
+var COCOAPODS_REPO_NOT_FOUND_MESSAGE = 'The CocoaPods repo at ~/.cocoapods was not found.';
+
 /**
  * Checks if xcode util is available
  * @return {Promise} Returns a promise either resolved with xcode version or rejected
@@ -53,25 +64,81 @@ module.exports.check_os = function () {
         Q.reject('Cordova tooling for iOS requires Apple OS X');
 };
 
+function check_cocoapod_tool() {
+    return checkTool('pod', COCOAPODS_MIN_VERSION, COCOAPODS_NOT_FOUND_MESSAGE, 'CocoaPods');
+}
+
+/**
+ * Checks if cocoapods repo size is what is expected
+ * @return {Promise} Returns a promise either resolved or rejected
+ */
+module.exports.check_cocoapods_repo_size = function () {
+    return check_cocoapod_tool()
+    .then(function() {
+        // check size of ~/.cocoapods repo
+        var commandString = util.format('du -sh %s/.cocoapods', process.env.HOME);
+        var command = shell.exec(commandString,  { silent:true });
+        if (command.code !== 0) { // error, perhaps not found 
+            return Q.reject(util.format('%s (%s)', COCOAPODS_REPO_NOT_FOUND_MESSAGE, command.output));
+        } else { // success, parse output
+            // command.output is e.g "750M   path/to/.cocoapods", we just scan the number
+            return Q.resolve(parseFloat(command.output));
+        }
+    })
+    .then(function(repoSize) {
+        if (COCOAPODS_SYNCED_MIN_SIZE > repoSize) {
+            return Q.reject(COCOAPODS_SYNC_ERROR_MESSAGE);
+        } else {
+            return Q.resolve();
+        }
+    });
+};
+
+/**
+ * Checks if cocoapods is available, and whether the repo is synced (because it takes a long time to download)
+ * @return {Promise} Returns a promise either resolved or rejected
+ */
+module.exports.check_cocoapods = function () {
+    return check_cocoapod_tool()
+    // check whether the cocoapods repo has been synced through `pod repo` command
+    // a value of '0 repos' means it hasn't been synced
+    .then(function() {
+        var code = shell.exec('pod repo | grep -e "^0 repos"',  { silent:true }).code;
+        return Q.resolve(code !== 0); // non-zero means it is synced (has 1 repo at least)
+    })
+    .then(function(repoIsSynced) {
+        if (repoIsSynced) {
+            // return check_cocoapods_repo_size();
+            // we could check the repo size above, but it takes too long.
+            return Q.resolve();
+        } else {
+            return Q.reject(COCOAPODS_NOT_SYNCED_MESSAGE);
+        }
+    });
+};
+
 /**
  * Checks if specific tool is available.
  * @param  {String} tool       Tool name to check. Known tools are 'xcodebuild' and 'ios-deploy'
  * @param  {Number} minVersion Min allowed tool version.
  * @param  {String} message    Message that will be used to reject promise.
+ * @param  {String} toolFriendlyName  Friendly name of the tool, to report to the user. Optional.
  * @return {Promise}           Returns a promise either resolved with tool version or rejected
  */
-function checkTool (tool, minVersion, message) {
+function checkTool (tool, minVersion, message, toolFriendlyName) {
+    toolFriendlyName = toolFriendlyName || tool;
+
     // Check whether tool command is available at all
     var tool_command = shell.which(tool);
     if (!tool_command) {
-        return Q.reject(tool + ' was not found. ' + (message || ''));
+        return Q.reject(toolFriendlyName + ' was not found. ' + (message || ''));
     }
     // check if tool version is greater than specified one
     return versions.get_tool_version(tool).then(function (version) {
         version = version.trim();
         return versions.compareVersions(version, minVersion) >= 0 ?
             Q.resolve(version) :
-            Q.reject('Cordova needs ' + tool + ' version ' + minVersion +
+            Q.reject('Cordova needs ' + toolFriendlyName + ' version ' + minVersion +
               ' or greater, you have version ' + version + '. ' + (message || ''));
     });
 }
@@ -102,7 +169,8 @@ module.exports.check_all = function() {
     var requirements = [
         new Requirement('os', 'Apple OS X', true),
         new Requirement('xcode', 'Xcode'),
-        new Requirement('ios-deploy', 'ios-deploy')
+        new Requirement('ios-deploy', 'ios-deploy'),
+        new Requirement('CocoaPods', 'CocoaPods')
     ];
 
     var result = [];
@@ -111,7 +179,8 @@ module.exports.check_all = function() {
     var checkFns = [
         module.exports.check_os,
         module.exports.check_xcodebuild,
-        module.exports.check_ios_deploy
+        module.exports.check_ios_deploy,
+        module.exports.check_cocoapods
     ];
 
     // Then execute requirement checks one-by-one

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ad096866/bin/lib/versions.js
----------------------------------------------------------------------
diff --git a/bin/lib/versions.js b/bin/lib/versions.js
index e22e499..da31d4f 100755
--- a/bin/lib/versions.js
+++ b/bin/lib/versions.js
@@ -111,6 +111,23 @@ exports.get_ios_deploy_version = function() {
 };
 
 /**
+ * Gets pod (CocoaPods) util version
+ * @return {Promise} Promise that either resolved with pod version
+ *                           or rejected in case of error
+ */
+exports.get_cocoapods_version = function() {
+    var d = Q.defer();
+    child_process.exec('pod --version', function(error, stdout, stderr) {
+        if (error) {
+            d.reject(stderr);
+        } else {
+            d.resolve(stdout);
+        }
+    });
+    return d.promise;
+};
+
+/**
  * Gets ios-sim util version
  * @return {Promise} Promise that either resolved with ios-sim version
  *                           or rejected in case of error
@@ -138,7 +155,8 @@ exports.get_tool_version = function (toolName) {
         case 'xcodebuild': return exports.get_apple_xcode_version();
         case 'ios-sim': return exports.get_ios_sim_version();
         case 'ios-deploy': return exports.get_ios_deploy_version();
-        default: return Q.reject(toolName + ' is not valid tool name. Valid names are: \'xcodebuild\', \'ios-sim\' and \'ios-deploy\'');
+        case 'pod': return exports.get_cocoapods_version();
+        default: return Q.reject(toolName + ' is not valid tool name. Valid names are: \'xcodebuild\', \'ios-sim\', \'ios-deploy\', and \'pod\'');
     }
 };
 

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ad096866/bin/templates/scripts/cordova/Api.js
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/Api.js b/bin/templates/scripts/cordova/Api.js
index fe9f440..dd2185e 100644
--- a/bin/templates/scripts/cordova/Api.js
+++ b/bin/templates/scripts/cordova/Api.js
@@ -27,6 +27,8 @@ var CordovaError = require('cordova-common').CordovaError;
 var CordovaLogger = require('cordova-common').CordovaLogger;
 var events = require('cordova-common').events;
 var PluginManager = require('cordova-common').PluginManager;
+var Q = require('q');
+var util = require('util');
 
 function setupEvents(externalEventEmitter) {
     if (externalEventEmitter) {
@@ -65,6 +67,7 @@ function Api(platform, platformRootDir, events) {
         if (!xcodeProjDir) {
             throw new CordovaError('The provided path "' + this.root + '" is not a Cordova iOS project.');
         }
+
         var cordovaProjName = xcodeProjDir.substring(xcodeProjDir.lastIndexOf(path.sep)+1, xcodeProjDir.indexOf('.xcodeproj'));
         xcodeCordovaProj = path.join(this.root, cordovaProjName);
     } catch(e) {
@@ -204,6 +207,7 @@ Api.prototype.prepare = function (cordovaProject) {
  */
 Api.prototype.addPlugin = function (plugin, installOptions) {
     var xcodeproj = projectFile.parse(this.locations);
+    var self = this;
 
     installOptions = installOptions || {};
     installOptions.variables = installOptions.variables || {};
@@ -212,93 +216,69 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
         installOptions.variables.PACKAGE_NAME = xcodeproj.getPackageName();
     }
 
-    return PluginManager.get(this.platform, this.locations, xcodeproj)
+    return PluginManager.get(self.platform, self.locations, xcodeproj)
         .addPlugin(plugin, installOptions)
-        .then(function() {
-            var project_dir = this.locations.root;
-            var project_path = this.locations.xcodeProjDir;
-            var project_name = this.locations.xcodeCordovaProj.split('/').pop();
-            
-            if (plugin.getFrameworks(this.platform).length === 0) return;
-            events.emit('verbose', 'Adding pods since the plugin contained <framework>');
-                    
-            var pods_file = path.join(project_dir, 'pods.json');
-            var pods = {};
-            
-            try {
-                delete require.cache[require.resolve(pods_file)];
-                pods = require(pods_file);
-            } catch (e) { 
-                /* no pods.json exists */ 
-                // create an empty pods.json file 
-                fs.writeFileSync(pods_file, JSON.stringify({}));
-                delete require.cache[require.resolve(pods_file)];
-                pods = require(pods_file);
-            }  
-
-            var podMod = require('./lib/podMod');
-            var frameworkTags = plugin.getFrameworks(this.platform);
-
-            // filter framework tags for type "podspec" 
-            var array_of_pod_objects = frameworkTags.filter(function(obj){
+        .then(function(){
+            var frameworkTags = plugin.getFrameworks(self.platform);
+            var frameworkPods = frameworkTags.filter(function(obj){
                 return (obj.type == 'podspec'); 
             });
 
-            var podIsAlreadyInPodfile;
-            var specForPodInSecondPluginIsDifferentFromSpecAlreadyInPodfile;
-            
-            array_of_pod_objects.forEach(function (obj) {
-                //check if pod already exists, if so if spec has changed 
-                //if pods.json does not exist yet, create it
-                // if it does not exist, only overwrite the type and spec, NOT the count
-                var nameOfPod = obj.src;
-
-                if(!pods[nameOfPod]) {
-                    pods[nameOfPod] = {'type': obj.type, 'spec': obj.spec};
-                    podIsAlreadyInPodfile = false;
-                } else {
-                    podIsAlreadyInPodfile = true;
-                    if (pods[nameOfPod].spec == obj.spec) {
-                        //same version
-                        pods[nameOfPod].spec = obj.spec;
-                        specForPodInSecondPluginIsDifferentFromSpecAlreadyInPodfile = false;
-                    } else {
-                        //different version
-                        //give warning, don't update anything
-                        specForPodInSecondPluginIsDifferentFromSpecAlreadyInPodfile = true;
-                        events.emit('warn', plugin.id + ' depends on ' + obj.src + '@' + obj.spec + ', which conflicts with another plugin. ' + obj.src + '@' + pods[nameOfPod].spec + ' is already installed and was not overwritten.');
+            return Q.resolve(frameworkPods);
+        })
+        .then(function(frameworkPods) {
+            if (!(frameworkPods.length)) {
+                return Q.resolve();
+            }
+
+            var project_dir = self.locations.root;
+            var project_name = self.locations.xcodeCordovaProj.split('/').pop();
+
+            var Podfile = require('./lib/Podfile').Podfile;
+            var PodsJson = require('./lib/PodsJson').PodsJson;
+
+            events.emit('verbose', 'Adding pods since the plugin contained <framework>(s) with type="podspec"');
+
+            var podsjsonFile = new PodsJson(path.join(project_dir, PodsJson.FILENAME));
+            var podfileFile = new Podfile(path.join(project_dir, Podfile.FILENAME), project_name); 
+
+            frameworkPods.forEach(function(obj) {
+                var podJson = {
+                    name: obj.src,
+                    type: obj.type,
+                    spec: obj.spec
+                };
+
+                var val = podsjsonFile.get(podJson.name);
+                if (val) { // found 
+                    if (podJson.spec !== val.spec) { // exists, different spec, print warning
+                        events.emit('warn', plugin.id + ' depends on ' + podJson.name + '@' + podJson.spec + ', which conflicts with another plugin. ' + podJson.name + '@' + val.spec + ' is already installed and was not overwritten.');          // no point in doing anything else with this plugin
+                        return;              
+                    } else { // exists, same spec, increment count
+                        podsjsonFile.increment(podJson.name);
                     }
+                } else { // not found, write new
+                    podJson.count = 1;
+                    podsjsonFile.setJson(podJson.name, podJson);
+                    // add to Podfile
+                    podfileFile.addSpec(podJson.name, podJson.spec);
                 }
+            });
 
-                // add a count incase multiple plugins depend on it.
-                if (pods[nameOfPod].count) {
-                    pods[nameOfPod].count = pods[nameOfPod].count + 1;
-                } else {
-                    pods[nameOfPod].count = 1;
-                }
+            // now that all the pods have been processed, write to pods.json
+            podsjsonFile.write();
 
-                if (podIsAlreadyInPodfile) {
-                    try { 
-                       fs.writeFileSync(pods_file, JSON.stringify(pods, null, 4));
-                    } catch (e) {
-                        throw new CordovaError('\nPod was not able to be added to pods.json in Api.js\n\n' + e);
-                    }
-                } else if (!podIsAlreadyInPodfile) {
-                    //add the pods to the Podfile, then add to pods.json
-                    podMod.addToPodfileSync(project_name, project_path, nameOfPod, obj.spec, pods_file); 
-                    events.emit('verbose', 'About to add ' + nameOfPod + ' to pods json');
-                    //write out updated pods.json, 
-                    // keep track of the order of the pods
-                    try { 
-                        fs.writeFileSync(pods_file, JSON.stringify(pods, null, 4));
-                    } catch (e) {
-                        throw new CordovaError('\nPod was not able to be added to pods.json in Api.js\n\n' + e);
-                    }
-                }
-            });
-            events.emit('verbose', 'Running pod install');
-            podMod.installAllPods(project_dir, false);
-        }.bind(this))
+            // only write and pod install if the Podfile changed
+            if (podfileFile.isDirty()) {
+                podfileFile.write();
+                events.emit('verbose', 'Running `pod install` (to install plugins)');
+
+                var check_reqs = require('./lib/check_reqs');
+                return podfileFile.install(check_reqs.check_cocoapods);
+            } else {
+                events.emit('verbose', 'Podfile unchanged, skipping `pod install`');
+            }
+        })
         // CB-11022 return non-falsy value to indicate
         // that there is no need to run prepare after
         .thenResolve(true);
@@ -319,46 +299,66 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
  */
 Api.prototype.removePlugin = function (plugin, uninstallOptions) {
     var xcodeproj = projectFile.parse(this.locations);
-    return PluginManager.get(this.platform, this.locations, xcodeproj)
+    var self = this;
+
+    return PluginManager.get(self.platform, self.locations, xcodeproj)
         .removePlugin(plugin, uninstallOptions)
-        .then(function() {
-            if (plugin.getFrameworks(this.platform).length === 0) return;
-                events.emit('verbose', 'Removing pods since the plugin contained <framework>');
-                //require script to run pod remove
-                //pods.json might not exist (if not pods were removed). 
-                //the pod will already be removed from pods.json at this stage
-                //need to check podfile and see if a pod exists in podfile that doesn't exist in pods.json. If so, remove it.
-
-                // which pods are in the plugin? 
-                var frameworkTags = plugin.getFrameworks(this.platform);
-                var project_dir = this.locations.root;
-                var pods_file = path.join(project_dir, 'pods.json');
-
-                delete require.cache[require.resolve(pods_file)];
-                var pods = require(pods_file);
-            
-                // filter framework tags for type "podspec" 
-                var array_of_pod_objects = frameworkTags.filter(function(obj){
-                    return (obj.type == 'podspec'); 
-                });
-
-                var podMod = require('./lib/podMod');
+        .then(function(){
+            var frameworkTags = plugin.getFrameworks(self.platform);
+            var frameworkPods = frameworkTags.filter(function(obj){
+                return (obj.type == 'podspec'); 
+            });
+
+            return Q.resolve(frameworkPods);
+        })
+        .then(function(frameworkPods) {
+            if (!(frameworkPods.length)) {
+                return Q.resolve();
+            }
+
+            var project_dir = self.locations.root;
+            var project_name = self.locations.xcodeCordovaProj.split('/').pop();
+
+            var Podfile = require('./lib/Podfile').Podfile;
+            var PodsJson = require('./lib/PodsJson').PodsJson;
+
+            events.emit('verbose', 'Adding pods since the plugin contained <framework>(s) with type=\"podspec\"');
+
+            var podsjsonFile = new PodsJson(path.join(project_dir, PodsJson.FILENAME));
+            var podfileFile = new Podfile(path.join(project_dir, Podfile.FILENAME), project_name); 
                 
-                array_of_pod_objects.forEach(function (obj) {
-                    // according to pods.json, does more than one plugin depend on the pod?
-                    if (pods[obj.src].count > 1) {
-                        // if so, only subtract one from the count in pods.json
-                        pods[obj.src].count = pods[obj.src].count - 1;
-                    } else {
-                        // if not, remove the pod from the Podfile 
-                        podMod.removeFromPodfileSync(project_dir, obj.src); 
-                        // update pods.json
-                        delete pods[obj.src];
-                    }
-                    fs.writeFileSync(pods_file, JSON.stringify(pods, null, 4));
-                });
-                podMod.installAllPods(project_dir, false);
-        }.bind(this))
+            frameworkPods.forEach(function(obj) {
+                var podJson = {
+                    name: obj.src,
+                    type: obj.type,
+                    spec: obj.spec
+                };
+
+                var val = podsjsonFile.get(podJson.name);
+                if (val) { // found, decrement count
+                    podsjsonFile.decrement(podJson.name);
+                } else { // not found (perhaps a sync error)
+                    var message = util.format('plugin \"%s\" podspec \"%s\" does not seem to be in pods.json, nothing to remove. Will attempt to remove from Podfile.', plugin.id, podJson.name);
+                    events.emit('verbose', message);
+                }
+
+                // always remove from the Podfile
+                podfileFile.removeSpec(podJson.name);
+            });
+
+            // now that all the pods have been processed, write to pods.json
+            podsjsonFile.write();
+
+            if (podfileFile.isDirty()) {
+                podfileFile.write();
+                events.emit('verbose', 'Running `pod install` (to uninstall pods)');
+
+                var check_reqs = require('./lib/check_reqs');
+                return podfileFile.install(check_reqs.check_cocoapods);
+            } else {
+                events.emit('verbose', 'Podfile unchanged, skipping `pod install`');
+            }
+        })
         // CB-11022 return non-falsy value to indicate
         // that there is no need to run prepare after
         .thenResolve(true);

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ad096866/bin/templates/scripts/cordova/lib/Podfile.js
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/lib/Podfile.js b/bin/templates/scripts/cordova/lib/Podfile.js
new file mode 100644
index 0000000..c0e12f9
--- /dev/null
+++ b/bin/templates/scripts/cordova/lib/Podfile.js
@@ -0,0 +1,178 @@
+var fs = require('fs'),
+    path = require('path'),
+    util = require('util'),
+    events = require('cordova-common').events,
+    Q = require('q'),
+    superspawn = require('cordova-common').superspawn,
+    CordovaError = require('cordova-common').CordovaError;
+
+Podfile.FILENAME = 'Podfile';
+
+function Podfile(podFilePath, projectName) {
+    this.podToken = '##INSERT_POD##';
+
+    this.path = podFilePath;
+    this.projectName = projectName;
+    this.contents = null;
+    this.pods = null;
+    this.__dirty = false;
+
+    // check whether it is named Podfile
+    var filename = this.path.split(path.sep).pop();
+    if (filename !== Podfile.FILENAME) {
+        throw new CordovaError(util.format('Podfile: The file at %s is not `%s`.', this.path, Podfile.FILENAME));
+    }
+
+    if (!projectName) {
+        throw new CordovaError('Podfile: The projectName was not specified in the constructor.');
+    }
+
+    if (!fs.existsSync(this.path)) {
+        events.emit('verbose', util.format('Podfile: The file at %s does not exist.', this.path));
+        events.emit('verbose', 'Creating new Podfile in platforms/ios');
+        this.clear();
+        this.write();
+    } else {
+        events.emit('verbose', 'Podfile found in platforms/ios');
+        // parse for pods 
+        this.pods = this.__parseForPods(fs.readFileSync(this.path, 'utf8'));
+    }
+}
+
+Podfile.prototype.__parseForPods = function(text) {
+    // split by \n
+    var arr = text.split('\n');
+
+    // aim is to match (space insignificant around the comma, comma optional):
+    //     'pod 'Foobar', '1.2'
+    //     'pod 'Foobar', 'abc 123 1.2'    
+    var podRE = new RegExp('pod \'(\\w+)\'\\s*,?(\\s*\'(\\w+|\\d+(\\.\\d)?)+\')?');
+
+    // only grab lines that don't have the pod spec'
+    return arr.filter(function(line) {
+        var m = podRE.exec(line);
+
+        return (m !== null);
+    })
+    .reduce(function(obj, line){
+        var m = podRE.exec(line);
+
+        if (m !== null) {
+            obj[m[1]] = m[3]; // i.e pod 'Foo', '1.2' ==> { 'Foo' : '1.2'}
+        }
+
+        return obj;
+    }, {});
+};
+
+Podfile.prototype.getTemplate = function() {
+    return util.format(
+            '# DO NOT MODIFY -- auto-generated by Apache Cordova\n' +
+            'platform :ios, \'8.0\'\n' +
+            'target \'%s\' do\n' +
+            '\tproject \'%s.xcodeproj\'\n' +
+            '%s\n' +
+            'end\n',
+             this.projectName, this.projectName, this.podToken);
+};
+
+Podfile.prototype.addSpec = function(name, spec) {
+    name = name || '';
+    spec = spec; // optional
+
+    if (!name.length) { // blank names are not allowed
+        throw new CordovaError('Podfile addSpec: name is not specified.');
+    }
+
+    this.pods[name] = spec;
+    this.__dirty = true;
+
+    events.emit('verbose', util.format('Added pod line for `%s`', name));
+};
+
+Podfile.prototype.removeSpec = function(name) {
+    if (this.existsSpec(name)) {
+        delete this.pods[name];
+        this.__dirty = true;
+    }
+    
+    events.emit('verbose', util.format('Removed pod line for `%s`', name));
+};
+
+Podfile.prototype.getSpec = function(name) {
+    return this.pods[name];
+};
+
+Podfile.prototype.existsSpec = function(name) {
+    return (name in this.pods);
+};
+
+Podfile.prototype.clear = function() {
+    this.pods = {};
+    this.__dirty = true;
+};
+
+Podfile.prototype.destroy = function() {
+    fs.unlinkSync(this.path);
+    events.emit('verbose', util.format('Deleted `%s`', this.path));
+};
+
+Podfile.prototype.write = function() {
+    var text = this.getTemplate();
+    var self = this;
+
+    var podsString =
+    Object.keys(this.pods).map(function(key) {
+        var name = key;
+        var spec = self.pods[key];
+
+        return spec.length?
+            util.format('\tpod \'%s\', \'%s\'', name, spec):
+            util.format('\tpod \'%s\'', name);
+    })
+    .join('\n');
+
+    text = text.replace(this.podToken, podsString);
+    fs.writeFileSync(this.path, text, 'utf8');
+    this.__dirty = false;
+
+    events.emit('verbose', 'Wrote to Podfile.');
+};
+
+Podfile.prototype.isDirty = function() {
+    return this.__dirty;
+};
+
+Podfile.prototype.install = function(requirementsCheckerFunction) {
+    var opts = {};
+    opts.cwd = path.join(this.path, '..'); // parent path of this Podfile
+    opts.stdio = 'pipe';
+    var first = true;
+
+    if (!requirementsCheckerFunction) {
+        requirementsCheckerFunction = Q();
+    }
+
+    return requirementsCheckerFunction()
+    .then(function() {
+        return superspawn.spawn('pod', ['install', '--verbose'], opts)
+        .progress(function (stdio){
+            if (stdio.stderr) { console.error(stdio.stderr); }
+            if (stdio.stdout) {
+                if (first) {
+                    events.emit('verbose', '==== pod install start ====\n');
+                    first = false;
+                }
+                events.emit('verbose', stdio.stdout); 
+            } 
+        });
+    })
+    .then(function() { // done
+        events.emit('verbose', '==== pod install end ====\n');
+    })
+    .fail(function(error){
+        throw error;
+    });
+};
+
+module.exports.Podfile = Podfile;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ad096866/bin/templates/scripts/cordova/lib/PodsJson.js
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/lib/PodsJson.js b/bin/templates/scripts/cordova/lib/PodsJson.js
new file mode 100644
index 0000000..55134a9
--- /dev/null
+++ b/bin/templates/scripts/cordova/lib/PodsJson.js
@@ -0,0 +1,96 @@
+var fs = require('fs'),
+    path = require('path'),
+    util = require('util'),
+    events = require('cordova-common').events,
+    CordovaError = require('cordova-common').CordovaError;
+
+PodsJson.FILENAME = 'pods.json';
+
+function PodsJson(podsJsonPath) {
+    this.path = podsJsonPath;
+    this.contents = null;
+    this.__dirty = false;
+
+    var filename = this.path.split(path.sep).pop();
+    if (filename !== PodsJson.FILENAME) {
+        throw new CordovaError(util.format('PodsJson: The file at %s is not `%s`.', this.path, PodsJson.FILENAME));
+    }
+
+    if (!fs.existsSync(this.path)) {
+        events.emit('verbose', util.format('pods.json: The file at %s does not exist.', this.path));
+        events.emit('verbose', 'Creating new pods.json in platforms/ios');
+        this.clear();
+        this.write();
+    } else {
+        events.emit('verbose', 'pods.json found in platforms/ios');  
+        // load contents
+        this.contents = fs.readFileSync(this.path, 'utf8');
+        this.contents = JSON.parse(this.contents);
+    }
+}
+
+PodsJson.prototype.get = function(name) {
+    return this.contents[name];
+};
+
+PodsJson.prototype.remove = function(name) {
+    if (this.contents[name]) {
+        delete this.contents[name];
+        this.__dirty = true;
+        events.emit('verbose', util.format('Remove from pods.json for `%s`', name));
+    }
+};
+
+PodsJson.prototype.clear = function() {
+    this.contents = {};
+    this.__dirty = true;
+};
+
+PodsJson.prototype.destroy = function() {
+    fs.unlinkSync(this.path);
+    events.emit('verbose', util.format('Deleted `%s`', this.path));
+};
+
+PodsJson.prototype.write = function() {
+    if (this.contents) {
+        fs.writeFileSync(this.path, JSON.stringify(this.contents, null, 4));
+        this.__dirty = false;
+        events.emit('verbose', 'Wrote to pods.json.');
+    }
+};
+
+PodsJson.prototype.set = function(name, type, spec, count) {
+    this.setJson(name, { name: name, type: type, spec: spec, count: count });
+};
+
+PodsJson.prototype.increment = function(name) {
+    var val = this.get(name);
+    if (val) {
+        val.count++;
+        this.setJson(val);
+    }
+};
+
+PodsJson.prototype.decrement = function(name) {
+    var val = this.get(name);
+    if (val) {
+        val.count--;
+        if (val.count <= 0) {
+            this.remove(name);
+        } else {
+            this.setJson(val);
+        }
+    }
+};
+
+PodsJson.prototype.setJson = function(name, json) {
+    this.contents[name] = json;
+    this.__dirty = true;
+    events.emit('verbose', util.format('Set pods.json for `%s`', name));
+};
+
+PodsJson.prototype.isDirty = function() {
+    return this.__dirty;
+};
+
+module.exports.PodsJson = PodsJson;

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ad096866/bin/templates/scripts/cordova/lib/podMod.js
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/lib/podMod.js b/bin/templates/scripts/cordova/lib/podMod.js
deleted file mode 100644
index f47a536..0000000
--- a/bin/templates/scripts/cordova/lib/podMod.js
+++ /dev/null
@@ -1,170 +0,0 @@
-var fs = require('fs'),
-    path = require('path'),
-    util = require('util'),
-    events = require('cordova-common').events,
-    superspawn = require('cordova-common').superspawn,
-    CordovaError = require('cordova-common').CordovaError;
-
-var opts = {};
-/*
--- After pods are installed in a .xcworkspace, all existing ios code needs to go into the WORKSPACE file -- will need to 
-    create a workspace file and then embed the Xcode project  
-
-        - Holly might have done some work on this, see the docs: 
-          https://github.com/phonegap/phonegap-webview-ios not sure how applicable it can be to our case
-*/
-function removeProjectFromPath (pathToProjectFile) {
-    var arrayOfDirectories = [];
-    //remove the project from the path
-    arrayOfDirectories = pathToProjectFile.split(path.sep);
-    arrayOfDirectories.pop();
-    var pathToProjectDirectory = arrayOfDirectories.join(path.sep);
-    return pathToProjectDirectory;
-}
-
-function createPodfile (projectName, pathToProjectFile) {
-    var pathToProjectDirectory = removeProjectFromPath(pathToProjectFile);
-    var projectFileName = pathToProjectFile.split(path.sep).pop();
-    var pathToPodfile = path.join(pathToProjectDirectory, 'Podfile');
-    var podfileText = util.format('platform :ios, \'8.0\'\n\ntarget \'%s\' do\n\n  project \'%s\'\n\n  \n\nend' , projectName, projectFileName);
-    fs.writeFileSync(pathToPodfile, podfileText);
-}
-
-function editPodfileSync (Podfile, pod, isRemoval) {
-    var podfileContents = fs.readFileSync(Podfile, 'utf8');
-    //split by \n, add in the pod after the project line, shift the rest down
-    var podfileContentsArray = podfileContents.split('\n');
-
-    if (isRemoval) {
-        var linesInPodfileToKeep = podfileContentsArray.filter(function(lineInPodfile) {
-            return (lineInPodfile.indexOf(pod) === -1);
-        });
-        
-        podfileContents = linesInPodfileToKeep.join('\n');
-    } else {
-        var lineNumberForInjectionWithinPodfile = 5;
-        podfileContentsArray.splice(lineNumberForInjectionWithinPodfile, 0, pod);
-        podfileContents = podfileContentsArray.join('\n');
-    }
-    return podfileContents;
-}
-
-function installAllPods (path, isPathToProjectFile) {
-    // change working directory for all calls of pod install to platforms/ios
-    if (isPathToProjectFile){
-        //if the path passed leads to the project, and not the dir that contains the proj
-         //remove the project from the path
-        path = removeProjectFromPath(path);
-    }
-    opts.cwd = path;
-    opts.stdio = 'pipe';
-    var first = true;
-
-    superspawn.spawn('pod', ['install', '--verbose'], opts)
-    .progress(function (stdio){
-        if (stdio.stderr) { console.error(stdio.stderr); }
-        if (stdio.stdout) {
-            if (first) {
-                events.emit('verbose', '==== pod install start ====\n');
-                first = false;
-            }
-            events.emit('verbose', stdio.stdout); 
-        } 
-    })
-    .then(function() { // done
-        events.emit('verbose', '==== pod install end ====\n');
-    })
-    .fail(function(error) {
-        console.error(error);
-        // TODO: report on what to do if cocoapods is not installed
-    })
-    .fin();
-}
-
-function addToPodfileSync (projectName, pathToProjectFile, nameOfPod, podSpec, podsJSON) {
-    //  nameOfPod           = obj.src                   //from framework tag
-    //  podSpec             = obj.spec                  //from framework tag   
-    //  podsJSON            = pods.json file in cordovaProjectDir/platforms/ios/
-
-    // readFileSync will currently truncate the Podfile if it exists
-    // if a Podfile doesn't exist, one will be created
-
-    // this code will be run during cordova plugin add x -- which has to be run in the cordova project dir
-    
-    //-----------
-    //ERROR
-    //
-    //if no podName is specified, console err 
-    if (nameOfPod === '' || nameOfPod === ' '){
-        throw new CordovaError('\nERROR: name of pod is not specified\n');
-    }
-    //-----------
-
-    podSpec = podSpec || ''; //spec is optional
-    
-    var stringToWrite; //overwrites Podfile
-    var lineToInjectInPodfile; //adds pod
-    var pathToProject = removeProjectFromPath(pathToProjectFile);
-    var podfile = path.join(pathToProject, 'Podfile');
-    var podfileExistsInCurrentDirectory = fs.existsSync(podfile);
-    var podExistsInPodsJSON = podsJSON[nameOfPod];
-    var podRequestedForSpecChange;
-   
-    if (podSpec === '') {
-        lineToInjectInPodfile = util.format('pod \'%s\'', nameOfPod);
-        podRequestedForSpecChange = false;
-    } else {
-        if (podExistsInPodsJSON){
-            if (podsJSON[nameOfPod].spec !== podSpec){
-                podRequestedForSpecChange = true; 
-            }
-        } else {
-            lineToInjectInPodfile = util.format('pod \'%s\', \'%s\'', nameOfPod, podSpec);
-            podRequestedForSpecChange = false; 
-        }
-    }
-
-    //does Podfile exist in the current directory?
-    if (podfileExistsInCurrentDirectory) {
-        events.emit('verbose', 'Podfile found in platforms/ios');
-        //is the pod already in the Podfile? 
-        if (podExistsInPodsJSON) {
-            events.emit('verbose', 'Selected pod already exists in Podfile according to pods.json');
-            //if pod is in Podfile, is there a change in spec? 
-            if (podRequestedForSpecChange) {
-                //if spec change requested, it won't make it to this point-- TODO: rm this line 
-                events.emit('verbose', 'Pod requested for spec change');
-            } // no change in spec handled above
-        } else if (!podExistsInPodsJSON) {
-            //if pod not already in Podfile, inject the line in the existing Podfile
-            events.emit('verbose', 'Pod not found in Podfile. Injecting now...');
-            stringToWrite = editPodfileSync(podfile, lineToInjectInPodfile);
-        }
-    } else if (!podfileExistsInCurrentDirectory) {
-        //create the Podfile and inject the line
-        events.emit('verbose', 'Creating new Podfile in platforms/ios');
-        createPodfile(projectName, pathToProjectFile);
-        events.emit('verbose', 'Adding pod to Podfile');
-        stringToWrite = editPodfileSync(podfile, lineToInjectInPodfile);
-    }
-    
-    if (stringToWrite) {
-        events.emit('verbose', 'Overwriting Podfile');
-        fs.writeFileSync(podfile, stringToWrite, 'utf8');
-    } else {
-        //the code should have returned early by now
-    }
-    events.emit('verbose', 'Pods installed in xcode workspace in platforms/ios');
-}
-
-function removeFromPodfileSync (projectDirectory, pod) {
-    var podfile = path.join(projectDirectory, 'Podfile');
-    var stringToWrite = editPodfileSync(podfile, pod, true);
-    fs.writeFileSync(podfile, stringToWrite);
-}
-
-module.exports = {
-    addToPodfileSync        : addToPodfileSync,
-    removeFromPodfileSync   : removeFromPodfileSync,
-    installAllPods          : installAllPods
-};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ad096866/tests/spec/unit/Podfile.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/Podfile.spec.js b/tests/spec/unit/Podfile.spec.js
new file mode 100644
index 0000000..b68d435
--- /dev/null
+++ b/tests/spec/unit/Podfile.spec.js
@@ -0,0 +1,101 @@
+var	path = require('path'),
+	util = require('util'),
+	CordovaError = require('cordova-common').CordovaError;
+
+var Podfile = require(path.resolve(path.join(__dirname, '..', '..', '..', 'bin', 'templates', 'scripts', 'cordova', 'lib', 'Podfile.js'))).Podfile;
+var fixturePodfile = path.resolve(__dirname, 'fixtures', 'testProj', 'platforms', 'ios', 'Podfile');
+
+// tests are nested in a describe to ensure clean up happens after all unit tests are run
+describe('unit tests for Podfile module', function () {
+	var podfile = new Podfile(fixturePodfile, 'testProj');
+
+	describe('tests', function () {
+
+		it ('throws CordovaError when the path filename is not named Podfile', function () {
+			var dummyPath = 'NotAPodfile';
+			expect( function () { 
+				new Podfile(dummyPath);	 
+			})
+			.toThrow(new CordovaError(util.format('Podfile: The file at %s is not `%s`.', dummyPath, Podfile.FILENAME)));
+		});
+
+		it ('throws CordovaError when no projectName provided when creating a Podfile', function () {
+			expect( function () { 
+				new Podfile(fixturePodfile);	 
+			})
+			.toThrow(new CordovaError('Podfile: The projectName was not specified in the constructor.'));
+		});
+
+		it ('throws CordovaError when no pod name provided when adding a spec', function () {
+			expect( function () { 
+				podfile.addSpec(null);	 
+			})
+			.toThrow(new CordovaError('Podfile addSpec: name is not specified.'));
+		});
+
+		it ('adds the spec', function () {
+			expect(podfile.existsSpec('Foo')).toBe(false);
+			podfile.addSpec('Foo', '1.0');
+			expect(podfile.existsSpec('Foo')).toBe(true);
+		});
+
+		it ('removes the spec', function () {
+			podfile.addSpec('Baz', '3.0');
+			expect(podfile.existsSpec('Baz')).toBe(true);
+			podfile.removeSpec('Baz');
+			expect(podfile.existsSpec('Baz')).toBe(false);
+		});
+
+		it ('clears all specs', function () {
+			podfile.addSpec('Bar', '2.0');
+			podfile.clear();
+
+			expect(podfile.existsSpec('Foo')).toBe(false);
+			expect(podfile.existsSpec('Bar')).toBe(false);
+		});
+
+		it ('isDirty tests', function () {
+			podfile.addSpec('Foo', '1.0');
+			expect(podfile.isDirty()).toBe(true);
+
+			podfile.write();
+			expect(podfile.isDirty()).toBe(false);
+
+			podfile.removeSpec('Foo');
+			expect(podfile.isDirty()).toBe(true);
+			
+			podfile.clear();
+			expect(podfile.isDirty()).toBe(true);
+
+			podfile.write();
+			expect(podfile.isDirty()).toBe(false);
+		});
+
+		it ('writes specs to the Podfile', function () {
+			podfile.clear();
+			
+			podfile.addSpec('Foo', '1.0');
+			podfile.addSpec('Bar', '2.0');
+			podfile.addSpec('Baz', '3.0');
+
+			podfile.write();
+
+			// verify by reading it back in a new Podfile 
+			var newPodfile = new Podfile(fixturePodfile, 'testProj2');
+			expect(newPodfile.existsSpec('Foo')).toBe(true);
+			expect(newPodfile.existsSpec('Bar')).toBe(true);
+			expect(newPodfile.existsSpec('Baz')).toBe(true);
+
+			expect(newPodfile.getSpec('Foo')).toBe(podfile.getSpec('Foo'));
+			expect(newPodfile.getSpec('Bar')).toBe(podfile.getSpec('Bar'));
+			expect(newPodfile.getSpec('Baz')).toBe(podfile.getSpec('Baz'));
+			
+		});
+
+	});
+
+	it('tear down', function () {
+		podfile.destroy();
+	});
+});
+

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ad096866/tests/spec/unit/PodsJson.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/PodsJson.spec.js b/tests/spec/unit/PodsJson.spec.js
new file mode 100644
index 0000000..5b3cff3
--- /dev/null
+++ b/tests/spec/unit/PodsJson.spec.js
@@ -0,0 +1,168 @@
+var path = require('path'),
+	util = require('util'),
+	CordovaError = require('cordova-common').CordovaError;
+
+var PodsJson = require(path.resolve(path.join(__dirname, '..', '..', '..', 'bin', 'templates', 'scripts', 'cordova', 'lib', 'PodsJson.js'))).PodsJson;
+var fixturePodsJson = path.resolve(__dirname, 'fixtures', 'testProj', 'platforms', 'ios', 'pods.json');
+
+// tests are nested in a describe to ensure clean up happens after all unit tests are run
+describe('unit tests for Podfile module', function () {
+	var podsjson = new PodsJson(fixturePodsJson);
+
+	describe('tests', function () {
+
+		it ('throws CordovaError when the path filename is not named pods.json', function () {
+			var dummyPath = 'NotPodsJson';
+			expect( function () { 
+				new PodsJson(dummyPath);	 
+			})
+			.toThrow(new CordovaError(util.format('PodsJson: The file at %s is not `%s`.', dummyPath, PodsJson.FILENAME)));
+		});
+
+		it ('sets and gets pod test', function () {
+			var val0 = {
+				name: 'Foo',
+				type: 'podspec',
+				spec: '1.0',
+				count: 1
+			};
+			podsjson.set(val0.name, val0.type, val0.spec, val0.count);
+			var val1 = podsjson.get(val0.name);
+
+			expect(val1).toBeTruthy();
+			expect(val1.name).toEqual(val0.name);
+			expect(val1.type).toEqual(val0.type);
+			expect(val1.spec).toEqual(val0.spec);
+			expect(val1.count).toEqual(val0.count);
+		});
+
+		it ('setsJson and remove pod test', function () {
+			var val0 = {
+				name: 'Bar',
+				type: 'podspec',
+				spec: '2.0',
+				count: 2
+			};
+			podsjson.setJson(val0.name, val0);
+			var val1 = podsjson.get(val0.name);
+
+			expect(val1).toBeTruthy();
+			expect(val1.name).toEqual(val0.name);
+			expect(val1.type).toEqual(val0.type);
+			expect(val1.spec).toEqual(val0.spec);
+			expect(val1.count).toEqual(val0.count);
+
+			podsjson.remove(val0.name);
+			val1 = podsjson.get(val0.name);
+			expect(val1).toBeFalsy();
+		});
+		
+		it ('clears all pods', function () {
+			var val0 = {
+				name: 'Baz',
+				type: 'podspec',
+				spec: '3.0',
+				count: 3
+			};
+			podsjson.setJson(val0.name, val0);
+			podsjson.clear();
+
+			expect(podsjson.get(val0.name)).toBeFalsy();
+			expect(podsjson.get('Foo')).toBeFalsy();
+			expect(podsjson.get('Bar')).toBeFalsy();
+		});
+
+		it ('isDirty tests', function () {
+			var val0 = {
+				name: 'Foo',
+				type: 'podspec',
+				spec: '1.0',
+				count: 1
+			};
+
+			podsjson.setJson(val0.name, val0);
+			expect(podsjson.isDirty()).toBe(true);
+
+			podsjson.write();
+			expect(podsjson.isDirty()).toBe(false);
+
+			podsjson.remove(val0.name);
+			expect(podsjson.isDirty()).toBe(true);
+			
+			podsjson.clear();
+			expect(podsjson.isDirty()).toBe(true);
+
+			podsjson.write();
+			expect(podsjson.isDirty()).toBe(false);
+		});
+
+		it ('increment and decrement count test', function () {
+			var val0 = {
+				name: 'Bla',
+				type: 'podspec',
+				spec: '4.0',
+				count: 4
+			};
+			
+			podsjson.setJson(val0.name, val0);
+			expect(podsjson.get(val0.name).count).toBe(4);
+
+			podsjson.increment(val0.name);
+			expect(podsjson.get(val0.name).count).toBe(5);
+
+			podsjson.decrement(val0.name);
+			expect(podsjson.get(val0.name).count).toBe(4);
+			podsjson.decrement(val0.name);
+			expect(podsjson.get(val0.name).count).toBe(3);
+			podsjson.decrement(val0.name);
+			expect(podsjson.get(val0.name).count).toBe(2);
+			podsjson.decrement(val0.name);
+			expect(podsjson.get(val0.name).count).toBe(1);
+			
+			// this next decrement takes it down to zero, where the pod will just be removed
+			podsjson.decrement(val0.name);
+			expect(podsjson.get(val0.name)).toBeFalsy();
+		});
+
+		it ('writes pods to the pods.json', function () {
+			podsjson.clear();
+
+			var vals = {
+				'Foo': { name: 'Foo', type: 'podspec', spec: '1.0', count: 1 },
+				'Bar': { name: 'Bar', type: 'podspec', spec: '2.0', count: 2 },
+				'Baz': { name: 'Baz', type: 'podspec', spec: '3.0', count: 3 }
+			};
+			
+			podsjson.setJson('Foo', vals.Foo);
+			podsjson.setJson('Bar', vals.Bar);
+			podsjson.setJson('Baz', vals.Baz);
+
+			podsjson.write();
+
+			// verify by reading it back in a new PodsJson 
+			var newPodsJson = new PodsJson(fixturePodsJson);
+			expect(newPodsJson.get('Foo')).toBeTruthy();
+			expect(newPodsJson.get('Bar')).toBeTruthy();
+			expect(newPodsJson.get('Baz')).toBeTruthy();
+
+			function podEqual(a, b) {
+				return (
+					a.name === b.name &&
+					a.type === b.type &&
+					a.spec === b.spec &&
+					a.count === b.count
+				);
+			}
+
+			expect(podEqual(podsjson.get('Foo'), newPodsJson.get('Foo'))).toBe(true);
+			expect(podEqual(podsjson.get('Bar'), newPodsJson.get('Bar'))).toBe(true);
+			expect(podEqual(podsjson.get('Baz'), newPodsJson.get('Baz'))).toBe(true);
+		});
+
+	});
+
+	it('tear down', function () {
+		podsjson.destroy();
+	});
+});
+

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ad096866/tests/spec/unit/podMod.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/podMod.spec.js b/tests/spec/unit/podMod.spec.js
deleted file mode 100644
index c942fdb..0000000
--- a/tests/spec/unit/podMod.spec.js
+++ /dev/null
@@ -1,87 +0,0 @@
-var fs = require('fs'),
-	path = require('path'),
-	util = require('util'),
-	superspawn = require('cordova-common').superspawn,
-	CordovaError = require('cordova-common').CordovaError;
-
-var podMod = require(path.resolve(path.join(__dirname, '..', '..', '..', 'bin', 'templates', 'scripts', 'cordova', 'lib', 'podMod.js')));
-
-var fixtureProject = { 'path' : path.resolve(__dirname, 'fixtures', 'testProj'), 
-						'pathToProjectFile' : path.resolve(__dirname, 'fixtures', 'testProj', 'platforms', 'ios', 'HelloCordova.xcodeproj'),
-						'pathToProjectDirectory' : path.resolve(__dirname, 'fixtures', 'testProj', 'platforms', 'ios'),
-						'id' : 'testProj' };
-
-var samplePods = { 'AFNetworking' : 'AFNetworking', 
-					'emptyPod' : '' };
-var sampleSpec = { 'AFNetworkingSpec' : '~> 2.0', 
-					'emptySpec' : '' };
-var samplePodsJSON = { 'AFNetworkingPodsJSON' : {'AFNetworking' : {'count': 1, 'spec' : '~> 2.0'}},
-						'emptyPodsJSON' : {} };
-
-
-var fixturePodfile = path.resolve(__dirname, 'fixtures', 'testProj', 'platforms', 'ios', 'Podfile');
-
-
-// tests are nested in a describe to ensure clean up happens after all unit tests are run
-describe('unit tests for pod module', function () {
-
-	describe('tests', function () {
-		describe('installPodSync', function () {
-			beforeEach(function () {
-				spyOn(fs, 'writeFileSync').andCallThrough();
-			});
-
-			afterEach(function () {
-			    fs.writeFileSync(fixturePodfile, util.format('platform :ios, \'8.0\'\n\ntarget \'%s\' do\n\n  project \'%s\'\n\n  \n\nend' , fixtureProject.id, fixtureProject.pathToProjectFile));
-			});
-
-			it ('throws cordova error when no pod name provided', function () {
-				//expect cordova error to have been thrown
-				expect( function () { podMod.addToPodfileSync(fixtureProject.id, fixtureProject.pathToProjectFile, samplePods.emptyPod, sampleSpec.emptySpec, samplePodsJSON.emptyPodsJSON); } ).toThrow(new CordovaError('\nERROR: name of pod is not specified\n'));
-			});
-
-			it ('writes to the Podfile via fs.writeFileSync', function () {
-				podMod.addToPodfileSync(fixtureProject.id, fixtureProject.pathToProjectFile, samplePods.AFNetworking, sampleSpec.AFNetworkingSpec, samplePodsJSON.emptyPodsJSON);
-				expect(fs.writeFileSync).toHaveBeenCalled();
-			});
-
-			it ('does not write to Podfile when pod already installed', function () {
-				podMod.addToPodfileSync(fixtureProject.id, fixtureProject.pathToProjectFile, samplePods.AFNetworking, sampleSpec.AFNetworkingSpec, samplePodsJSON.AFNetworkingPodsJSON);
-				expect(fs.writeFileSync).not.toHaveBeenCalled();
-			});
-		});
-
-		describe('uninstallPodSync', function () {
-			beforeEach(function () {
-				spyOn(fs, 'writeFileSync').andCallThrough();
-			});
-
-			afterEach(function () {
-				fs.writeFileSync(fixturePodfile, util.format('platform :ios, \'8.0\'\n\ntarget \'%s\' do\n\n  project \'%s\'\n\n  \n\nend' , fixtureProject.id, fixtureProject.pathToProjectFile));
-			});
-
-			it ('removes pod from Podfile', function () {
-				podMod.removeFromPodfileSync(fixtureProject.pathToProjectDirectory, samplePods.AFNetworking);
-
-				expect(fs.writeFileSync).toHaveBeenCalled();
-				var fixturePodfileContent = fs.readFileSync(fixturePodfile, 'utf8');
-				expect(fixturePodfileContent.indexOf(samplePods.AFNetworking) === -1);
-			});
-		});
-
-		describe('installPodSuperspawn', function () {
-			beforeEach(function () {
-				spyOn(superspawn, 'spawn').andCallThrough();
-			});
-
-			it ('calls superspawn with pod install', function () {
-				podMod.installAllPods(fixtureProject.pathToProjectFile, true);
-				expect(superspawn.spawn).toHaveBeenCalled();
-			});
-		});
-	});
-
-	it('tear down', function () {
-		fs.unlinkSync(fixturePodfile);
-	});
-});
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


Mime
View raw message