You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2013/07/10 20:03:21 UTC

[1/6] git commit: [CB-4077] Separate the actions of removing a plugin from a platform and removing the plugin entirely

Updated Branches:
  refs/heads/master 4646aa41c -> ba9d4b0cb


[CB-4077] Separate the actions of removing a plugin from a platform and removing the plugin entirely


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

Branch: refs/heads/master
Commit: 21a102c360f2ec1f5501e7f0c1316e98ffde885a
Parents: 4646aa4
Author: Ian Clelland <ic...@chromium.org>
Authored: Fri Jul 5 10:49:04 2013 -0400
Committer: Fil Maj <ma...@gmail.com>
Committed: Wed Jul 10 11:01:27 2013 -0700

----------------------------------------------------------------------
 src/uninstall.js | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/21a102c3/src/uninstall.js
----------------------------------------------------------------------
diff --git a/src/uninstall.js b/src/uninstall.js
index dbe0fae..8728711 100644
--- a/src/uninstall.js
+++ b/src/uninstall.js
@@ -11,7 +11,17 @@ var path = require('path'),
     platform_modules = require('./platforms');
 
 // possible options: cli_variables, www_dir
-module.exports = function uninstallPlugin(platform, project_dir, id, plugins_dir, options, callback) {
+module.exports = function(platform, project_dir, id, plugins_dir, options, callback) {
+    module.exports.uninstallPlatform(platform, project_dir, id, plugins_dir, options, function(err) {
+        if (err) {
+            if (callback) return callback(err);
+            else throw err;
+        }
+        module.exports.uninstallPlugin(id, plugins_dir, options, callback);
+    });
+}
+
+module.exports.uninstallPlatform = function(platform, project_dir, id, plugins_dir, options, callback) {
     if (!platform_modules[platform]) {
         var err = new Error(platform + " not supported.");
         if (callback) return callback(err);
@@ -32,11 +42,21 @@ module.exports = function uninstallPlugin(platform, project_dir, id, plugins_dir
     runUninstall(current_stack, platform, project_dir, plugin_dir, plugins_dir, options, callback);
 };
 
+module.exports.uninstallPlugin = function(id, plugins_dir, callback) {
+    var plugin_dir = path.join(plugins_dir, id);
+    var xml_path     = path.join(plugin_dir, 'plugin.xml')
+      , plugin_et    = xml_helpers.parseElementtreeSync(xml_path);
+    var plugin_id    = plugin_et._root.attrib['id'];
+    // axe the directory
+    shell.rm('-rf', plugin_dir);
+    require('../plugman').emit('log', plugin_id + ' uninstalled.');
+    if (callback) callback();
+};
+
 // possible options: cli_variables, www_dir, is_top_level
 function runUninstall(actions, platform, project_dir, plugin_dir, plugins_dir, options, callback) {
     var xml_path     = path.join(plugin_dir, 'plugin.xml')
       , plugin_et    = xml_helpers.parseElementtreeSync(xml_path);
-    var name         = plugin_et.findall('name').text;
     var plugin_id    = plugin_et._root.attrib['id'];
     options = options || {};
 
@@ -131,9 +151,6 @@ function handleUninstall(actions, platform, plugin_id, plugin_et, project_dir, w
             config_changes.add_uninstalled_plugin_to_prepare_queue(plugins_dir, path.basename(plugin_dir), platform, is_top_level);
             // call prepare after a successful uninstall
             require('./../plugman').prepare(project_dir, platform, plugins_dir);
-            // axe the directory
-            shell.rm('-rf', plugin_dir);
-            require('../plugman').emit('log', plugin_id + ' uninstalled.');
             if (callback) callback();
         }
     });


[5/6] git commit: Work for [CB-4077]: uninstallation should look at platform json file for determining which plugins to iterate over. fetching multiple plugins from git should not collide in temp dir.

Posted by fi...@apache.org.
Work for [CB-4077]: uninstallation should look at platform json file for determining which plugins to iterate over. fetching multiple plugins from git should not collide in temp dir.


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

Branch: refs/heads/master
Commit: 611ec4db2dbe2a2918a1416e2cfd2787fa4335ee
Parents: 859e275
Author: Fil Maj <ma...@gmail.com>
Authored: Tue Jul 9 14:10:48 2013 -0700
Committer: Fil Maj <ma...@gmail.com>
Committed: Wed Jul 10 11:01:28 2013 -0700

----------------------------------------------------------------------
 spec/prepare.spec.js | 7 +++----
 src/install.js       | 6 ++----
 src/prepare.js       | 8 +++-----
 src/util/plugins.js  | 6 +++---
 4 files changed, 11 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/611ec4db/spec/prepare.spec.js
----------------------------------------------------------------------
diff --git a/spec/prepare.spec.js b/spec/prepare.spec.js
index 675444a..5bf51ff 100644
--- a/spec/prepare.spec.js
+++ b/spec/prepare.spec.js
@@ -15,12 +15,12 @@ var json = path.join(temp, 'assets', 'www', 'cordova_plugins.json');
 var js = path.join(temp, 'assets', 'www', 'cordova_plugins.js');
 
 describe('prepare', function() {
-    var proc, readdir, write, stat, read, parseET, mkdir;
+    var proc, platform_json, write, stat, read, parseET, mkdir;
     var root, findall, find;
     beforeEach(function() {
         mkdir = spyOn(shell, 'mkdir');
         proc = spyOn(config_changes, 'process');
-        readdir = spyOn(fs, 'readdirSync').andReturn([]);
+        platform_json = spyOn(config_changes, 'get_platform_json').andReturn({installed_plugins:{},dependent_plugins:{}});
         write = spyOn(fs, 'writeFileSync');
         stat = spyOn(fs, 'statSync').andReturn({isDirectory:function() { return true; }});
         root = jasmine.createSpy('ElementTree getroot').andReturn({
@@ -46,11 +46,10 @@ describe('prepare', function() {
     });
     describe('handling of js-modules', function() {
         var read, child_one;
-        var fake_plugins = ['plugin_one', 'plugin_two'];
         beforeEach(function() {
             child_one = jasmine.createSpy('getchildren').andReturn([]);
             read = spyOn(fs, 'readFileSync').andReturn('JAVASCRIPT!');
-            readdir.andReturn(fake_plugins);
+            platform_json.andReturn({installed_plugins:{plugin_one:'',plugin_two:''},dependent_plugins:{}});
             findall.andReturn([
                 {attrib:{src:'somedir', name:'NAME'}, getchildren:child_one},
                 {attrib:{src:'someotherdir', name:'NAME'}, getchildren:child_one}

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/611ec4db/src/install.js
----------------------------------------------------------------------
diff --git a/src/install.js b/src/install.js
index 2c2c025..3868ccf 100644
--- a/src/install.js
+++ b/src/install.js
@@ -184,14 +184,12 @@ function runInstall(actions, platform, project_dir, plugin_dir, plugins_dir, opt
                     var result = shell.exec('git rev-parse --show-toplevel', { silent:true, async:false});
                     if (result.code === 128) {
                         var err = new Error('Error: Plugin ' + plugin_id + ' is not in git repository. All plugins must be in a git repository.');
-                        if (callback) callback(err);
+                        if (callback) return callback(err);
                         else throw err;
-                        return;
                     } else if(result.code > 0) {
                         var err = new Error('Error trying to locate git repository for plugin.');
-                        if (callback) callback(err);
+                        if (callback) return callback(err);
                         else throw err;
-                        return;
                     }
 
                     var dep_url = path.join(result.output.trim(), dep_subdir);

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/611ec4db/src/prepare.js
----------------------------------------------------------------------
diff --git a/src/prepare.js b/src/prepare.js
index 4904975..f898b84 100644
--- a/src/prepare.js
+++ b/src/prepare.js
@@ -46,14 +46,12 @@ module.exports = function handlePrepare(project_dir, platform, plugins_dir) {
     config_changes.process(plugins_dir, project_dir, platform);
 
     var wwwDir = platform_modules[platform].www_dir(project_dir);
-    // TODO: perhaps this should look at platform json files to determine which plugins to prepare?
-    var plugins = fs.readdirSync(plugins_dir).filter(function(p) {
-        return p != '.svn' && p != 'CVS';
-    });
+    var platform_json = config_changes.get_platform_json(plugins_dir, platform);
+    var plugins = Object.keys(platform_json.installed_plugins).concat(Object.keys(platform_json.dependent_plugins));
 
     // This array holds all the metadata for each module and ends up in cordova_plugins.json
     var moduleObjects = [];
-    require('../plugman').emit('log', 'Iterating over installed plugins...');
+    require('../plugman').emit('log', 'Iterating over installed plugins:', plugins);
 
     plugins && plugins.forEach(function(plugin) {
         var pluginDir = path.join(plugins_dir, plugin);

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/611ec4db/src/util/plugins.js
----------------------------------------------------------------------
diff --git a/src/util/plugins.js b/src/util/plugins.js
index 90b24f7..7153926 100644
--- a/src/util/plugins.js
+++ b/src/util/plugins.js
@@ -23,8 +23,7 @@ var http = require('http'),
     fs = require('fs'),
     util = require('util'),
     shell = require('shelljs'),
-    xml_helpers = require('./xml-helpers'),
-    tmp_dir = path.join(os.tmpdir(), 'plugman-tmp');
+    xml_helpers = require('./xml-helpers');
 
 module.exports = {
     searchAndReplace:require('./search-and-replace'),
@@ -35,6 +34,7 @@ module.exports = {
             if (callback) return callback(err);
             else throw err;
         }
+        var tmp_dir = path.join(os.tmpdir(), 'plugman-tmp' +(new Date).valueOf());
 
         shell.rm('-rf', tmp_dir);
 
@@ -69,8 +69,8 @@ module.exports = {
 
                 // TODO: what if a plugin dependended on different subdirectories of the same plugin? this would fail.
                 // should probably copy over entire plugin git repo contents into plugins_dir and handle subdir seperately during install.
-                require('../../plugman').emit('log', 'Copying fetched plugin over "' + plugin_dir + '"...');
                 var plugin_dir = path.join(plugins_dir, plugin_id);
+                require('../../plugman').emit('log', 'Copying fetched plugin over "' + plugin_dir + '"...');
                 shell.cp('-R', path.join(tmp_dir, '*'), plugin_dir);
 
                 require('../../plugman').emit('log', 'Plugin "' + plugin_id + '" fetched.');


[2/6] git commit: Added a spec for uninstalling dependencies.

Posted by fi...@apache.org.
Added a spec for uninstalling dependencies.


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

Branch: refs/heads/master
Commit: 4e90181a361202d0f07c731f5e428dc94e03f2d4
Parents: db8b3d4
Author: Fil Maj <ma...@gmail.com>
Authored: Tue Jul 9 20:59:08 2013 -0700
Committer: Fil Maj <ma...@gmail.com>
Committed: Wed Jul 10 11:01:28 2013 -0700

----------------------------------------------------------------------
 spec/uninstall.spec.js | 50 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 48 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/4e90181a/spec/uninstall.spec.js
----------------------------------------------------------------------
diff --git a/spec/uninstall.spec.js b/spec/uninstall.spec.js
index 738e941..3c6a73e 100644
--- a/spec/uninstall.spec.js
+++ b/spec/uninstall.spec.js
@@ -1,6 +1,7 @@
 var uninstall = require('../src/uninstall'),
     actions = require('../src/util/action-stack'),
     config_changes = require('../src/util/config-changes'),
+    dependencies = require('../src/util/dependencies'),
     xml_helpers = require('../src/util/xml-helpers'),
     plugman = require('../plugman'),
     fs      = require('fs'),
@@ -17,6 +18,7 @@ var uninstall = require('../src/uninstall'),
 
 describe('uninstallPlatform', function() {
     var exists, get_json, chmod, exec, proc, add_to_queue, prepare, actions_push, c_a, rm;
+    var gen_deps, get_chain;
     beforeEach(function() {
         proc = spyOn(actions.prototype, 'process').andCallFake(function(platform, proj, cb) {
             cb();
@@ -33,6 +35,13 @@ describe('uninstallPlatform', function() {
         });
         rm = spyOn(shell, 'rm');
         add_to_queue = spyOn(config_changes, 'add_uninstalled_plugin_to_prepare_queue');
+        dependents = jasmine.createSpy('getChain').andReturn([]),
+        gen_deps = spyOn(dependencies, 'generate_dependency_info').andReturn({
+            graph:{
+                getChain:dependents
+            },
+            top_level_plugins:[]
+        });
     });
     describe('success', function() {
         it('should call prepare after a successful uninstall', function() {
@@ -51,9 +60,46 @@ describe('uninstallPlatform', function() {
         });
 
         describe('with dependencies', function() {
-            it('should uninstall "dangling" dependencies', function() {
+            var uninstall_spy, parseET;
+            beforeEach(function() {
+                uninstall_spy = spyOn(uninstall, 'uninstallPlugin').andCallFake(function(id, dir, cb) {
+                    cb();
+                });
+                parseET = spyOn(xml_helpers, 'parseElementtreeSync').andReturn({
+                    _root:{
+                        attrib:{}
+                    },
+                    find:function() { return null },
+                    findall:function() { return [] }
+                });
             });
-            it('should remove dangling dependent directories', function() {
+            it('should uninstall "dangling" dependencies', function() {
+                // TODO: this is a terrible way to do conditional mocking, i am sorry.
+                // if you have a better idea on how to mock out this recursive function, plz patch it
+                var counter = 0;
+                gen_deps.andCallFake(function() {
+                    var obj;
+                    if (counter === 0) {
+                        counter++;
+                        obj = {
+                            graph:{
+                                getChain:function() { return ['one','two'] }
+                            },
+                            top_level_plugins:[]
+                        };
+                    } else {
+                        obj = {
+                            graph:{
+                                getChain:dependents
+                            },
+                            top_level_plugins:[]
+                        };
+                    }
+                    return obj;
+                });
+                uninstall.uninstallPlatform('android', temp, dummyplugin, plugins_dir, {});
+                expect(uninstall_spy).toHaveBeenCalledWith('one', plugins_dir, jasmine.any(Function));
+                expect(uninstall_spy).toHaveBeenCalledWith('two', plugins_dir, jasmine.any(Function));
             });
             it('should not uninstall any dependencies that are relied on by other plugins');
         });


[3/6] git commit: Further [CB-4077] work: remove plugin directory for dependent plugins during uninstallation.

Posted by fi...@apache.org.
Further [CB-4077] work: remove plugin directory for dependent plugins during uninstallation.


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

Branch: refs/heads/master
Commit: db8b3d49ccacd9394d3eec6a9c7fa746f15cfd4c
Parents: 611ec4d
Author: Fil Maj <ma...@gmail.com>
Authored: Tue Jul 9 14:27:41 2013 -0700
Committer: Fil Maj <ma...@gmail.com>
Committed: Wed Jul 10 11:01:28 2013 -0700

----------------------------------------------------------------------
 spec/uninstall.spec.js | 5 ++++-
 src/uninstall.js       | 8 +++++++-
 2 files changed, 11 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/db8b3d49/spec/uninstall.spec.js
----------------------------------------------------------------------
diff --git a/spec/uninstall.spec.js b/spec/uninstall.spec.js
index aca4e7c..738e941 100644
--- a/spec/uninstall.spec.js
+++ b/spec/uninstall.spec.js
@@ -51,7 +51,10 @@ describe('uninstallPlatform', function() {
         });
 
         describe('with dependencies', function() {
-            it('should uninstall "dangling" dependencies');
+            it('should uninstall "dangling" dependencies', function() {
+            });
+            it('should remove dangling dependent directories', function() {
+            });
             it('should not uninstall any dependencies that are relied on by other plugins');
         });
     });

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/db8b3d49/src/uninstall.js
----------------------------------------------------------------------
diff --git a/src/uninstall.js b/src/uninstall.js
index 6d59e84..0f07774 100644
--- a/src/uninstall.js
+++ b/src/uninstall.js
@@ -93,7 +93,13 @@ function runUninstall(actions, platform, project_dir, plugin_dir, plugins_dir, o
                 cli_variables: options.cli_variables,
                 is_top_level: false /* TODO: should this "is_top_level" param be false for dependents? */
             };
-            runUninstall(actions, platform, project_dir, dependent_path, plugins_dir, opts, end);
+            runUninstall(actions, platform, project_dir, dependent_path, plugins_dir, opts, function(err) {
+                if (err) {
+                    if (callback) return callback(err);
+                    else throw err;
+                }
+                module.exports.uninstallPlugin(dangler, plugins_dir, end);
+            });
         });
     } else {
         // this plugin can get axed by itself, gogo!


[6/6] git commit: 0.9.0

Posted by fi...@apache.org.
0.9.0


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

Branch: refs/heads/master
Commit: ba9d4b0cb609fcbdfaec917de3534746dbf0f8dd
Parents: 4e90181
Author: Fil Maj <ma...@gmail.com>
Authored: Wed Jul 10 11:03:15 2013 -0700
Committer: Fil Maj <ma...@gmail.com>
Committed: Wed Jul 10 11:03:15 2013 -0700

----------------------------------------------------------------------
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/ba9d4b0c/package.json
----------------------------------------------------------------------
diff --git a/package.json b/package.json
index 345fc06..1229831 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
   "author": "Andrew Lunny <al...@gmail.com>",
   "name": "plugman",
   "description": "install/uninstall Cordova plugins",
-  "version": "0.8.2",
+  "version": "0.9.0",
   "repository": {
     "type": "git",
     "url": "git://git-wip-us.apache.org/repos/asf/cordova-plugman.git"


[4/6] git commit: [CB-4077] Fix tests for cordova-cli, properly uninstall plugin source

Posted by fi...@apache.org.
[CB-4077] Fix tests for cordova-cli, properly uninstall plugin source


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

Branch: refs/heads/master
Commit: 859e275d3e0fb0bf1c25a7b4752a6f0f506aff8e
Parents: 21a102c
Author: Ian Clelland <ic...@chromium.org>
Authored: Mon Jul 8 14:26:40 2013 -0400
Committer: Fil Maj <ma...@gmail.com>
Committed: Wed Jul 10 11:01:28 2013 -0700

----------------------------------------------------------------------
 spec/uninstall.spec.js | 96 ++++++++++++++++++++++++++++++++++++++++++++-
 src/uninstall.js       |  2 +-
 2 files changed, 95 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/859e275d/spec/uninstall.spec.js
----------------------------------------------------------------------
diff --git a/spec/uninstall.spec.js b/spec/uninstall.spec.js
index 61e1c81..aca4e7c 100644
--- a/spec/uninstall.spec.js
+++ b/spec/uninstall.spec.js
@@ -15,6 +15,98 @@ var uninstall = require('../src/uninstall'),
     engineplugin = 'EnginePlugin',
     plugins_dir = path.join(temp, 'plugins');
 
+describe('uninstallPlatform', function() {
+    var exists, get_json, chmod, exec, proc, add_to_queue, prepare, actions_push, c_a, rm;
+    beforeEach(function() {
+        proc = spyOn(actions.prototype, 'process').andCallFake(function(platform, proj, cb) {
+            cb();
+        });
+        actions_push = spyOn(actions.prototype, 'push');
+        c_a = spyOn(actions.prototype, 'createAction');
+        prepare = spyOn(plugman, 'prepare');
+        exec = spyOn(shell, 'exec').andReturn({code:1});
+        chmod = spyOn(fs, 'chmodSync');
+        exists = spyOn(fs, 'existsSync').andReturn(true);
+        get_json = spyOn(config_changes, 'get_platform_json').andReturn({
+            installed_plugins:{},
+            dependent_plugins:{}
+        });
+        rm = spyOn(shell, 'rm');
+        add_to_queue = spyOn(config_changes, 'add_uninstalled_plugin_to_prepare_queue');
+    });
+    describe('success', function() {
+        it('should call prepare after a successful uninstall', function() {
+            uninstall.uninstallPlatform('android', temp, dummyplugin, plugins_dir, {});
+            expect(prepare).toHaveBeenCalled();
+        });
+        it('should call the config-changes module\'s add_uninstalled_plugin_to_prepare_queue method after processing an install', function() {
+            uninstall.uninstallPlatform('android', temp, dummyplugin, plugins_dir, {});
+            expect(add_to_queue).toHaveBeenCalledWith(plugins_dir, 'DummyPlugin', 'android', true);
+        });
+        it('should queue up actions as appropriate for that plugin and call process on the action stack', function() {
+            uninstall.uninstallPlatform('android', temp, dummyplugin, plugins_dir, {});
+            expect(actions_push.calls.length).toEqual(3);
+            expect(c_a).toHaveBeenCalledWith(jasmine.any(Function), [jasmine.any(Object), temp, dummy_id], jasmine.any(Function), [jasmine.any(Object), path.join(plugins_dir, dummyplugin), temp, dummy_id]);
+            expect(proc).toHaveBeenCalled();
+        });
+
+        describe('with dependencies', function() {
+            it('should uninstall "dangling" dependencies');
+            it('should not uninstall any dependencies that are relied on by other plugins');
+        });
+    });
+
+    describe('failure', function() {
+        it('should throw if platform is unrecognized', function() {
+            expect(function() {
+                uninstall.uninstallPlatform('atari', temp, 'SomePlugin', plugins_dir, {});
+            }).toThrow('atari not supported.');
+        });
+        it('should throw if plugin is missing', function() {
+            exists.andReturn(false);
+            expect(function() {
+                uninstall.uninstallPlatform('android', temp, 'SomePluginThatDoesntExist', plugins_dir, {});
+            }).toThrow('Plugin "SomePluginThatDoesntExist" not found. Already uninstalled?');
+        });
+    });
+});
+
+describe('uninstallPlugin', function() {
+    var exists, get_json, chmod, exec, proc, add_to_queue, prepare, actions_push, c_a, rm;
+    beforeEach(function() {
+        proc = spyOn(actions.prototype, 'process').andCallFake(function(platform, proj, cb) {
+            cb();
+        });
+        actions_push = spyOn(actions.prototype, 'push');
+        c_a = spyOn(actions.prototype, 'createAction');
+        prepare = spyOn(plugman, 'prepare');
+        exec = spyOn(shell, 'exec').andReturn({code:1});
+        chmod = spyOn(fs, 'chmodSync');
+        exists = spyOn(fs, 'existsSync').andReturn(true);
+        get_json = spyOn(config_changes, 'get_platform_json').andReturn({
+            installed_plugins:{},
+            dependent_plugins:{}
+        });
+        rm = spyOn(shell, 'rm');
+        add_to_queue = spyOn(config_changes, 'add_uninstalled_plugin_to_prepare_queue');
+    });
+    describe('success', function() {
+        it('should remove the plugin directory', function() {
+            uninstall.uninstallPlugin(dummyplugin, plugins_dir);
+            expect(rm).toHaveBeenCalled();
+        });
+    });
+
+    describe('failure', function() {
+        it('should throw if plugin is missing', function() {
+            exists.andReturn(false);
+            expect(function() {
+                uninstall('android', temp, 'SomePluginThatDoesntExist', plugins_dir, {});
+            }).toThrow('Plugin "SomePluginThatDoesntExist" not found. Already uninstalled?');
+        });
+    });
+});
+
 describe('uninstall', function() {
     var exists, get_json, chmod, exec, proc, add_to_queue, prepare, actions_push, c_a, rm;
     beforeEach(function() {
@@ -52,10 +144,10 @@ describe('uninstall', function() {
 
         describe('with dependencies', function() {
             it('should uninstall "dangling" dependencies');
-            it('should not uninstall any dependencies that are relied on by other plugins'); 
+            it('should not uninstall any dependencies that are relied on by other plugins');
         });
     });
-    
+
     describe('failure', function() {
         it('should throw if platform is unrecognized', function() {
             expect(function() {

http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/859e275d/src/uninstall.js
----------------------------------------------------------------------
diff --git a/src/uninstall.js b/src/uninstall.js
index 8728711..6d59e84 100644
--- a/src/uninstall.js
+++ b/src/uninstall.js
@@ -17,7 +17,7 @@ module.exports = function(platform, project_dir, id, plugins_dir, options, callb
             if (callback) return callback(err);
             else throw err;
         }
-        module.exports.uninstallPlugin(id, plugins_dir, options, callback);
+        module.exports.uninstallPlugin(id, plugins_dir, callback);
     });
 }