You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by lo...@apache.org on 2013/05/07 17:18:50 UTC

[13/30] git commit: gnarliest future->master merge evar

gnarliest future->master merge evar


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

Branch: refs/heads/future
Commit: f677a15313b4f57091515a116fef4a885b982008
Parents: 0b99039 13982f2
Author: Fil Maj <ma...@gmail.com>
Authored: Tue Apr 23 15:57:53 2013 -0700
Committer: Fil Maj <ma...@gmail.com>
Committed: Tue Apr 23 15:57:53 2013 -0700

----------------------------------------------------------------------
 .gitmodules                                        |    3 -
 FUTURE.md                                          |   42 +
 README.md                                          |  215 ++-
 main.js                                            |  118 +
 package.json                                       |   36 +-
 platforms/android.js                               |  226 --
 platforms/blackberry.js                            |  183 --
 platforms/ios.js                                   |  443 ----
 platforms/wp7.js                                   |  236 --
 platforms/wp8.js                                   |  237 --
 platforms/www.js                                   |   43 -
 plugman.js                                         |  158 +--
 spec/fetch.spec.js                                 |   42 +
 spec/install.spec.js                               |   90 +
 spec/platforms/android.spec.js                     |  217 ++
 spec/platforms/blackberry.spec.js                  |   50 +
 spec/platforms/common.spec.js                      |   26 +
 spec/plugins/AndroidJS/plugin.xml                  |   35 +
 spec/plugins/AndroidJS/www/android.js              |    1 +
 spec/plugins/ChildBrowser/plugin.xml               |  141 ++
 .../ChildBrowser/src/android/ChildBrowser.java     |   19 +
 .../src/ios/ChildBrowser.bundle/arrow_left.png     |  Bin 0 -> 2946 bytes
 .../src/ios/ChildBrowser.bundle/arrow_left@2x.png  |  Bin 0 -> 2946 bytes
 .../src/ios/ChildBrowser.bundle/arrow_right.png    |  Bin 0 -> 2946 bytes
 .../src/ios/ChildBrowser.bundle/arrow_right@2x.png |  Bin 0 -> 2946 bytes
 .../src/ios/ChildBrowser.bundle/but_refresh.png    |  Bin 0 -> 3369 bytes
 .../src/ios/ChildBrowser.bundle/but_refresh@2x.png |  Bin 0 -> 3369 bytes
 .../src/ios/ChildBrowser.bundle/compass.png        |  Bin 0 -> 3035 bytes
 .../src/ios/ChildBrowser.bundle/compass@2x.png     |  Bin 0 -> 3035 bytes
 .../ChildBrowser/src/ios/ChildBrowserCommand.h     |   49 +
 .../ChildBrowser/src/ios/ChildBrowserCommand.m     |   86 +
 .../src/ios/ChildBrowserViewController.h           |   73 +
 .../src/ios/ChildBrowserViewController.m           |  239 ++
 .../src/ios/ChildBrowserViewController.xib         |  875 ++++++++
 spec/plugins/ChildBrowser/src/ios/TargetDirTest.h  |   20 +
 spec/plugins/ChildBrowser/src/ios/TargetDirTest.m  |    1 +
 .../src/ios/preserveDirs/PreserveDirsTest.h        |   20 +
 .../src/ios/preserveDirs/PreserveDirsTest.m        |    1 +
 spec/plugins/ChildBrowser/www/childbrowser.js      |   19 +
 .../ChildBrowser/www/childbrowser/image.jpg        |    1 +
 .../ChildBrowser/www/childbrowser_file.html        |    1 +
 spec/plugins/DummyPlugin/plugin.xml                |  103 +
 .../DummyPlugin/src/android/DummyPlugin.java       |   19 +
 spec/plugins/DummyPlugin/src/blackberry/client.js  |   19 +
 spec/plugins/DummyPlugin/src/blackberry/index.js   |   19 +
 spec/plugins/DummyPlugin/www/dummyplugin.js        |   19 +
 spec/plugins/DummyPlugin/www/dummyplugin/image.jpg |    1 +
 spec/plugins/FaultyPlugin/plugin.xml               |   74 +
 .../FaultyPlugin/src/android/FaultyPlugin.java     |   19 +
 spec/plugins/FaultyPlugin/src/ios/FaultyPlugin.h   |   49 +
 spec/plugins/FaultyPlugin/src/ios/FaultyPlugin.m   |   86 +
 spec/plugins/VariablePlugin/plugin.xml             |   37 +
 spec/plugins/WebNotifications/plugin.xml           |   45 +
 .../WebNotifications/src/ios/AppDelegate.m.diff    |   18 +
 .../WebNotifications/src/ios/WebNotifications.h    |   35 +
 .../WebNotifications/src/ios/WebNotifications.m    |  124 +
 .../WebNotifications/www/webnotifications.js       |  123 +
 spec/plugins/WeblessPlugin/plugin.xml              |   81 +
 .../WeblessPlugin/src/android/WeblessPlugin.java   |   19 +
 .../src/ios/WeblessPlugin.bundle/arrow_left.png    |  Bin 0 -> 2946 bytes
 .../src/ios/WeblessPlugin.bundle/arrow_left@2x.png |  Bin 0 -> 2946 bytes
 .../src/ios/WeblessPlugin.bundle/arrow_right.png   |  Bin 0 -> 2946 bytes
 .../ios/WeblessPlugin.bundle/arrow_right@2x.png    |  Bin 0 -> 2946 bytes
 .../src/ios/WeblessPlugin.bundle/but_refresh.png   |  Bin 0 -> 3369 bytes
 .../ios/WeblessPlugin.bundle/but_refresh@2x.png    |  Bin 0 -> 3369 bytes
 .../src/ios/WeblessPlugin.bundle/compass.png       |  Bin 0 -> 3035 bytes
 .../src/ios/WeblessPlugin.bundle/compass@2x.png    |  Bin 0 -> 3035 bytes
 .../WeblessPlugin/src/ios/WeblessPluginCommand.h   |   49 +
 .../WeblessPlugin/src/ios/WeblessPluginCommand.m   |   86 +
 .../src/ios/WeblessPluginViewController.h          |   73 +
 .../src/ios/WeblessPluginViewController.m          |  239 ++
 .../src/ios/WeblessPluginViewController.xib        |  875 ++++++++
 spec/plugins/cordova.echo/.gitignore               |    1 +
 spec/plugins/cordova.echo/plugin.xml               |   24 +
 spec/plugins/cordova.echo/src/blackberry/client.js |   53 +
 .../src/blackberry/device/echoJnext.so             |  Bin 0 -> 1291818 bytes
 spec/plugins/cordova.echo/src/blackberry/index.js  |   85 +
 .../cordova.echo/src/blackberry/manifest.json      |    5 +
 .../src/blackberry/public/json/autolink.h          |   19 +
 .../src/blackberry/public/json/config.h            |   43 +
 .../src/blackberry/public/json/features.h          |   42 +
 .../src/blackberry/public/json/forwards.h          |   39 +
 .../cordova.echo/src/blackberry/public/json/json.h |   10 +
 .../src/blackberry/public/json/reader.h            |  196 ++
 .../src/blackberry/public/json/value.h             | 1069 +++++++++
 .../src/blackberry/public/json/writer.h            |  174 ++
 .../src/blackberry/public/json_batchallocator.h    |  125 ++
 .../src/blackberry/public/json_internalarray.inl   |  448 ++++
 .../src/blackberry/public/json_internalmap.inl     |  607 +++++
 .../src/blackberry/public/json_reader.cpp          |  894 ++++++++
 .../src/blackberry/public/json_value.cpp           | 1726 +++++++++++++++
 .../src/blackberry/public/json_valueiterator.inl   |  292 +++
 .../src/blackberry/public/json_writer.cpp          |  829 +++++++
 .../cordova.echo/src/blackberry/public/plugin.cpp  |  320 +++
 .../cordova.echo/src/blackberry/public/plugin.h    |   70 +
 .../src/blackberry/public/tokenizer.cpp            |  222 ++
 .../cordova.echo/src/blackberry/public/tokenizer.h |   55 +
 .../src/blackberry/simulator/echoJnext.so          |  Bin 0 -> 231778 bytes
 .../cordova.echo/src/blackberry/src/echo.cpp       |  121 +
 .../cordova.echo/src/blackberry/src/echo.hpp       |   45 +
 spec/plugins/cordova.echo/src/device/echoJnext.so  |  Bin 0 -> 1291818 bytes
 .../cordova.echo/src/simulator/echoJnext.so        |  Bin 0 -> 231778 bytes
 spec/plugins/multiple-children/plugin.xml          |  109 +
 spec/prepare.spec.js                               |   65 +
 spec/projects/FriendSting-Info.plist               |   78 +
 spec/projects/android_one/AndroidManifest.xml      |   71 +
 spec/projects/android_one/res/xml/plugins.xml      |   38 +
 spec/projects/android_two/AndroidManifest.xml      |   69 +
 spec/projects/android_two/res/xml/config.xml       |   54 +
 spec/projects/blackberry/www/config.xml            |   97 +
 spec/projects/blackberry/www/plugins.xml           |   35 +
 .../CordovaLib.xcodeproj/project.pbxproj           |  636 ++++++
 spec/projects/ios-config-xml/SampleApp-Info.plist  |   78 +
 .../SampleApp.xcodeproj/project.orig.pbxproj       |  498 +++++
 .../SampleApp.xcodeproj/project.pbxproj            |  498 +++++
 .../ios-config-xml/SampleApp/SampleApp-Info.plist  |   78 +
 spec/projects/ios-config-xml/SampleApp/config.xml  |   59 +
 .../CordovaLib.xcodeproj/project.pbxproj           |  636 ++++++
 .../SampleApp.xcodeproj/project.orig.pbxproj       |  498 +++++
 .../ios-plist/SampleApp.xcodeproj/project.pbxproj  |  498 +++++
 spec/projects/ios-plist/SampleApp/PhoneGap.plist   |   53 +
 .../ios-plist/SampleApp/SampleApp-Info.plist       |   80 +
 .../projects/multiple-children/AndroidManifest.xml |   69 +
 .../projects/multiple-children/res/xml/plugins.xml |   38 +
 spec/remove.spec.js                                |   30 +
 spec/uninstall.spec.js                             |   53 +
 spec/util/plugins.spec.js                          |   66 +
 spec/util/xml-helpers.spec.js                      |   72 +
 src/fetch.js                                       |   34 +
 src/install.js                                     |  121 +
 src/platforms.js                                   |    8 +
 src/platforms/android.js                           |  131 ++
 src/platforms/blackberry.js                        |  110 +
 src/platforms/common.js                            |   42 +
 src/platforms/ios.js                               |  292 +++
 src/platforms/wp7.js                               |  236 ++
 src/platforms/wp8.js                               |  237 ++
 src/prepare.js                                     |  152 ++
 src/remove.js                                      |   14 +
 src/uninstall.js                                   |   52 +
 src/util/config-changes.js                         |   38 +
 src/util/fs.js                                     |   34 +
 src/util/plist-helpers.js                          |   90 +
 src/util/plugins.js                                |  123 +
 src/util/search-and-replace.js                     |   37 +
 src/util/xml-helpers.js                            |  176 ++
 test/android-one-install.js                        |  169 --
 test/android-one-uninstall.js                      |   78 +-
 test/android-two-install.js                        |   79 +-
 test/android-two-uninstall.js                      |   56 +-
 test/blackberry-install.js                         |   29 +-
 test/blackberry-uninstall.js                       |   38 +-
 test/config-changes.js                             |    3 +-
 test/ios-config-xml-install.js                     |  148 +-
 test/ios-config-xml-uninstall.js                   |  138 +-
 test/ios-plist-install.js                          |   26 +-
 test/plugins/ChildBrowser/plugin-old.xml           |   96 -
 test/plugins/ChildBrowser/plugin.xml               |  138 --
 .../ChildBrowser/www/childbrowser_file.html        |    1 +
 test/plugins/DummyPlugin/plugin.xml                |    8 +-
 test/plugins/FaultyPlugin/plugin.xml               |   12 +-
 test/plugins/PGSQLitePlugin                        |    1 -
 test/plugins/WebNotifications/plugin.xml           |    4 +-
 test/plugins/WeblessPlugin/plugin.xml              |   14 +-
 test/plugins/cordova.echo/plugin.xml               |   10 +-
 test/plugman.js                                    |   97 +-
 test/remote-test.js                                |   29 +-
 test/www-only.js                                   |   80 -
 util/config-changes.js                             |   38 -
 util/fs.js                                         |   34 -
 util/plist-helpers.js                              |   90 -
 util/plugins.js                                    |  106 -
 util/search-and-replace.js                         |   37 -
 util/xml-helpers.js                                |  176 --
 174 files changed, 19000 insertions(+), 2890 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/main.js
----------------------------------------------------------------------
diff --cc main.js
index 0000000,f3ada41..fc50c23
mode 000000,100755..100755
--- a/main.js
+++ b/main.js
@@@ -1,0 -1,118 +1,118 @@@
+ #!/usr/bin/env node
+ /*
+  *
+  * 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.
+  *
+ */
+ 
+ // copyright (c) 2013 Andrew Lunny, Adobe Systems
+ var path = require('path')
+     , url = require('url')
+     , package = require(path.join(__dirname, 'package'))
+     , nopt = require('nopt')
+     , plugins = require('./src/util/plugins')
+     , plugman = require('./plugman');
+ 
 -var known_opts = { 'platform' : [ 'ios', 'android', 'blackberry' ]
++var known_opts = { 'platform' : [ 'ios', 'android', 'blackberry', 'wp7', 'wp8' ]
+             , 'project' : path
+             , 'plugin' : [String, path, url]
+             , 'remove' : Boolean
+             , 'install' : Boolean
+             , 'uninstall' : Boolean
+             , 'fetch' : Boolean
+             , 'list' : Boolean
+             , 'v' : Boolean
+             , 'debug' : Boolean
+             , 'prepare' : Boolean
+             , 'plugins': path
+             , 'link': Boolean
+             , 'variable' : Array
+             }, shortHands = { 'var' : 'variable' };
+ 
+ var cli_opts = nopt(known_opts);
+ 
+ // Default the plugins_dir to './cordova/plugins'.
+ var plugins_dir;
+ 
+ // Without these arguments, the commands will fail and print the usage anyway.
+ if (cli_opts.plugins_dir || cli_opts.project) {
+     plugins_dir = typeof cli_opts.plugins_dir == 'string' ?
+         cli_opts.plugins_dir :
+         path.join(cli_opts.project, 'cordova', 'plugins');
+ }
+ 
+ // only dump stack traces in debug mode, otherwise show error message and exit
+ // provide clean output on exceptions rather than dumping a stack trace
+ process.on('uncaughtException', function(error){
+     if (cli_opts.debug) {
+         console.error(error.stack);
+     } else {
+         console.error(error + '\n');
+     }
+     process.exit(1);
+ });
+ 
+ if (cli_opts.v) {
+     console.log(package.name + ' version ' + package.version);
+ }
+ else if (cli_opts.list) {
+     plugins.listAllPlugins(function(plugins) {
+         for(var i = 0, j = plugins.length ; i < j ; i++) {
+             console.log(plugins[i].value.name, '-', plugins[i].value.description);
+         }
+     });
+ }
+ else if (cli_opts.prepare && cli_opts.project) {
+     plugman.prepare(cli_opts.project, cli_opts.platform, plugins_dir);
+ }
+ else if (cli_opts.remove) {
+     plugman.remove(cli_opts.plugin, plugins_dir);
+     console.log('Plugin ' + cli_opts.plugin + ' deleted.');
+ }
+ else if (cli_opts.fetch) {
+     plugman.fetch(cli_opts.plugin, plugins_dir, cli_opts.link);
+ }
+ else if (!cli_opts.platform || !cli_opts.project || !cli_opts.plugin) {
+     printUsage();
+ }
+ else if (cli_opts.uninstall) {
+     plugman.uninstall(cli_opts.platform, cli_opts.project, cli_opts.plugin, plugins_dir);
+ }
+ else {
+     var cli_variables = {}
+     if (cli_opts.variable) {
+         cli_opts.variable.forEach(function (variable) {
+             var tokens = variable.split('=');
+             var key = tokens.shift().toUpperCase();
+             if (/^[\w-_]+$/.test(key)) cli_variables[key] = tokens.join('=');
+         });
+     }
+     plugman.install(cli_opts.platform, cli_opts.project, cli_opts.plugin, plugins_dir, cli_variables);
+ }
+ 
+ function printUsage() {
+     platforms = known_opts.platform.join('|');
+     console.log('Usage\n---------');
+     console.log('Fetch a plugin:\n\t' + package.name + ' --fetch --plugin <directory|git-url|name> [--plugins_dir <directory>]\n');
+     console.log('Install an already fetched plugin:\n\t' + package.name + ' --platform <'+ platforms +'> --project <directory> --plugin <name> [--plugins_dir <directory>]\n');
+     console.log('Uninstall a plugin:\n\t' + package.name + ' --uninstall --platform <'+ platforms +'> --project <directory> --plugin <name> [--plugins_dir <directory>]\n');
+     console.log('Delete the local copy of a plugin:\n\t' + package.name + ' --remove --plugin <name> [--plugins_dir <directory>]\n');
+     console.log('List plugins:\n\t' + package.name + ' --list [--plugins_dir <directory>]\n');
+     console.log('Prepare project:\n\t' + package.name + ' --prepare --platform <ios|android|bb10> --project <directory> [--plugins_dir <directory>]');
+     console.log('\n\t--plugins_dir defaults to <project>/cordova/plugins, but can be any directory containing a subdirectory for each plugin');
+ }
+ 
+ 

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/package.json
----------------------------------------------------------------------
diff --cc package.json
index 217a23a,d687620..83add6e
--- a/package.json
+++ b/package.json
@@@ -2,10 -2,10 +2,10 @@@
    "author": "Andrew Lunny <al...@gmail.com>",
    "name": "plugman",
    "description": "install/uninstall Cordova plugins",
 -  "version": "0.5.7",
 +  "version": "0.5.8",
    "repository": {
      "type": "git",
-     "url": "git://github.com/imhotep/plugman.git"
+     "url": "git://git-wip-us.apache.org/repos/asf/cordova-plugman.git"
    },
    "main": "plugman.js",
    "engines": {

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/plugman.js
----------------------------------------------------------------------
diff --cc plugman.js
index ac45c98,5ab22a2..98e0cf4
--- a/plugman.js
+++ b/plugman.js
@@@ -19,153 -18,11 +18,10 @@@
  */
  
  // copyright (c) 2013 Andrew Lunny, Adobe Systems
- var fs = require('fs')
-   , path = require('path')
-   , url = require('url')
-   , package = require(path.join(__dirname, 'package'))
-   , et = require('elementtree')
-   , nopt = require('nopt')
-   , plugins = require('./util/plugins')
-   , platform_modules = {
-         'android': require('./platforms/android'),
-         'ios': require('./platforms/ios'),
-         'blackberry': require('./platforms/blackberry'),
-         'wp7': require('./platforms/wp7'),
-         'wp8': require('./platforms/wp8'),
-         'www': require('./platforms/www')
-     };
--
- var known_opts = { 'platform' : [ 'ios', 'android', 'blackberry' ,'wp7', 'wp8' , 'www' ]
-             , 'project' : path
-             , 'plugin' : [String, path, url]
-             , 'remove' : Boolean
-             , 'list' : Boolean
-             , 'v' : Boolean
-             , 'debug' : Boolean
-             , 'variable' : Array
-             }, shortHands = { 'var' : 'variable' };
- 
- var cli_opts = nopt(known_opts);
- 
- // only dump stack traces in debug mode, otherwise show error message and exit
- if (!cli_opts.debug) {
-     // provide clean output on exceptions rather than dumping a stack trace
-     process.on('uncaughtException', function(error){
-         console.error(error + '\n');
-         process.exit(1);
-     });
- }
- 
- if (cli_opts.v) {
-     console.log(package.name + ' version ' + package.version);
- }
- else if (cli_opts.list) {
-     plugins.listAllPlugins(function(plugins) {
-       for(var i = 0, j = plugins.length ; i < j ; i++) {
-         console.log(plugins[i].value.name, '-', plugins[i].value.description);
-       }
-     });
- }
- else if (!cli_opts.platform || !cli_opts.project || !cli_opts.plugin) {
-     printUsage();
- }
- else if (cli_opts.remove) {
-     handlePlugin('uninstall', cli_opts.platform, cli_opts.project, cli_opts.plugin);
- }
- else {
-   var cli_variables = {}
-   if (cli_opts.variable) {
-     cli_opts.variable.forEach(function (variable) {
-         var tokens = variable.split('=');
-         var key = tokens.shift().toUpperCase();
-         if (/^[\w-_]+$/.test(key)) cli_variables[key] = tokens.join('=');
-         });
-   }
-   handlePlugin('install', cli_opts.platform, cli_opts.project, cli_opts.plugin, cli_variables);
- }
- 
- function printUsage() {
-     platforms = known_opts.platform.join('|');
-     console.error('Usage\n---------');
-     console.error('Add a plugin:\n\t' + package.name + ' --platform <'+ platforms +'> --project <directory> --variable <preference_name>="<substituion>" --plugin <directory|git-url|name>\n');
-     console.error('Remove a plugin:\n\t' + package.name + ' --remove --platform <'+ platforms +'> --project <directory> --plugin <directory|git-url|name>\n');
-     console.error('List plugins:\n\t' + package.name + ' --list\n');
-     process.exit(1);
- }
- 
- function execAction(action, platform, project_dir, plugin_dir, cli_variables) {
-     var xml_path     = path.join(plugin_dir, 'plugin.xml')
-       , xml_text     = fs.readFileSync(xml_path, 'utf-8')
-       , plugin_et    = new et.ElementTree(et.XML(xml_text))
-       , filtered_variables = {};
- 
-     if (action == 'install') {
-         // checking preferences
-         prefs = plugin_et.findall('./preference') || [];
-         prefs = prefs.concat(plugin_et.findall('./platform[@name="'+platform+'"]/preference'));
-         var missing_vars = [];
-         prefs.forEach(function (pref) {
-             var key = pref.attrib["name"].toUpperCase();
-             if (cli_variables[key] == undefined)
-                 missing_vars.push(key)
-             else
-                 filtered_variables[key] = cli_variables[key]
-         })
-         if (missing_vars.length > 0) {
-             console.error('Variable missing: ' + missing_vars.join(", "));
-             return;
-         }
- 
-         if((info = plugin_et.find('./platform[@name="'+platform+'"]/info'))) {
-             console.log(info.text);
-         }
-     }
-     
-     // run the platform-specific function
-     try {
-       platform_modules[platform].handlePlugin(action, project_dir, plugin_dir, plugin_et, filtered_variables);
-       console.log('plugin ' + action + 'ed');
-     } catch(e) {
-         var revert = (action == "install" ? "force-uninstall" : "force-install" );
-         console.error("An error occurred for action", action, ":", e.message, "\nTrying to revert changes...");
-         try {
-           platform_modules[platform].handlePlugin(revert, project_dir, plugin_dir, plugin_et, filtered_variables);
-         } catch(e) {
-           console.log("Changes might have not been reverted: "+e.message);
-           process.exit(1);
-         }
-     }
- }
- 
- function handlePlugin(action, platform, project_dir, plugin_dir, cli_variables) {
-     var plugin_xml_path, async = false;
- 
-     // clone from git repository
-     if(plugin_dir.indexOf('https://') == 0 || plugin_dir.indexOf('git://') == 0) {
-         plugin_dir = plugins.clonePluginGitRepo(plugin_dir);
-     }
- 
-     plugin_xml_path = path.join(plugin_dir, 'plugin.xml');
-     if (!fs.existsSync(plugin_xml_path)) {
-         // try querying the plugin database
-         async = true;
-         plugins.getPluginInfo(plugin_dir,
-             function(plugin_info) {
-                 execAction(action, platform, project_dir, plugins.clonePluginGitRepo(plugin_info.url), cli_variables);
-             },
-             function(e) {
-                 throw new Error(action + ' failed. "' + plugin_xml_path + '" not found');
-             }
-         );
-     }
- 
-     if (!platform_modules[platform]) {
-         throw { name: "Platform Error", message: platform + " not supported" }
-     }
- 
-     // check arguments and resolve file paths
-     if(!async) {
-         execAction(action, platform, project_dir, plugin_dir, cli_variables);
-     }
- }
- 
+ module.exports = {
+     install:  require('./src/install'),
+     uninstall:require('./src/uninstall'),
+     remove:   require('./src/remove'),
+     fetch:    require('./src/fetch'),
+     prepare:  require('./src/prepare')
+ };

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/spec/plugins/ChildBrowser/plugin.xml
----------------------------------------------------------------------
diff --cc spec/plugins/ChildBrowser/plugin.xml
index 0000000,9c87b06..ee5e2ba
mode 000000,100644..100644
--- a/spec/plugins/ChildBrowser/plugin.xml
+++ b/spec/plugins/ChildBrowser/plugin.xml
@@@ -1,0 -1,95 +1,141 @@@
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!--
+ 
+  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.
+ 
+ -->
+ 
+ <plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
+     xmlns:android="http://schemas.android.com/apk/res/android"
+     id="com.phonegap.plugins.childbrowser"
+     version="0.6.0">
+ 
+     <name>Child Browser</name>
+ 
+     <asset src="www/childbrowser" target="childbrowser" />
+     <asset src="www/childbrowser_file.html" target="childbrowser_file.html" />
+ 
+     <js-module src="www/childbrowser.js" name="ChildBrowser">
+         <clobbers target="childbrowser" />
+     </js-module>
+ 
+     <access origin="build.phonegap.com" />
 -    <access origin="$APP_ID.s3.amazonaws.com" />
++    <access origin="s3.amazonaws.com" />
+ 
+     <!-- android -->
+     <platform name="android">
+         <config-file target="AndroidManifest.xml" parent="/manifest/application">
+             <activity android:name="com.phonegap.plugins.childBrowser.ChildBrowser"
+                       android:label="@string/app_name">
+                 <intent-filter>
+                 </intent-filter>
+             </activity>
+         </config-file>
+ 
+         <!-- CDV < 2.0 -->
+         <config-file target="res/xml/plugins.xml" parent="/plugins">
+             <plugin name="ChildBrowser"
+                 value="com.phonegap.plugins.childBrowser.ChildBrowser"/>
+         </config-file>
+ 
+         <!-- CDV 2.0+ (for now) -->
+         <config-file target="res/xml/config.xml" parent="/cordova/plugins">
+             <plugin name="ChildBrowser"
+                 value="com.phonegap.plugins.childBrowser.ChildBrowser"/>
+         </config-file>
+ 
+         <source-file src="src/android/ChildBrowser.java"
+                 target-dir="src/com/phonegap/plugins/childBrowser" />
+         <info>
+           Please make sure you read this because it is very important to complete the installation of your plugin
+         </info>
+     </platform>
+ 
+     <!-- ios -->
+     <platform name="ios">
+         <plugins-plist key="com.phonegap.plugins.childbrowser"
+             string="ChildBrowserCommand" />
+ 
+         <config-file target="config.xml" parent="/widget/plugins">
+             <plugin name="ChildBrowser"
+                 value="ChildBrowserCommand" />
+         </config-file>
+ 
+         <resource-file src="src/ios/ChildBrowser.bundle" />
+         <resource-file src="src/ios/ChildBrowserViewController.xib" />
+ 
 -        <header-file src="src/ios/ChildBrowserCommand.h" />
 -        <header-file src="src/ios/ChildBrowserViewController.h" />
 -        <header-file src="src/ios/preserveDirs/PreserveDirsTest.h" preserve-dirs="true" />
 -        <header-file src="src/ios/TargetDirTest.h" target-dir="targetDir"/>
++        <config-file target="*-Info.plist" parent="AppId">
++            <string>$APP_ID</string>
++        </config-file>
++        
++        <config-file target="*-Info.plist" parent="CFBundleURLTypes">
++            <array>
++              <dict>
++                <key>PackageName</key>
++                <string>$PACKAGE_NAME</string>
++              </dict>
++            </array>
++        </config-file>
++
++        <header-file src="ChildBrowserCommand.h" />
++        <header-file src="ChildBrowserViewController.h" />
++        <header-file src="preserveDirs/PreserveDirsTest.h" preserve-dirs="true" />
++        <header-file src="TargetDirTest.h" target-dir="targetDir"/>
+ 
+         <source-file src="src/ios/ChildBrowserCommand.m" />
+         <source-file src="src/ios/ChildBrowserViewController.m" />
+         <source-file src="src/ios/preserveDirs/PreserveDirsTest.m" preserve-dirs="true" />
+         <header-file src="src/ios/TargetDirTest.m" target-dir="targetDir"/>
+ 
+         <!-- framework for testing (not actual dependency of ChildBrowser -->
+         <framework src="libsqlite3.dylib" />
+         <framework src="social.framework" weak="true" />
+         <framework src="music.framework" weak="rabbit" />
+     </platform>
++    <!-- wp7 -->
++    <platform name="wp7">
++        <resource-file src="src\wp7\Images\appbar.back.rest.png" />
++        <config-file target="config.xml" parent="/widget/plugins">
++            <plugin name="ChildBrowser"
++                value="ChildBrowser"/>
++        </config-file>
++
++        <source-file src="src\wp7\ChildBrowserCommand.cs"
++                     target-dir="Plugins\" />
++
++        <!-- modify the project file to include the added files -->
++        <config-file target=".csproj" parent=".">  
++        </config-file> 
++
++    </platform>
++
++    <!-- wp8 -->
++    <platform name="wp8">
++        <resource-file src="src\wp7\Images\appbar.back.rest.png" />
++        <config-file target="config.xml" parent="/widget/plugins">
++            <plugin name="ChildBrowser"
++                value="ChildBrowser"/>
++        </config-file>
++
++        <source-file src="src\wp7\ChildBrowserCommand.cs"
++                     target-dir="Plugins\" />
++
++        <!-- modify the project file to include the added files -->
++        <config-file target=".csproj" parent=".">  
++        </config-file> 
++
++    </platform>
+ </plugin>

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/src/platforms.js
----------------------------------------------------------------------
diff --cc src/platforms.js
index 0000000,4ac29e3..862f47b
mode 000000,100644..100644
--- a/src/platforms.js
+++ b/src/platforms.js
@@@ -1,0 -1,5 +1,8 @@@
+ module.exports = {
+     'android': require('./platforms/android'),
+     'ios': require('./platforms/ios'),
 -    'blackberry': require('./platforms/blackberry')
++    'blackberry': require('./platforms/blackberry'),
++    'wp7': require('./platforms/wp7'),
++    'wp8': require('./platforms/wp8'),
++    'www': require('./platforms/www')
+ };

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/src/platforms/wp7.js
----------------------------------------------------------------------
diff --cc src/platforms/wp7.js
index 0000000,0000000..5220395
new file mode 100644
--- /dev/null
+++ b/src/platforms/wp7.js
@@@ -1,0 -1,0 +1,236 @@@
++/*
++ *
++ * Copyright 2013 Jesse MacFadyen
++ *
++ * 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.
++ *
++*/
++
++/*
++node plugman --platform wp7 --project '/c//users/jesse/documents/visual studio 2012/Projects/TestPlugin7/' --plugin '.\test\plugins\ChildBrowser\'
++
++TODO:  ( Apr. 16, 2013 - jm )
++- Update WMAppManifest.xml with any new required capabilities 
++- add references for any new libraries required by plugin
++
++
++
++*/
++
++var fs = require('fs'),
++    path = require('path'),
++    glob = require('glob'),
++    shell = require('shelljs'),
++    et = require('elementtree'),
++    xml_helpers = require('../util/xml-helpers'),
++    getConfigChanges = require('../util/config-changes'),
++    assetsDir = 'www'; // relative path to project's web assets
++
++var unix_projPath,  //  for use with glob
++    projectFilename,//  first csproj returned by glob unix_projPath
++    projPath,       //  full path to the project file, including file name
++    configFilePath, //  path to config.xml
++    assets,         //  assets node et in root ./asset
++    platformTag,    //  wp7 platform node et
++    sourceFiles,    //  ./source-file inside platform
++    hosts,          //  ./access inside root
++    projectChanges; //  <config-file target=".csproj" parent=".">, inside platform
++
++
++
++function copyFileSync(srcPath, destPath) {
++
++  var stats = fs.statSync(srcPath);
++  if(stats.isDirectory()) {
++     shell.mkdir('-p', destPath);
++     // without the added slash at the end, we will get an extra folder inside destination
++     shell.cp('-r', srcPath + "/" , destPath);
++  }
++  else if(fs.existsSync(srcPath)) {
++    shell.cp(srcPath, destPath);
++  }
++  else {
++    console.log("File does not exist :: " + srcPath);
++    return;
++  }
++
++  var msg = shell.error();
++  if(msg) {
++    console.log("msg" + msg);
++    throw { name: "ShellError", message: msg};
++  }
++}    
++
++function initPaths(project_dir, plugin_dir, plugin_et, variables) {
++
++    unix_projPath = project_dir.split("\\").join("/");
++    configFilePath = path.join(unix_projPath,'config.xml');
++    projectFilename = glob.sync('*.csproj',{nocase:true,cwd:unix_projPath})[0];
++    projPath = path.join(unix_projPath,projectFilename);
++    assets = plugin_et.findall('./asset');
++    platformTag = plugin_et.find('./platform[@name="wp7"]');
++    sourceFiles = platformTag.findall('./source-file');
++    projectChanges = platformTag.findall('./config-file[@target=".csproj"]');
++    hosts = plugin_et.findall('./access');
++}
++
++function install(project_dir, plugin_dir, plugin_et, variables) {
++
++  // move asset files
++  assets && assets.forEach(function (asset) {
++      var srcPath = path.resolve(plugin_dir, asset.attrib['src']);
++      var targetPath = path.resolve(project_dir, assetsDir,  asset.attrib['target']);
++      copyFileSync(srcPath, targetPath);
++  });
++
++  // move source files
++  sourceFiles && sourceFiles.forEach(function (sourceFile) {
++      var srcFilePath = path.resolve(plugin_dir,  sourceFile.attrib['src']);
++      var destDir = path.resolve(project_dir, sourceFile.attrib['target-dir']);
++      var destFilePath = path.resolve(destDir, path.basename(sourceFile.attrib['src']));
++      copyFileSync(srcFilePath, destFilePath);
++  });
++
++  updateConfigXml("install", configFilePath, plugin_et);
++
++  et.register_namespace("csproj", "http://schemas.microsoft.com/developer/msbuild/2003");
++  projectChanges && projectChanges.forEach(function (configNode) {
++
++    var docStr = fs.readFileSync(projPath,"utf8");
++
++    // child is the configNode child that we will insert into csproj
++    var child = configNode.find('*'); 
++    // we use empty text as a default, so we always modify the project file so Visual Studio will notice if open.
++    var newNodeText = "";
++    if(child) {
++
++      newNodeText = new et.ElementTree(child).write({xml_declaration:false});
++      newNodeText = newNodeText.split("&#xA;").join("\n").split("&#xD;").join("\r");
++      newNodeText += "\n\r";
++    }
++
++    // insert text right before closing tag
++    var newDocStr = docStr.replace("</Project>", newNodeText + "</Project>");
++
++    // save it, and get out
++    fs.writeFileSync(projPath, newDocStr);
++  });
++}
++
++function updateConfigXml(action, config_path, plugin_et) {
++
++    var hosts = plugin_et.findall('./access');
++    var platformTag = plugin_et.find('./platform[@name="wp7"]');
++    var configChanges = getConfigChanges(platformTag);   
++    var base_config_path = path.basename(config_path);
++        // add whitelist hosts
++    var root = et.Element("config-file");
++        root.attrib['parent'] = '.';
++      
++    hosts && hosts.forEach( function (tag) {
++      root.append(tag);
++    });
++
++    if (root.len()) {
++      var changeList = configChanges[path.basename(config_path)];
++      // if changeList then add to it, otherwise create it.
++      if(changeList) {
++        changeList.push(root);
++      }
++      else {
++        configChanges[path.basename(config_path)] = [root]
++      }
++    }  
++
++    if (configChanges[path.basename(config_path)]) {
++
++          // edit configuration files
++      var xmlDoc = xml_helpers.parseElementtreeSync(config_path)
++      configChanges[base_config_path].forEach( function (configNode) {
++            var selector = configNode.attrib["parent"],
++                children = configNode.findall('*');
++            if( action == 'install') {
++                if (!xml_helpers.graftXML(xmlDoc, children, selector)) {
++                    throw new Error('failed to add children to ' + selector + ' in ' + config_path);
++                }
++            } else {
++                if (!xml_helpers.pruneXML(xmlDoc, children, selector)) {
++                    throw new Error('failed to remove children from ' + selector + ' in ' + config_path);
++                }
++            }
++      });
++    }
++
++    fs.writeFileSync(config_path, xmlDoc.write({indent: 4}));
++}
++
++function uninstall(project_dir, plugin_dir, plugin_et, variables) {
++
++   assets && assets.forEach(function (asset) {
++      var targetPath = path.resolve(project_dir, assetsDir,  asset.attrib['target']);
++      shell.rm('-rf', targetPath);
++   });
++
++   sourceFiles && sourceFiles.forEach(function (sourceFile) {
++      var destDir = path.resolve(project_dir, sourceFile.attrib['target-dir']);
++      var destFilePath = path.resolve(destDir, path.basename(sourceFile.attrib['src']));
++      shell.rm('-rf', destFilePath);
++   });
++
++   updateConfigXml("uninstall", configFilePath, plugin_et);
++
++   et.register_namespace("csproj", "http://schemas.microsoft.com/developer/msbuild/2003");
++
++   projectChanges && projectChanges.forEach(function (configNode) {
++
++    var docStr = fs.readFileSync(projPath,"utf8");
++
++    // child is the configNode child that we will insert into csproj
++    var child = configNode.find('*'); 
++    if(child) {
++      var newNodeText = new et.ElementTree(child).write({xml_declaration:false});
++          
++      newNodeText = newNodeText.split("&#xA;").join("\n").split("&#xD;").join("\r");
++      
++      // insert text right before closing tag
++      var splitString = docStr.split(newNodeText);
++      console.log("split length = " + splitString.length);
++      var newDocStr = splitString.join("");
++
++      // save it, and get out
++      fs.writeFileSync(projPath, newDocStr);
++    }
++    else {
++      // this just lets Visual Studio know to reload the project if it is open
++      fs.writeFileSync(projPath, docStr);
++    }
++  });
++}
++
++exports.handlePlugin = function (action, project_dir, plugin_dir, plugin_et, variables) {
++    console.log("action = " + action);
++    switch(action) {
++        case 'install' :
++            initPaths(project_dir, plugin_dir, plugin_et, variables);
++            install(project_dir, plugin_dir, plugin_et, variables);
++            break;
++        case 'uninstall' :
++            initPaths(project_dir, plugin_dir, plugin_et, variables);
++            uninstall(project_dir, plugin_dir, plugin_et, variables);
++            break;
++        default :
++          throw 'error unknown action';
++          break;
++    }
++}

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/src/platforms/wp8.js
----------------------------------------------------------------------
diff --cc src/platforms/wp8.js
index 0000000,0000000..d1406ee
new file mode 100644
--- /dev/null
+++ b/src/platforms/wp8.js
@@@ -1,0 -1,0 +1,237 @@@
++/*
++/*
++ *
++ * Copyright 2013 Jesse MacFadyen
++ *
++ * 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.
++ *
++*/
++
++/*
++node plugman --platform wp8 --project '/c//users/jesse/documents/visual studio 2012/Projects/TestPlugin7/' --plugin '.\test\plugins\ChildBrowser\'
++
++TODO:  ( Apr. 16, 2013 - jm )
++- Update WMAppManifest.xml with any new required capabilities 
++- add references for any new libraries required by plugin
++
++
++
++*/
++
++var fs = require('fs'),
++    path = require('path'),
++    glob = require('glob'),
++    shell = require('shelljs'),
++    et = require('elementtree'),
++    xml_helpers = require('../util/xml-helpers'),
++    getConfigChanges = require('../util/config-changes'),
++    assetsDir = 'www'; // relative path to project's web assets
++
++var unix_projPath,  //  for use with glob
++    projectFilename,//  first csproj returned by glob unix_projPath
++    projPath,       //  full path to the project file, including file name
++    configFilePath, //  path to config.xml
++    assets,         //  assets node et in root ./asset
++    platformTag,    //  wp8 platform node et
++    sourceFiles,    //  ./source-file inside platform
++    hosts,          //  ./access inside root
++    projectChanges; //  <config-file target=".csproj" parent=".">, inside platform
++
++
++
++function copyFileSync(srcPath, destPath) {
++
++  var stats = fs.statSync(srcPath);
++  if(stats.isDirectory()) {
++     shell.mkdir('-p', destPath);
++     // without the added slash at the end, we will get an extra folder inside destination
++     shell.cp('-r', srcPath + "/" , destPath);
++  }
++  else if(fs.existsSync(srcPath)) {
++    shell.cp(srcPath, destPath);
++  }
++  else {
++    console.log("File does not exist :: " + srcPath);
++    return;
++  }
++
++  var msg = shell.error();
++  if(msg) {
++    console.log("msg" + msg);
++    throw { name: "ShellError", message: msg};
++  }
++}    
++
++function initPaths(project_dir, plugin_dir, plugin_et, variables) {
++
++    unix_projPath = project_dir.split("\\").join("/");
++    configFilePath = path.join(unix_projPath,'config.xml');
++    projectFilename = glob.sync('*.csproj',{nocase:true,cwd:unix_projPath})[0];
++    projPath = path.join(unix_projPath,projectFilename);
++    assets = plugin_et.findall('./asset');
++    platformTag = plugin_et.find('./platform[@name="wp8"]');
++    sourceFiles = platformTag.findall('./source-file');
++    projectChanges = platformTag.findall('./config-file[@target=".csproj"]');
++    hosts = plugin_et.findall('./access');
++}
++
++function install(project_dir, plugin_dir, plugin_et, variables) {
++
++  // move asset files
++  assets && assets.forEach(function (asset) {
++      var srcPath = path.resolve(plugin_dir, asset.attrib['src']);
++      var targetPath = path.resolve(project_dir, assetsDir,  asset.attrib['target']);
++      copyFileSync(srcPath, targetPath);
++  });
++
++  // move source files
++  sourceFiles && sourceFiles.forEach(function (sourceFile) {
++      var srcFilePath = path.resolve(plugin_dir,  sourceFile.attrib['src']);
++      var destDir = path.resolve(project_dir, sourceFile.attrib['target-dir']);
++      var destFilePath = path.resolve(destDir, path.basename(sourceFile.attrib['src']));
++      copyFileSync(srcFilePath, destFilePath);
++  });
++
++  updateConfigXml("install", configFilePath, plugin_et);
++
++  et.register_namespace("csproj", "http://schemas.microsoft.com/developer/msbuild/2003");
++  projectChanges && projectChanges.forEach(function (configNode) {
++
++    var docStr = fs.readFileSync(projPath,"utf8");
++
++    // child is the configNode child that we will insert into csproj
++    var child = configNode.find('*'); 
++    // we use empty text as a default, so we always modify the project file so Visual Studio will notice if open.
++    var newNodeText = "";
++    if(child) {
++
++      newNodeText = new et.ElementTree(child).write({xml_declaration:false});
++      newNodeText = newNodeText.split("&#xA;").join("\n").split("&#xD;").join("\r");
++      newNodeText += "\n\r";
++    }
++
++    // insert text right before closing tag
++    var newDocStr = docStr.replace("</Project>", newNodeText + "</Project>");
++
++    // save it, and get out
++    fs.writeFileSync(projPath, newDocStr);
++  });
++}
++
++function updateConfigXml(action, config_path, plugin_et) {
++
++    var hosts = plugin_et.findall('./access');
++    var platformTag = plugin_et.find('./platform[@name="wp8"]');
++    var configChanges = getConfigChanges(platformTag);   
++    var base_config_path = path.basename(config_path);
++        // add whitelist hosts
++    var root = et.Element("config-file");
++        root.attrib['parent'] = '.';
++      
++    hosts && hosts.forEach( function (tag) {
++      root.append(tag);
++    });
++
++    if (root.len()) {
++      var changeList = configChanges[path.basename(config_path)];
++      // if changeList then add to it, otherwise create it.
++      if(changeList) {
++        changeList.push(root);
++      }
++      else {
++        configChanges[path.basename(config_path)] = [root]
++      }
++    }  
++
++    if (configChanges[path.basename(config_path)]) {
++
++          // edit configuration files
++      var xmlDoc = xml_helpers.parseElementtreeSync(config_path)
++      configChanges[base_config_path].forEach( function (configNode) {
++            var selector = configNode.attrib["parent"],
++                children = configNode.findall('*');
++            if( action == 'install') {
++                if (!xml_helpers.graftXML(xmlDoc, children, selector)) {
++                    throw new Error('failed to add children to ' + selector + ' in ' + config_path);
++                }
++            } else {
++                if (!xml_helpers.pruneXML(xmlDoc, children, selector)) {
++                    throw new Error('failed to remove children from ' + selector + ' in ' + config_path);
++                }
++            }
++      });
++    }
++
++    fs.writeFileSync(config_path, xmlDoc.write({indent: 4}));
++}
++
++function uninstall(project_dir, plugin_dir, plugin_et, variables) {
++
++   assets && assets.forEach(function (asset) {
++      var targetPath = path.resolve(project_dir, assetsDir,  asset.attrib['target']);
++      shell.rm('-rf', targetPath);
++   });
++
++   sourceFiles && sourceFiles.forEach(function (sourceFile) {
++      var destDir = path.resolve(project_dir, sourceFile.attrib['target-dir']);
++      var destFilePath = path.resolve(destDir, path.basename(sourceFile.attrib['src']));
++      shell.rm('-rf', destFilePath);
++   });
++
++   updateConfigXml("uninstall", configFilePath, plugin_et);
++
++   et.register_namespace("csproj", "http://schemas.microsoft.com/developer/msbuild/2003");
++
++   projectChanges && projectChanges.forEach(function (configNode) {
++
++    var docStr = fs.readFileSync(projPath,"utf8");
++
++    // child is the configNode child that we will insert into csproj
++    var child = configNode.find('*'); 
++    if(child) {
++      var newNodeText = new et.ElementTree(child).write({xml_declaration:false});
++          
++      newNodeText = newNodeText.split("&#xA;").join("\n").split("&#xD;").join("\r");
++      
++      // insert text right before closing tag
++      var splitString = docStr.split(newNodeText);
++      console.log("split length = " + splitString.length);
++      var newDocStr = splitString.join("");
++
++      // save it, and get out
++      fs.writeFileSync(projPath, newDocStr);
++    }
++    else {
++      // this just lets Visual Studio know to reload the project if it is open
++      fs.writeFileSync(projPath, docStr);
++    }
++  });
++}
++
++exports.handlePlugin = function (action, project_dir, plugin_dir, plugin_et, variables) {
++    console.log("action = " + action);
++    switch(action) {
++        case 'install' :
++            initPaths(project_dir, plugin_dir, plugin_et, variables);
++            install(project_dir, plugin_dir, plugin_et, variables);
++            break;
++        case 'uninstall' :
++            initPaths(project_dir, plugin_dir, plugin_et, variables);
++            uninstall(project_dir, plugin_dir, plugin_et, variables);
++            break;
++        default :
++          throw 'error unknown action';
++          break;
++    }
++}

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/src/util/plist-helpers.js
----------------------------------------------------------------------
diff --cc src/util/plist-helpers.js
index 0000000,0000000..9a49feb
new file mode 100644
--- /dev/null
+++ b/src/util/plist-helpers.js
@@@ -1,0 -1,0 +1,90 @@@
++/*
++ *
++ * Copyright 2013 Brett Rudd
++ *
++ * 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.
++ *
++*/
++
++// contains PLIST utility functions
++
++var et = require('elementtree'),
++    plist = require('plist');
++ 
++// adds node to doc at selector
++exports.graftPLIST = function (doc, nodes, selector) {
++    var text = et.tostring(nodes, { xml_declaration: false });
++        obj = plist.parseStringSync("<plist>"+text+"</plist>");
++
++    var node = doc[selector];
++    if (node && Array.isArray(node) && Array.isArray(obj))
++        doc[selector] = node.concat(obj);
++    else
++        doc[selector] = obj;
++
++    return true;
++}
++
++// removes node from doc at selector
++exports.prunePLIST = function(doc, nodes, selector) {
++    var text = et.tostring(nodes, { xml_declaration: false }),
++        obj = plist.parseStringSync("<plist>"+text+"</plist>");
++        
++    pruneOBJECT(doc, selector, obj);
++
++    return true;
++}
++
++function pruneOBJECT(doc, selector, fragment) {
++    if (Array.isArray(fragment) && Array.isArray(doc[selector])) {
++        var empty = true;
++        for (i in fragment) {
++            for (j in doc[selector]) {
++                empty = pruneOBJECT(doc[selector], j, fragment[i]) && empty;
++            }  
++        }
++        if (empty) 
++        {
++            delete doc[selector];
++            return true;
++        }
++    }
++    else if (nodeEqual(doc[selector], fragment)) {
++        delete doc[selector];
++        return true;
++    }
++    
++    return false;
++}
++
++function nodeEqual(node1, node2) {
++    if (typeof node1 != typeof node2)
++        return false;
++    else if (typeof node1 == 'string') {
++        node2 = escapeRE(node2).replace(new RegExp("\\$[a-zA-Z0-9-_]+","gm"),"(.*?)");
++        return new RegExp('^' + node2 + '$').test(node1);
++    }
++    else {
++        for (var key in node2) {
++            if (!nodeEqual(node1[key], node2[key])) return false;
++        }
++        return true;
++    }
++}
++
++// escape string for use in regex
++function escapeRE(str) {
++     return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\$&");
++};
++ 

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/src/util/xml-helpers.js
----------------------------------------------------------------------
diff --cc src/util/xml-helpers.js
index 0000000,0e9f0f5..f270132
mode 000000,100644..100644
--- a/src/util/xml-helpers.js
+++ b/src/util/xml-helpers.js
@@@ -1,0 -1,176 +1,176 @@@
+ /*
+  *
+  * 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.
+  *
+ */
+ 
+ /**
+  * contains XML utility functions, some of which are specific to elementtree
+  */
+ 
+ var fs = require('fs')
+   , path = require('path')
+   , et = require('elementtree');
+ 
+ exports = module.exports = {
+     moveProjFile: function(origFile, projPath, callback) {
+         var src = path.resolve(projPath, origFile)
+           , dest = src.replace('.orig', '');
+ 
+         fs.createReadStream(src)
+             .pipe(fs.createWriteStream(dest))
+             .on('close', callback);
+     },
+ 
+     // compare two et.XML nodes, see if they match
+     // compares tagName, text, attributes and children (recursively)
+     equalNodes: function(one, two) {
+         if (one.tag != two.tag) {
+             return false;
+         } else if (one.text.trim() != two.text.trim()) {
+             return false;
+         } else if (one._children.length != two._children.length) {
+             return false;
+         }
+ 
+         var oneAttribKeys = Object.keys(one.attrib),
+             twoAttribKeys = Object.keys(two.attrib),
+             i = 0, attribName;
+ 
+         if (oneAttribKeys.length != twoAttribKeys.length) {
+             return false;
+         }
+ 
+         for (i; i < oneAttribKeys.length; i++) {
+             attribName = oneAttribKeys[i];
+ 
+             if (one.attrib[attribName] != two.attrib[attribName]) {
+                 return false;
+             }
+         }
+ 
+         for (i; i < one._children.length; i++) {
+             if (!exports.equalNodes(one._children[i], two._children[i])) {
+                 return false;
+             }
+         }
+ 
+         return true;
+     },
+ 
+     // adds node to doc at selector
+     graftXML: function (doc, nodes, selector) {
+         var ROOT = /^\/([^\/]*)/
+           , ABSOLUTE = /^\/([^\/]*)\/(.*)/
+           , parent, tagName, subSelector;
+ 
+         // handle absolute selector (which elementtree doesn't like)
+         if (ROOT.test(selector)) {
+             tagName = selector.match(ROOT)[1];
+             if (tagName === doc._root.tag) {
+                 parent = doc._root;
+ 
+                 // could be an absolute path, but not selecting the root
+                 if (ABSOLUTE.test(selector)) {
+                     subSelector = selector.match(ABSOLUTE)[2];
+                     parent = parent.find(subSelector)
+                 }
+             } else {
+                 return false;
+             }
+         } else {
+             parent = doc.find(selector)
+         }
+ 
+         nodes.forEach(function (node) {
+             // check if child is unique first
+             if (uniqueChild(node, parent)) {
+                 parent.append(node);
+             }
+         });
+ 
+         return true;
+     },
+ 
+     // removes node from doc at selector
+     pruneXML: function(doc, nodes, selector) {
+         var ROOT = /^\/([^\/]*)/
+           , ABSOLUTE = /^\/([^\/]*)\/(.*)/
+           , parent, tagName, subSelector;
+ 
+         // handle absolute selector (which elementtree doesn't like)
+         if (ROOT.test(selector)) {
+             tagName = selector.match(ROOT)[1];
+             if (tagName === doc._root.tag) {
+                 parent = doc._root;
+ 
+                 // could be an absolute path, but not selecting the root
+                 if (ABSOLUTE.test(selector)) {
+                     subSelector = selector.match(ABSOLUTE)[2];
+                     parent = parent.find(subSelector)
+                 }
+             } else {
+                 return false;
+             }
+         } else {
+             parent = doc.find(selector)
+         }
+         nodes.forEach(function (node) {
+             var matchingKid = null;
+             if ((matchingKid = findChild(node, parent)) != null) {
+                 // stupid elementtree takes an index argument it doesn't use
+                 // and does not conform to the python lib
+                 parent.remove(0, matchingKid);
+             }
+         });
+ 
+         return true;
+     },
+ 
+     parseElementtreeSync: function (filename) {
 -        var contents = fs.readFileSync(filename, 'utf-8');
++        var contents = fs.readFileSync(filename, 'utf-8').replace("\ufeff", "");;
+         return new et.ElementTree(et.XML(contents));
+     }
+ };
+ 
+ function findChild(node, parent) {
+     var matchingKids = parent.findall(node.tag)
+       , i, j;
+ 
+     for (i = 0, j = matchingKids.length ; i < j ; i++) {
+         if (exports.equalNodes(node, matchingKids[i])) {
+             return matchingKids[i];
+         }
+     }
+     return null;
+ }
+ 
+ function uniqueChild(node, parent) {
+     var matchingKids = parent.findall(node.tag)
+       , i = 0;
+ 
+     if (matchingKids.length == 0) {
+         return true;
+     } else  {
+         for (i; i < matchingKids.length; i++) {
+             if (exports.equalNodes(node, matchingKids[i])) {
+                 return false;
+             }
+         }
+         return true;
+     }
+ }
+ 

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/test/android-one-install.js
----------------------------------------------------------------------
diff --cc test/android-one-install.js
index 8c889f4,0ae8f45..0000000
deleted file mode 100644,100644
--- a/test/android-one-install.js
+++ /dev/null
@@@ -1,169 -1,201 +1,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.
-- *
--*/
--
- // Test installation on Cordova 1.x project
- 
--var fs = require('fs')
--  , path = require('path')
--  , plist = require('plist')
--  , xcode = require('xcode')
--  , osenv = require('osenv')
--  , shell = require('shelljs')
--  , et = require('elementtree')
--  , android = require(path.join(__dirname, '..', 'platforms', 'android'))
- 
-   , test_dir = path.join(osenv.tmpdir(), 'test_plugman')
-   , test_project_dir = path.join(test_dir, 'projects', 'android_one')
-   , test_plugin_dir = path.join(test_dir, 'plugins', 'ChildBrowser')
-   , xml_path     = path.join(test_dir, 'plugins', 'ChildBrowser', 'plugin.xml')
-   , xml_text, plugin_et;
- 
- 
- exports.setUp = function(callback) {
-     shell.mkdir('-p', test_dir);
-     
-     // copy the ios test project to a temp directory
-     shell.cp('-r', path.join(__dirname, 'projects'), test_dir);
- 
-     // copy the ios test plugin to a temp directory
-     shell.cp('-r', path.join(__dirname, 'plugins'), test_dir);
- 
-     // parse the plugin.xml into an elementtree object
-     xml_text   = fs.readFileSync(xml_path, 'utf-8')
-     plugin_et  = new et.ElementTree(et.XML(xml_text));
- 
-     callback();
- }
- 
- exports.tearDown = function(callback) {
-     // remove the temp files (projects and plugins)
-     shell.rm('-rf', test_dir);
-     callback();
- }
- 
- exports['should install webless plugin'] = function (test) {
-     
-     // setting up a DummyPlugin
-     var dummy_plugin_dir = path.join(test_dir, 'plugins', 'WeblessPlugin')
-     var dummy_xml_path = path.join(test_dir, 'plugins', 'WeblessPlugin', 'plugin.xml')
-     dummy_plugin_et  = new et.ElementTree(et.XML(fs.readFileSync(dummy_xml_path, 'utf-8')));
- 
-     android.handlePlugin('install', test_project_dir, dummy_plugin_dir, dummy_plugin_et, { APP_ID: 12345 });
- 
-     test.done();
- }
- 
- exports['should move the js file'] = function (test) {
-     var jsPath = path.join(test_dir, 'projects', 'android_one', 'assets', 'www', 'childbrowser.js');
-     android.handlePlugin('install', test_project_dir, test_plugin_dir, plugin_et, { APP_ID: 12345 });
-     fs.stat(jsPath, function(err, stats) {
-         test.ok(!err);
-         test.ok(stats.isFile());
-         test.done();
-     });
- }
- 
- exports['should move the directory'] = function (test) {
-     android.handlePlugin('install', test_project_dir, test_plugin_dir, plugin_et, { APP_ID: 12345 });
- 
-     var assetPath = path.join(test_dir, 'projects', 'android_one', 'assets', 'www', 'childbrowser');
- 
-     var assets = fs.statSync(assetPath);
- 
-     test.ok(assets.isDirectory());
-     test.ok(fs.statSync(assetPath + '/image.jpg'))
-     test.done();
- }
- 
- exports['should move the src file'] = function (test) {
-     android.handlePlugin('install', test_project_dir, test_plugin_dir, plugin_et, { APP_ID: 12345 });
- 
-     var javaPath = path.join(test_dir, 'projects', 'android_one', 'src', 'com', 'phonegap', 'plugins', 'childBrowser', 'ChildBrowser.java');
-     test.ok(fs.statSync(javaPath));
-     test.done();
- }
- 
- exports['should add ChildBrowser to plugins.xml'] = function (test) {
-     android.handlePlugin('install', test_project_dir, test_plugin_dir, plugin_et, { APP_ID: 12345 });
- 
-     var pluginsXmlPath = path.join(test_dir, 'projects', 'android_one', 'res', 'xml', 'plugins.xml');
-     var pluginsTxt = fs.readFileSync(pluginsXmlPath, 'utf-8'),
-         pluginsDoc = new et.ElementTree(et.XML(pluginsTxt)),
-         expected = 'plugin[@name="ChildBrowser"]' +
-                     '[@value="com.phonegap.plugins.childBrowser.ChildBrowser"]';
- 
-     test.ok(pluginsDoc.find(expected));
-     test.done();
- }
- 
- exports['should add ChildBrowser to AndroidManifest.xml'] = function (test) {
-     android.handlePlugin('install', test_project_dir, test_plugin_dir, plugin_et, { APP_ID: 12345 });
- 
-     var manifestPath = path.join(test_dir, 'projects', 'android_one', 'AndroidManifest.xml');
-     var manifestTxt = fs.readFileSync(manifestPath, 'utf-8'),
-         manifestDoc = new et.ElementTree(et.XML(manifestTxt)),
-         activities = manifestDoc.findall('application/activity'), i;
- 
-     var found = false;
-     for (i=0; i<activities.length; i++) {
-         if ( activities[i].attrib['android:name'] === 'com.phonegap.plugins.childBrowser.ChildBrowser' ) {
-             found = true;
-             break;
-         }
-     }
-     test.ok(found);
-     test.done();
- }
- 
- exports['should add whitelist hosts'] = function (test) {
- 	android.handlePlugin('install', test_project_dir, test_plugin_dir, plugin_et, { APP_ID: 12345 });
- 
-     var pluginsXmlPath = path.join(test_dir, 'projects', 'android_one', 'res', 'xml', 'plugins.xml');
-     var pluginsTxt = fs.readFileSync(pluginsXmlPath, 'utf-8'),
-         pluginsDoc = new et.ElementTree(et.XML(pluginsTxt));
- 
-     test.equal(pluginsDoc.findall("access").length, 2, "/access");
- 	test.equal(pluginsDoc.findall("access")[0].attrib["origin"], "build.phonegap.com")
-     test.equal(pluginsDoc.findall("access")[1].attrib["origin"], "s3.amazonaws.com")
-     test.done();
- }
- 
- exports['should search/replace plugin.xml'] = function (test) {
- 	android.handlePlugin('install', test_project_dir, test_plugin_dir, plugin_et, { APP_ID: 12345 });
- 
-     var pluginsXmlPath = path.join(test_dir, 'projects', 'android_one', 'res', 'xml', 'plugins.xml');
-     var pluginsTxt = fs.readFileSync(pluginsXmlPath, 'utf-8'),
-         pluginsDoc = new et.ElementTree(et.XML(pluginsTxt));
- 
-     test.equal(pluginsDoc.findall("access").length, 2, "/access");
- 	test.equal(pluginsDoc.findall("access")[0].attrib["origin"], "build.phonegap.com")
-     test.equal(pluginsDoc.findall("access")[1].attrib["origin"], "s3.amazonaws.com")
-     test.done();
- }
- 
- exports['should search/replace manifest.xml files'] = function (test) {
- 	android.handlePlugin('install', test_project_dir, test_plugin_dir, plugin_et, { APP_ID: 12345 });
- 
-     var manifestXmlPath = path.join(test_dir, 'projects', 'android_one', 'AndroidManifest.xml');
-     var manifestTxt = fs.readFileSync(manifestXmlPath, 'utf-8'),
-         manifestDoc = new et.ElementTree(et.XML(manifestTxt));
- 
- 	test.equal(manifestDoc.findall("appid")[0].attrib["value"], "12345")
-     test.done();
- }
 -  , plugman = require('../plugman')
 -  , plugin_loader = require('../util/plugin_loader')
 -  , test_dir = path.join(osenv.tmpdir(), 'test_plugman')
 -  , test_project_dir = path.join(test_dir, 'projects', 'android_one')
 -  , test_plugin_dir = path.join(test_dir, 'plugins', 'ChildBrowser')
 -  , xml_path     = path.join(test_dir, 'plugins', 'ChildBrowser', 'plugin.xml')
 -  , plugins_dir = path.join(test_dir, 'plugins')
 -  , silent = require('../util/test-helpers').suppressOutput
 -  , xml_text, plugin_et;
 -
 -describe('Installation on Cordova-Android 1.x projects', function() {
 -    beforeEach(function() {
 -        shell.mkdir('-p', test_dir);
 -        
 -        // copy the ios test project to a temp directory
 -        shell.cp('-r', path.join(__dirname, 'projects'), test_dir);
 -
 -        // copy the ios test plugin to a temp directory
 -        shell.cp('-r', path.join(__dirname, 'plugins'), test_dir);
 -
 -        // parse the plugin.xml into an elementtree object
 -        xml_text   = fs.readFileSync(xml_path, 'utf-8')
 -        plugin_et  = new et.ElementTree(et.XML(xml_text));
 -    });
 -    afterEach(function() {
 -        // remove the temp files (projects and plugins)
 -        shell.rm('-rf', test_dir);
 -    });
 -
 -    it('should install webless plugin\'s native code', function () {
 -        // setting up a DummyPlugin
 -        silent(function() {
 -            plugman.handlePlugin('install', 'android', test_project_dir, 'WeblessPlugin', plugins_dir);
 -        });
 -        expect(fs.existsSync(path.join(test_project_dir, 'src', 'com', 'phonegap', 'plugins', 'weblessplugin', 'WeblessPlugin.java'))).toBe(true);
 -    });
 -
 -    it('should copy the js file', function () {
 -        var pluginsPath = path.join(test_dir, 'plugins');
 -        var wwwPath = path.join(test_project_dir, 'assets', 'www');
 -        var jsPath = path.join(wwwPath, 'plugins', 'com.phonegap.plugins.childbrowser', 'www', 'childbrowser.js');
 -
 -        silent(function() {
 -            plugman.handlePlugin('install', 'android', test_project_dir, 'ChildBrowser', plugins_dir);
 -        });
 -
 -        expect(fs.existsSync(jsPath)).toBe(true);
 -    });
 -
 -    it('should move asset files', function() {
 -        var wwwPath = path.join(test_project_dir, 'assets', 'www');
 -
 -        silent(function() {
 -            plugman.handlePlugin('install', 'android', test_project_dir, 'ChildBrowser', plugins_dir);
 -        });
 -
 -        var assetPath = path.join(wwwPath, 'childbrowser_file.html');
 -
 -        expect(fs.existsSync(assetPath)).toBe(true);
 -    });
 -
 -    it('should move asset directories', function () {
 -        var wwwPath = path.join(test_project_dir, 'assets', 'www');
 -
 -        silent(function() {
 -            plugman.handlePlugin('install', 'android', test_project_dir, 'ChildBrowser', plugins_dir);
 -        });
 -
 -        var assetPath = path.join(wwwPath, 'childbrowser');
 -        var assets = fs.statSync(assetPath);
 -
 -        expect(assets.isDirectory()).toBe(true);
 -        expect(fs.existsSync(path.join(assetPath, 'image.jpg'))).toBe(true);
 -    });
 -
 -    it('should add entries to the cordova_plugins.json file', function() {
 -        var wwwPath = path.join(test_project_dir, 'assets', 'www');
 -
 -        silent(function() {
 -            plugman.handlePlugin('install', 'android', test_project_dir, 'ChildBrowser', plugins_dir);
 -        });
 -
 -        var jsonPath = path.join(wwwPath, 'cordova_plugins.json');
 -        var content = JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));
 -
 -    });
 -
 -    exports['should move the src file'] = function (test) {
 -        var wwwPath = path.join(test_dir, 'projects', 'android_one', 'assets', 'www');
 -
 -        silent(function() {
 -            plugman.handlePlugin('install', 'android', test_project_dir, 'ChildBrowser', plugins_dir);
 -        });
 -
 -        var javaPath = path.join(test_dir, 'projects', 'android_one', 'src', 'com', 'phonegap', 'plugins', 'childBrowser', 'ChildBrowser.java');
 -
 -        test.ok(fs.statSync(javaPath));
 -        test.done();
 -    }
 -
 -    exports['should add ChildBrowser to plugins.xml'] = function (test) {
 -        silent(function() {
 -            plugman.handlePlugin('install', 'android', test_project_dir, 'ChildBrowser', plugins_dir);
 -        });
 -
 -        var pluginsXmlPath = path.join(test_dir, 'projects', 'android_one', 'res', 'xml', 'plugins.xml');
 -        var pluginsTxt = fs.readFileSync(pluginsXmlPath, 'utf-8'),
 -            pluginsDoc = new et.ElementTree(et.XML(pluginsTxt)),
 -            expected = 'plugin[@name="ChildBrowser"]' +
 -                        '[@value="com.phonegap.plugins.childBrowser.ChildBrowser"]';
 -
 -        test.ok(pluginsDoc.find(expected));
 -        test.done();
 -    }
 -
 -    exports['should add ChildBrowser to AndroidManifest.xml'] = function (test) {
 -        silent(function() {
 -            plugman.handlePlugin('install', 'android', test_project_dir, 'ChildBrowser', plugins_dir);
 -        });
 -
 -        var manifestPath = path.join(test_dir, 'projects', 'android_one', 'AndroidManifest.xml');
 -        var manifestTxt = fs.readFileSync(manifestPath, 'utf-8'),
 -            manifestDoc = new et.ElementTree(et.XML(manifestTxt)),
 -            activities = manifestDoc.findall('application/activity'), i;
 -
 -        var found = false;
 -        for (i=0; i<activities.length; i++) {
 -            if ( activities[i].attrib['android:name'] === 'com.phonegap.plugins.childBrowser.ChildBrowser' ) {
 -                found = true;
 -                break;
 -            }
 -        }
 -        test.ok(found);
 -        test.done();
 -    }
 -
 -    exports['should add whitelist hosts'] = function (test) {
 -        android.handlePlugin('install', test_project_dir, test_plugin_dir, plugin_et, { APP_ID: 12345 });
 -
 -        var pluginsXmlPath = path.join(test_dir, 'projects', 'android_one', 'res', 'xml', 'plugins.xml');
 -        var pluginsTxt = fs.readFileSync(pluginsXmlPath, 'utf-8'),
 -            pluginsDoc = new et.ElementTree(et.XML(pluginsTxt));
 -
 -        test.equal(pluginsDoc.findall("access").length, 2, "/access");
 -        test.equal(pluginsDoc.findall("access")[0].attrib["origin"], "build.phonegap.com")
 -        test.equal(pluginsDoc.findall("access")[1].attrib["origin"], "12345.s3.amazonaws.com")
 -        test.done();
 -    }
 -
 -    exports['should search/replace plugin.xml'] = function (test) {
 -        android.handlePlugin('install', test_project_dir, test_plugin_dir, plugin_et, { APP_ID: 12345 });
 -
 -        var pluginsXmlPath = path.join(test_dir, 'projects', 'android_one', 'res', 'xml', 'plugins.xml');
 -        var pluginsTxt = fs.readFileSync(pluginsXmlPath, 'utf-8'),
 -            pluginsDoc = new et.ElementTree(et.XML(pluginsTxt));
 -
 -        test.equal(pluginsDoc.findall("access").length, 2, "/access");
 -        test.equal(pluginsDoc.findall("access")[0].attrib["origin"], "build.phonegap.com")
 -        test.equal(pluginsDoc.findall("access")[1].attrib["origin"], "12345.s3.amazonaws.com")
 -        test.done();
 -    }
 -
 -    exports['should search/replace manifest.xml files'] = function (test) {
 -        android.handlePlugin('install', test_project_dir, test_plugin_dir, plugin_et, { APP_ID: 12345 });
 -
 -        var manifestXmlPath = path.join(test_dir, 'projects', 'android_one', 'AndroidManifest.xml');
 -        var manifestTxt = fs.readFileSync(manifestXmlPath, 'utf-8'),
 -            manifestDoc = new et.ElementTree(et.XML(manifestTxt));
 -
 -        test.equal(manifestDoc.findall("appid")[0].attrib["value"], "12345")
 -        test.done();
 -    }
 -});
 -

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/test/android-two-install.js
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/test/ios-config-xml-uninstall.js
----------------------------------------------------------------------
diff --cc test/ios-config-xml-uninstall.js
index 6b2674e,da8d061..0ba5813
--- a/test/ios-config-xml-uninstall.js
+++ b/test/ios-config-xml-uninstall.js
@@@ -175,32 -152,14 +152,34 @@@ exports['should edit config.xml'] = fun
      test.done();
  }
  
 +exports['should remove custom config-file elements'] = function (test) {
 +    // setting up WebNotification (with config.xml) 
 +    var dummy_plugin_dir = path.join(test_dir, 'plugins', 'ChildBrowser')
 +    var dummy_xml_path = path.join(test_dir, 'plugins', 'ChildBrowser', 'plugin.xml')
 +    
 +    // overriding some params
 +    var dummy_plugin_et  = new et.ElementTree(et.XML(fs.readFileSync(dummy_xml_path, 'utf-8')));
 +
 +    // run the platform-specific function
 +    ios.handlePlugin('install', test_project_dir, dummy_plugin_dir, dummy_plugin_et, { APP_ID: '1234'  });
 +    ios.handlePlugin('uninstall', test_project_dir, dummy_plugin_dir, dummy_plugin_et);
 +    
 +    var configPath = path.join(test_project_dir, 'SampleApp', 'SampleApp-Info.plist');
 +    var configPList = plist.parseFileSync(configPath);
 +
 +    test.equal(configPList['AppId'], null);
 +    test.equal(configPList['CFBundleURLTypes'], null);
 +    test.done();
 +}
 +
  exports['should edit the pbxproj file'] = function (test) {
      // run the platform-specific function
-     ios.handlePlugin('install', test_project_dir, test_plugin_dir, plugin_et);
-     ios.handlePlugin('uninstall', test_project_dir, test_plugin_dir, plugin_et);
+     silent(function() {
+         plugman.handlePlugin('install', 'ios', test_project_dir, 'ChildBrowser', plugins_dir);
+         plugman.handlePlugin('uninstall', 'ios', test_project_dir, 'ChildBrowser', plugins_dir);
+     });
  
-     var projPath = test_project_dir + '/SampleApp.xcodeproj/project.pbxproj';
+     var projPath = path.join(test_project_dir, 'SampleApp.xcodeproj', 'project.pbxproj');
  
      obj = xcode.project(projPath).parseSync();
      var fileRefSection = obj.hash.project.objects['PBXFileReference'],

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/test/ios-plist-install.js
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/f677a153/test/plugins/ChildBrowser/plugin.xml
----------------------------------------------------------------------
diff --cc test/plugins/ChildBrowser/plugin.xml
index 946f3a8,9c87b06..0000000
deleted file mode 100644,100644
--- a/test/plugins/ChildBrowser/plugin.xml
+++ /dev/null
@@@ -1,138 -1,95 +1,0 @@@
--<?xml version="1.0" encoding="UTF-8"?>
--<!--
--
-- 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.
--
---->
--
--<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
--    xmlns:android="http://schemas.android.com/apk/res/android"
--    id="com.phonegap.plugins.childbrowser"
--    version="0.6.0">
--
--    <name>Child Browser</name>
--
-     <asset src="www/childbrowser.js" target="childbrowser.js" />
--    <asset src="www/childbrowser" target="childbrowser" />
- 
-     <access origin="build.phonegap.com" />
-     <access origin="s3.amazonaws.com" />
- 
-     <!-- android -->
-     <platform name="android">
-         <config-file target="AndroidManifest.xml" parent="/manifest/application">
-             <activity android:name="com.phonegap.plugins.childBrowser.ChildBrowser"
-                       android:label="@string/app_name">
-                 <intent-filter>
-                 </intent-filter>
-             </activity>
-         </config-file>
- 
-         <!-- CDV < 2.0 -->
-         <config-file target="res/xml/plugins.xml" parent="/plugins">
-             <plugin name="ChildBrowser"
-                 value="com.phonegap.plugins.childBrowser.ChildBrowser"/>
-         </config-file>
- 
-         <!-- CDV 2.0+ (for now) -->
-         <config-file target="res/xml/config.xml" parent="/cordova/plugins">
-             <plugin name="ChildBrowser"
-                 value="com.phonegap.plugins.childBrowser.ChildBrowser"/>
-         </config-file>
- 
-         <source-file src="ChildBrowser.java"
-                 target-dir="src/com/phonegap/plugins/childBrowser" />
-         <info>
-           Please make sure you read this because it is very important to complete the installation of your plugin
-         </info>
-     </platform>
- 
-     <!-- ios -->
-     <platform name="ios">
-         <plugins-plist key="com.phonegap.plugins.childbrowser"
-             string="ChildBrowserCommand" />
- 
-         <config-file target="config.xml" parent="/widget/plugins">
-             <plugin name="ChildBrowser"
-                 value="ChildBrowserCommand" />
-         </config-file>
- 
-         <config-file target="*-Info.plist" parent="AppId">
-             <string>$APP_ID</string>
-         </config-file>
-         
-         <config-file target="*-Info.plist" parent="CFBundleURLTypes">
-             <array>
-               <dict>
-                 <key>PackageName</key>
-                 <string>$PACKAGE_NAME</string>
-               </dict>
-             </array>
-         </config-file>
- 
-         <resource-file src="ChildBrowser.bundle" />
-         <resource-file src="ChildBrowserViewController.xib" />
- 
-         <header-file src="ChildBrowserCommand.h" />
-         <header-file src="ChildBrowserViewController.h" />
-         <header-file src="preserveDirs/PreserveDirsTest.h" preserve-dirs="true" />
-         <header-file src="TargetDirTest.h" target-dir="targetDir"/>
- 
-         <source-file src="ChildBrowserCommand.m" />
-         <source-file src="ChildBrowserViewController.m" />
-         <source-file src="preserveDirs/PreserveDirsTest.m" preserve-dirs="true" />
-         <header-file src="TargetDirTest.m" target-dir="targetDir"/>
- 
-         <!-- framework for testing (not actual dependency of ChildBrowser -->
-         <framework src="libsqlite3.dylib" />
-         <framework src="social.framework" weak="true" />
-         <framework src="music.framework" weak="rabbit" />
-     </platform>
- 
-     <!-- wp7 -->
-     <platform name="wp7">
-         <resource-file src="src\wp7\Images\appbar.back.rest.png" />
-         <config-file target="config.xml" parent="/widget/plugins">
-             <plugin name="ChildBrowser"
-                 value="ChildBrowser"/>
-         </config-file>
- 
-         <source-file src="src\wp7\ChildBrowserCommand.cs"
-                      target-dir="Plugins\" />
- 
-         <!-- modify the project file to include the added files -->
-         <config-file target=".csproj" parent=".">  
-         </config-file> 
- 
-     </platform>
- 
-     <!-- wp8 -->
-     <platform name="wp8">
-         <resource-file src="src\wp7\Images\appbar.back.rest.png" />
-         <config-file target="config.xml" parent="/widget/plugins">
-             <plugin name="ChildBrowser"
-                 value="ChildBrowser"/>
-         </config-file>
- 
-         <source-file src="src\wp7\ChildBrowserCommand.cs"
-                      target-dir="Plugins\" />
- 
-         <!-- modify the project file to include the added files -->
-         <config-file target=".csproj" parent=".">  
-         </config-file> 
- 
-     </platform>
- </plugin>
 -    <asset src="www/childbrowser_file.html" target="childbrowser_file.html" />
 -
 -    <js-module src="www/childbrowser.js" name="ChildBrowser">
 -        <clobbers target="childbrowser" />
 -    </js-module>
 -
 -    <access origin="build.phonegap.com" />
 -    <access origin="$APP_ID.s3.amazonaws.com" />
 -
 -    <!-- android -->
 -    <platform name="android">
 -        <config-file target="AndroidManifest.xml" parent="/manifest/application">
 -            <activity android:name="com.phonegap.plugins.childBrowser.ChildBrowser"
 -                      android:label="@string/app_name">
 -                <intent-filter>
 -                </intent-filter>
 -            </activity>
 -        </config-file>
 -
 -        <!-- CDV < 2.0 -->
 -        <config-file target="res/xml/plugins.xml" parent="/plugins">
 -            <plugin name="ChildBrowser"
 -                value="com.phonegap.plugins.childBrowser.ChildBrowser"/>
 -        </config-file>
 -
 -        <!-- CDV 2.0+ (for now) -->
 -        <config-file target="res/xml/config.xml" parent="/cordova/plugins">
 -            <plugin name="ChildBrowser"
 -                value="com.phonegap.plugins.childBrowser.ChildBrowser"/>
 -        </config-file>
 -
 -        <source-file src="src/android/ChildBrowser.java"
 -                target-dir="src/com/phonegap/plugins/childBrowser" />
 -        <info>
 -          Please make sure you read this because it is very important to complete the installation of your plugin
 -        </info>
 -    </platform>
 -
 -    <!-- ios -->
 -    <platform name="ios">
 -        <plugins-plist key="com.phonegap.plugins.childbrowser"
 -            string="ChildBrowserCommand" />
 -
 -        <config-file target="config.xml" parent="/widget/plugins">
 -            <plugin name="ChildBrowser"
 -                value="ChildBrowserCommand" />
 -        </config-file>
 -
 -        <resource-file src="src/ios/ChildBrowser.bundle" />
 -        <resource-file src="src/ios/ChildBrowserViewController.xib" />
 -
 -        <header-file src="src/ios/ChildBrowserCommand.h" />
 -        <header-file src="src/ios/ChildBrowserViewController.h" />
 -        <header-file src="src/ios/preserveDirs/PreserveDirsTest.h" preserve-dirs="true" />
 -        <header-file src="src/ios/TargetDirTest.h" target-dir="targetDir"/>
 -
 -        <source-file src="src/ios/ChildBrowserCommand.m" />
 -        <source-file src="src/ios/ChildBrowserViewController.m" />
 -        <source-file src="src/ios/preserveDirs/PreserveDirsTest.m" preserve-dirs="true" />
 -        <header-file src="src/ios/TargetDirTest.m" target-dir="targetDir"/>
 -
 -        <!-- framework for testing (not actual dependency of ChildBrowser -->
 -        <framework src="libsqlite3.dylib" />
 -        <framework src="social.framework" weak="true" />
 -        <framework src="music.framework" weak="rabbit" />
 -    </platform>
 -</plugin>