CB-10438 :Install correct dependency version. Removed shell.remove, added 
pkg.json to dependency tests 1-3, and updated install.js (.replace) to fix 
tests in uninstall.spec.js and update to workw with jasmine 2.0

 This closes #530, this closes #455


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

Branch: refs/heads/common-2.0.x
Commit: fd6b9dd45e5f9fa8f6e7d7bfa28b9a4183882b2b
Parents: 7235aeb
Author: carynbear <[email protected]>
Authored: Mon Jun 6 17:21:02 2016 -0700
Committer: Steve Gill <[email protected]>
Committed: Thu Mar 23 23:01:29 2017 -0700

----------------------------------------------------------------------
 cordova-common/src/PluginInfo/PluginInfo.js     |   1 +
 cordova-lib/spec-plugman/install.spec.js        | 239 ++++++++++++++-----
 .../plugins/dependencies/[email protected]/package.json   |  11 +
 .../plugins/dependencies/[email protected]/plugin.xml     |  57 +++++
 .../dependencies/[email protected]/src/android/C.java     |   1 +
 .../[email protected]/src/ios/CPluginCommand.h            |   1 +
 .../[email protected]/src/ios/CPluginCommand.m            |   1 +
 .../dependencies/[email protected]/www/plugin-c.js        |   1 +
 .../plugins/dependencies/I/plugin.xml           |  59 +++++
 .../plugins/dependencies/I/src/android/I.java   |   1 +
 .../dependencies/I/src/ios/IPluginCommand.h     |   1 +
 .../dependencies/I/src/ios/IPluginCommand.m     |   1 +
 .../plugins/dependencies/I/www/plugin-i.js      |   1 +
 .../spec-plugman/plugins/dependencies/README.md |   7 +
 .../plugins/dependencies/Test1/package.json     |  11 +
 .../plugins/dependencies/Test1/plugin.xml       |  46 ++++
 .../dependencies/Test1/src/android/Test1.java   |   1 +
 .../dependencies/Test1/www/plugin-test.js       |   1 +
 .../plugins/dependencies/Test2/package.json     |  11 +
 .../plugins/dependencies/Test2/plugin.xml       |  46 ++++
 .../dependencies/Test2/src/android/Test2.java   |   1 +
 .../dependencies/Test2/www/plugin-test.js       |   1 +
 .../plugins/dependencies/Test3/package.json     |  11 +
 .../plugins/dependencies/Test3/plugin.xml       |  46 ++++
 .../dependencies/Test3/src/android/Test3.java   |   1 +
 .../dependencies/Test3/www/plugin-test.js       |   1 +
 .../projects/android_uninstall/cordova/version  |   4 +-
 .../android_uninstall/cordova/version.bat       |   2 +-
 cordova-lib/spec-plugman/uninstall.spec.js      |   6 +-
 cordova-lib/src/plugman/install.js              |  43 +++-
 cordova-lib/src/plugman/plugman.js              |   3 +-
 31 files changed, 548 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-common/src/PluginInfo/PluginInfo.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/PluginInfo/PluginInfo.js 
b/cordova-common/src/PluginInfo/PluginInfo.js
index 44501fa..09bd8de 100644
--- a/cordova-common/src/PluginInfo/PluginInfo.js
+++ b/cordova-common/src/PluginInfo/PluginInfo.js
@@ -108,6 +108,7 @@ function PluginInfo(dirname) {
     function _parseDependency(tag) {
         var dep =
             { id : tag.attrib.id
+            , version: tag.attrib.version || ''
             , url : tag.attrib.url || ''
             , subdir : tag.attrib.subdir || ''
             , commit : tag.attrib.commit

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/install.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/install.spec.js 
b/cordova-lib/spec-plugman/install.spec.js
index 081cc3c..86977a3 100644
--- a/cordova-lib/spec-plugman/install.spec.js
+++ b/cordova-lib/spec-plugman/install.spec.js
@@ -19,7 +19,10 @@
 
 /* jshint sub:true */
 
-var install = require('../src/plugman/install'),
+var helpers = require('../spec-cordova/helpers'),
+    path = require('path'),
+    cordova = require('../src/cordova/cordova'),
+    install = require('../src/plugman/install'),
     actions = require('cordova-common').ActionStack,
     xmlHelpers = require('cordova-common').xmlHelpers,
     et      = require('elementtree'),
@@ -57,9 +60,15 @@ var install = require('../src/plugman/install'),
         'B' : path.join(plugins_dir, 'dependencies', 'B'),
         'C' : path.join(plugins_dir, 'dependencies', 'C'),
         'F' : path.join(plugins_dir, 'dependencies', 'F'),
-        'G' : path.join(plugins_dir, 'dependencies', 'G')
+        'G' : path.join(plugins_dir, 'dependencies', 'G'),
+        'I' : path.join(plugins_dir, 'dependencies', 'I'),
+        '[email protected]' : path.join(plugins_dir, 'dependencies', '[email protected]'),
+        'Test1' : path.join(plugins_dir, 'dependencies', 'Test1'),
+        'Test2' : path.join(plugins_dir, 'dependencies', 'Test2'),
+        'Test3' : path.join(plugins_dir, 'dependencies', 'Test3')
     },
     results = {},
+    TIMEOUT = 60000,
     superspawn = require('cordova-common').superspawn;
 
 
@@ -84,7 +93,6 @@ var fake = {
         'dependencies' : function(id, dir) {
             if(id == plugins['A'])
                 return Q(id); // full path to plugin
-
             return Q( path.join(plugins_dir, 'dependencies', id) );
         }
     }
@@ -169,7 +177,7 @@ describe('plugman install start', function() {
         }).fail(function(error) {
             expect(error).toBeUndefined();
         });
-    });
+    }, TIMEOUT);
 });
 
 describe('install', function() {
@@ -199,15 +207,15 @@ describe('install', function() {
         it('Test 002 : should emit a results event with platform-agnostic 
<info>', function() {
             // org.test.plugins.childbrowser
             expect(results['emit_results'][0]).toBe('No matter what platform 
you are installing to, this notice is very important.');
-        });
+        }, TIMEOUT);
         it('Test 003 : should emit a results event with platform-specific 
<info>', function() {
             // org.test.plugins.childbrowser
             expect(results['emit_results'][1]).toBe('Please make sure you read 
this because it is very important to complete the installation of your 
plugin.');
-        });
+        }, TIMEOUT);
         it('Test 004 : should interpolate variables into <info> tags', 
function() {
             // VariableBrowser
             expect(results['emit_results'][2]).toBe('Remember that your api 
key is batman!');
-        });
+        }, TIMEOUT);
         it('Test 005 : should call fetch if provided plugin cannot be resolved 
locally', function(done) {
             fetchSpy.and.returnValue( Q( 
plugins['org.test.plugins.dummyplugin'] ) );
             spyOn(fs, 'existsSync').and.callFake( 
fake['existsSync']['noPlugins'] );
@@ -219,7 +227,7 @@ describe('install', function() {
                 expect(fetchSpy).toHaveBeenCalled();
                 done();
             });
-        });
+        }, TIMEOUT);
 
         it('Test 006 : should call fetch and convert oldID to newID', 
function(done) {
             fetchSpy.and.returnValue( Q( 
plugins['org.test.plugins.dummyplugin'] ) );
@@ -237,7 +245,7 @@ describe('install', function() {
                 expect(fetchSpy).toHaveBeenCalled();
                 done();
             });
-        });
+        }, TIMEOUT);
         describe('engine versions', function () {
             var fail, satisfies;
             beforeEach(function () {
@@ -254,7 +262,7 @@ describe('install', function() {
                     expect(satisfies).toHaveBeenCalledWith('2.5.0','>=1.0.0', 
true);
                     done();
                 });
-            });
+            }, TIMEOUT);
             it('Test 008 : should check version and munge it a little if it 
has "rc" in it so it plays nice with semver (introduce a dash in it)', 
function(done) {
                 exec.and.callFake(function(cmd, cb) { cb(null, '3.0.0rc1\n'); 
});
                 install('android', project, plugins['com.cordova.engine'])
@@ -263,7 +271,7 @@ describe('install', function() {
                     
expect(satisfies).toHaveBeenCalledWith('3.0.0-rc1','>=1.0.0', true);
                     done();
                 });
-            });
+            }, TIMEOUT);
             it('Test 009 : should check specific platform version over cordova 
version if specified', function(done) {
                 exec.and.callFake(function(cmd, cb) { cb(null, '3.1.0\n'); });
                 install('android', project, 
plugins['com.cordova.engine-android'])
@@ -272,7 +280,7 @@ describe('install', function() {
                     expect(satisfies).toHaveBeenCalledWith('3.1.0','>=3.1.0', 
true);
                     done();
                 });
-            });
+            }, TIMEOUT);
             it('Test 010 : should check platform sdk version if specified', 
function(done) {
                 var cordovaVersion = 
require('../package.json').version.replace(/-dev|-nightly.*$/, '');
                 exec.and.callFake(function(cmd, cb) { cb(null, '18\n'); });
@@ -288,7 +296,7 @@ describe('install', function() {
                     expect(satisfies.calls.argsFor(2)).toEqual([ 
'18.0.0','>=18', true ]);
                     done();
                 });
-            });
+            }, TIMEOUT);
             it('Test 011 : should check engine versions', function(done) {
                 install('android', project, plugins['com.cordova.engine'])
                 .fail(fail)
@@ -306,7 +314,7 @@ describe('install', function() {
                     expect(satisfies.calls.argsFor(3)).toEqual([ null, 
'>=3.0.0', true ]);
                     done();
                 });
-            });
+            }, TIMEOUT);
             it('Test 012 : should not check custom engine version that is not 
supported for platform', function(done) {
                 install('blackberry10', project, plugins['com.cordova.engine'])
                 .then(fail)
@@ -314,7 +322,7 @@ describe('install', function() {
                     expect(satisfies).not.toHaveBeenCalledWith('','>=3.0.0', 
true);
                 })
                 .fin(done);
-            });
+            }, TIMEOUT);
         });
 
         it('Test 014 : should not check custom engine version that is not 
supported for platform', function(done) {
@@ -326,7 +334,7 @@ describe('install', function() {
                 expect(spy).not.toHaveBeenCalledWith('','>=3.0.0');
                 done();
             }, 6000);
-        });
+        }, TIMEOUT);
 
         describe('with dependencies', function() {
             var emit;
@@ -339,37 +347,50 @@ describe('install', function() {
                 });
             });
 
-            it('Test 015 : should install any dependent plugins if missing', 
function(done) {
+            it('Test 015 : should install specific version of dependency', 
function(done) {
+                // Plugin I depends on [email protected]
+                emit.calls.reset();
+                return install('android', project, plugins['I'])
+                .then(function() {
+                    var install = common.spy.getInstall(emit);
+                    expect(fetchSpy).toHaveBeenCalledWith('[email protected]', 
jasmine.any(String), jasmine.any(Object));
+                    expect(install).toEqual([
+                        'Install start for "C" on android.',
+                        'Install start for "I" on android.'
+                    ]);
+                    done();
+                }, TIMEOUT);
+            }, TIMEOUT);
+
+            it('Test 016 : should install any dependent plugins if missing', 
function(done) {
                 emit.calls.reset();
                 return install('android', project, plugins['A'])
                 .then(function() {
                     var install = common.spy.getInstall(emit);
                     expect(install).toEqual([
-                    'Install start for "C" on android.',
-                    'Install start for "D" on android.',
-                    'Install start for "A" on android.'
+                        'Install start for "C" on android.',
+                        'Install start for "D" on android.',
+                        'Install start for "A" on android.'
                     ]);
                     done();
-                });
-                
-            });
+                }); 
+            }, TIMEOUT);
 
-            it('Test 016 : should install any dependent plugins from registry 
when url is not defined', function(done) {
+            it('Test 017 : should install any dependent plugins from registry 
when url is not defined', function(done) {
                 emit.calls.reset();
                 return install('android', project, plugins['A'])
                 .then(function() {
                     var install = common.spy.getInstall(emit);
                     expect(install).toEqual([
-                    'Install start for "C" on android.',
-                    'Install start for "D" on android.',
-                    'Install start for "A" on android.'
+                        'Install start for "C" on android.',
+                        'Install start for "D" on android.',
+                        'Install start for "A" on android.'
                     ]);
                     done();
                 });
-                
-            });
+            }, TIMEOUT);
 
-            it('Test 017 : should process all dependent plugins with alternate 
routes to the same plugin', function(done) {
+            it('Test 018 : should process all dependent plugins with alternate 
routes to the same plugin', function(done) {
                 // Plugin F depends on A, C, D and E
                 emit.calls.reset();
                 return install('android', project, plugins['F'])
@@ -384,18 +405,18 @@ describe('install', function() {
                     ]);
                     done();
                 });
-            });
+            }, TIMEOUT);
 
-            it('Test 018 : should throw if there is a cyclic dependency', 
function(done) {
+            it('Test 019 : should throw if there is a cyclic dependency', 
function(done) {
                 return install('android', project, plugins['G'])
                 .then(function() {
                     common.spy.getInstall(emit);
                 }).fail(function err (errMsg) {
                     expect(errMsg.toString()).toContain('Cyclic dependency 
from G to H');
                 }).fin(done);
-            });
+            }, TIMEOUT);
 
-            it('Test 019 : install subdir relative to top level plugin if no 
fetch meta', function(done) {
+            it('Test 020 : install subdir relative to top level plugin if no 
fetch meta', function(done) {
                 return install('android', project, plugins['B'])
                 .then(function() {
                     var install = common.spy.getInstall(emit);
@@ -406,9 +427,9 @@ describe('install', function() {
                     ]);
                     done();
                 });
-            });
+            }, TIMEOUT);
 
-            it('Test 020 : install uses meta data (if available) of top level 
plugin source', function(done) {
+            it('Test 021 : install uses meta data (if available) of top level 
plugin source', function(done) {
                 // Fake metadata so plugin 'B' appears from 'meta/B'
                 var meta = require('../src/plugman/util/metadata');
                 spyOn(meta, 'get_fetch_metadata').and.callFake(function(){
@@ -432,12 +453,12 @@ describe('install', function() {
                     expect(copy[1].indexOf(path.normalize('meta/subdir/E')) > 
0).toBe(true);
                     done();
                 });
-            });
+            }, TIMEOUT);
         });
     });
 
     describe('failure', function() {
-        it('Test 021 : should throw if platform is unrecognized & is missing 
api.js', function(done) {
+        it('Test 022 : should throw if platform is unrecognized & is missing 
api.js', function(done) {
             install('atari', project, 'SomePlugin')
             .then(function() {
                 expect(false).toBe(true);
@@ -445,9 +466,9 @@ describe('install', function() {
             }).fail(function err (errMsg) {
                 expect(errMsg.toString()).toContain('It is missing API.js');
                 done();
-            }, 6000);
-        });
-        it('Test 022 : should throw if variables are missing', function(done) {
+            });
+        }, TIMEOUT);
+        it('Test 023 : should throw if variables are missing', function(done) {
             var success = jasmine.createSpy('success');
             spyOn(PlatformJson.prototype, 
'isPluginInstalled').and.returnValue(false);
             install('android', project, plugins['com.adobe.vars'])
@@ -459,9 +480,9 @@ describe('install', function() {
                 expect(success).not.toHaveBeenCalled();
                 done();
             });
-        });
+        }, TIMEOUT);
 
-        it('Test 023 : should throw if git is not found on the path and a 
remote url is requested', function(done) {
+        it('Test 024 : should throw if git is not found on the path and a 
remote url is requested', function(done) {
             spyOn(fs, 'existsSync').and.callFake( 
fake['existsSync']['noPlugins'] );
             fetchSpy.and.callThrough();
             spyOn(shell, 'which').and.returnValue(null);
@@ -473,9 +494,9 @@ describe('install', function() {
                 expect(errMsg.toString()).toContain('"git" command line tool 
is not installed: make sure it is accessible on your PATH.');
                 done();
             });
-        }, 6000);
+        }, TIMEOUT);
 
-        it('Test 024 :should not fail when trying to install plugin less than 
minimum version. Skip instead  ', function(done){
+        it('Test 025 :should not fail when trying to install plugin less than 
minimum version. Skip instead  ', function(done){
             spyOn(semver, 'satisfies').and.returnValue(false);
             exec.and.callFake(function(cmd, cb) {
                 cb(null, '0.0.1\n');
@@ -488,9 +509,9 @@ describe('install', function() {
             .fail(function (error) {
                 expect(error).toBeUndefined();
             });
-        }, 6000);
+        }, TIMEOUT);
 
-        it('Test 025 : should throw if the engine scriptSrc escapes out of the 
plugin dir.', function(done) {
+        it('Test 026 : should throw if the engine scriptSrc escapes out of the 
plugin dir.', function(done) {
             var success = jasmine.createSpy('success'),
                 fail = jasmine.createSpy('fail').and.callFake(function(err) {
                     // <engine name="path-escaping-plugin" version=">=1.0.0" 
scriptSrc="../../../malicious/script" platform="*" />
@@ -507,8 +528,8 @@ describe('install', function() {
                     expect(fail).toHaveBeenCalled();
                     done();
                 });
-        });
-        it('Test 026 : should throw if a non-default cordova engine platform 
attribute is not defined.', function(done) {
+        }, TIMEOUT);
+        it('Test 027 : should throw if a non-default cordova engine platform 
attribute is not defined.', function(done) {
             var success = jasmine.createSpy('success'),
                 fail = jasmine.createSpy('fail');
             spyOn(PlatformJson.prototype, 
'isPluginInstalled').and.returnValue(false);
@@ -520,8 +541,8 @@ describe('install', function() {
                     expect(fail).toHaveBeenCalled();
                     done();
                 });
-        });
-        it('Test 027 : should throw if a non-default cordova engine scriptSrc 
attribute is not defined.', function(done) {
+        }, TIMEOUT);
+        it('Test 028 : should throw if a non-default cordova engine scriptSrc 
attribute is not defined.', function(done) {
             var success = jasmine.createSpy('success'),
                 fail = jasmine.createSpy('fail');
             spyOn(PlatformJson.prototype, 
'isPluginInstalled').and.returnValue(false);
@@ -533,13 +554,123 @@ describe('install', function() {
                     expect(fail).toHaveBeenCalled();
                     done();
                 });
-        });
+        }, TIMEOUT);
+    });
+});
+
+describe('end-to-end plugin dependency tests', function() {
+    var tmpDir, project, pluginsDir;
+
+    beforeEach(function() {
+        tmpDir = helpers.tmpDir('plugin_dependency_test');
+        project = path.join(tmpDir, 'hello3');
+        pluginsDir = path.join(project, 'plugins');
+        process.chdir(tmpDir);
+    });
+
+    afterEach(function() {
+
+        process.chdir(path.join(__dirname, '..'));  // Needed to rm the dir on 
Windows.
+        shell.rm('-rf', tmpDir);
     });
+
+    it('Test 029 : should fail if dependency already installed is wrong 
version', function(done) {
+        cordova.raw.create('hello3')
+        .then(function() {
+            process.chdir(project);
+            return cordova.raw.platform('add', 'android', {'fetch': true});
+        })
+        .then(function() {
+            return cordova.raw.plugin('add', 'cordova-plugin-file', {'fetch': 
true});
+        })
+        .then(function() {
+            expect(path.join(pluginsDir, 'cordova-plugin-file')).toExist();
+            return cordova.raw.plugin('add', plugins['Test1'], {'fetch': 
true});
+        })
+        .fail(function(err) {
+            expect(err.message).toContain('does not satisfy dependency plugin 
requirement');
+        })
+        .fin(done);
+    }, TIMEOUT);
+
+    it('Test 030 : should pass if dependency already installed is wrong 
version with --force', function(done) {
+        cordova.raw.create('hello3')
+        .then(function() {
+            process.chdir(project);
+            return cordova.raw.platform('add', 'android', {'fetch': true});
+        })
+        .then(function() {
+            return cordova.raw.plugin('add', 'cordova-plugin-file', {'fetch': 
true});
+        })
+        .then(function() {
+            expect(path.join(pluginsDir, 'cordova-plugin-file')).toExist();
+            return cordova.raw.plugin('add', plugins['Test1'], {'fetch': true, 
'force':true});
+        })
+        .then(function() {
+            expect(path.join(pluginsDir, 'Test1')).toExist();
+        })
+        .fail(function(err) {
+            expect(err).toBeUndefined();
+        })
+        .fin(done);
+    }, TIMEOUT);
+
+
+    it('Test 031 : should pass if dependency already installed is same major 
version (if specific version is specified)', function(done) {
+        //Test1 requires cordova-plugin-file version 2.0.0 (which should 
automatically turn into ^2.0.0); we'll install version 2.1.0
+        cordova.raw.create('hello3')
+        .then(function() {
+            process.chdir(project);
+            return cordova.raw.platform('add', 'android', {'fetch': true});
+        })
+        .then(function() {
+            return cordova.raw.plugin('add', '[email protected]', 
{'fetch': true});
+        })
+        .then(function() {
+            expect(path.join(pluginsDir, 'cordova-plugin-file')).toExist();
+            return cordova.raw.plugin('add', plugins['Test1'], {'fetch': 
true});
+        })
+        .then(function() {
+            expect(path.join(pluginsDir, 'Test1')).toExist();
+        })
+        .fail(function(err) {
+            //console.error(err);
+            expect(err).toBeUndefined();
+        })
+        .fin(done);
+    }, TIMEOUT);
+
+    it('Test 032 : should handle two plugins with same dependent plugin', 
function(done) {
+        //Test1 and Test2 have compatible dependencies on cordova-plugin-file
+        //Test1 and Test3 have incompatible dependencies on cordova-plugin-file
+        cordova.raw.create('hello3')
+        .then(function() {
+            process.chdir(project);
+            return cordova.raw.platform('add', 'android', {'fetch': true});
+        })
+        .then(function() {
+            return cordova.raw.plugin('add', plugins['Test1'], {'fetch': 
true});
+        })
+        .then(function() {
+            expect(path.join(pluginsDir, 'cordova-plugin-file')).toExist();
+            expect(path.join(pluginsDir, 'Test1')).toExist();
+            return cordova.raw.plugin('add', plugins['Test2'], {'fetch': 
true});
+        })
+        .then(function() {
+            return cordova.raw.plugin('add', plugins['Test3'], {'fetch': 
true});
+        })
+        .fail(function(err) {
+            expect(path.join(pluginsDir, 'Test2')).toExist();
+            expect(path.join(pluginsDir, 'Test3')).not.toExist();
+            expect(err.message).toContain('does not satisfy dependency plugin 
requirement');
+        }, TIMEOUT)
+        .fin(done);
+    }, TIMEOUT);
 });
 
 describe('end', function() {
 
-    it('Test 028 : end', function() {
+    it('Test 033 : end', function() {
         shell.rm('-rf', temp_dir);
-    });
+    }, TIMEOUT);
 });

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/package.json
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/package.json 
b/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/package.json
new file mode 100644
index 0000000..f2474fa
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/package.json
@@ -0,0 +1,11 @@
+{
+  "name": "c",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC"
+}

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/plugin.xml 
b/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/plugin.xml
new file mode 100644
index 0000000..2706bd6
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/plugin.xml
@@ -0,0 +1,57 @@
+<?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://cordova.apache.org/ns/plugins/1.0";
+    xmlns:android="http://schemas.android.com/apk/res/android";
+    id="C"
+    version="1.0.0">
+
+    <name>Plugin C</name>
+
+    <asset src="www/plugin-c.js" target="plugin-c.js" />
+
+    <config-file target="config.xml" parent="/*">
+        <access origin="build.phonegap.com" />
+    </config-file>
+
+    <!-- android -->
+    <platform name="android">
+        <config-file target="res/xml/config.xml" parent="plugins">
+            <plugin name="C"
+                value="org.test.C.C"/>
+        </config-file>
+
+        <source-file src="src/android/C.java"
+                target-dir="src/com/phonegap/C" />
+    </platform>
+
+        
+    <!-- ios -->
+    <platform name="ios">
+        <!-- CDV 2.5+ -->
+        <config-file target="config.xml" parent="plugins">
+            <plugin name="C"
+                value="CPluginCommand"/>
+        </config-file>
+
+        <header-file src="src/ios/CPluginCommand.h" />
+        <source-file src="src/ios/CPluginCommand.m"/>
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/src/android/C.java
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/src/android/C.java 
b/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/src/android/C.java
new file mode 100644
index 0000000..7f13a5f
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/src/android/C.java
@@ -0,0 +1 @@
+./dependencies/[email protected]/src/android/C.java

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/src/ios/CPluginCommand.h
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/src/ios/CPluginCommand.h
 
b/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/src/ios/CPluginCommand.h
new file mode 100644
index 0000000..83aea7b
--- /dev/null
+++ 
b/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/src/ios/CPluginCommand.h
@@ -0,0 +1 @@
+./dependencies/[email protected]/src/ios/CPluginCommand.h

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/src/ios/CPluginCommand.m
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/src/ios/CPluginCommand.m
 
b/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/src/ios/CPluginCommand.m
new file mode 100644
index 0000000..e9b80ec
--- /dev/null
+++ 
b/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/src/ios/CPluginCommand.m
@@ -0,0 +1 @@
+./dependencies/[email protected]/src/ios/CPluginCommand.m

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/www/plugin-c.js
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/www/plugin-c.js 
b/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/www/plugin-c.js
new file mode 100644
index 0000000..2ca5427
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/[email protected]/www/plugin-c.js
@@ -0,0 +1 @@
+./dependencies/Cv1/www/plugin-c.js

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/I/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/plugins/dependencies/I/plugin.xml 
b/cordova-lib/spec-plugman/plugins/dependencies/I/plugin.xml
new file mode 100644
index 0000000..0c2bf6d
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/I/plugin.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Iopyright 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/LIIENSE-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 IONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0";
+    xmlns:android="http://schemas.android.com/apk/res/android";
+    id="I"
+    version="0.5.0">
+
+    <name>Plugin I</name>
+
+    <dependency id="C" version="1.0.0" />
+
+    <asset src="www/plugin-i.js" target="plugin-i.js" />
+
+    <config-file target="config.xml" parent="/*">
+        <access origin="build.phonegap.com" />
+    </config-file>
+
+    <!-- android -->
+    <platform name="android">
+        <config-file target="res/xml/config.xml" parent="plugins">
+            <plugin name="I"
+                value="org.test.I.I"/>
+        </config-file>
+
+        <source-file src="src/android/I.java"
+                target-dir="src/com/phonegap/I" />
+    </platform>
+
+        
+    <!-- ios -->
+    <platform name="ios">
+        <!-- IDV 2.5+ -->
+        <config-file target="config.xml" parent="plugins">
+            <plugin name="I"
+                value="IPluginCommand"/>
+        </config-file>
+
+        <header-file src="src/ios/IPluginCommand.h" />
+        <source-file src="src/ios/IPluginCommand.m"/>
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/I/src/android/I.java
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/plugins/dependencies/I/src/android/I.java 
b/cordova-lib/spec-plugman/plugins/dependencies/I/src/android/I.java
new file mode 100644
index 0000000..85f102a
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/I/src/android/I.java
@@ -0,0 +1 @@
+./dependencies/I/src/android/I.java

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/I/src/ios/IPluginCommand.h
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/plugins/dependencies/I/src/ios/IPluginCommand.h 
b/cordova-lib/spec-plugman/plugins/dependencies/I/src/ios/IPluginCommand.h
new file mode 100644
index 0000000..64b6e73
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/I/src/ios/IPluginCommand.h
@@ -0,0 +1 @@
+./dependencies/C/src/ios/CPluginCommand.h

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/I/src/ios/IPluginCommand.m
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/plugins/dependencies/I/src/ios/IPluginCommand.m 
b/cordova-lib/spec-plugman/plugins/dependencies/I/src/ios/IPluginCommand.m
new file mode 100644
index 0000000..9d1eef4
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/I/src/ios/IPluginCommand.m
@@ -0,0 +1 @@
+./dependencies/I/src/ios/IPluginCommand.m

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/I/www/plugin-i.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/plugins/dependencies/I/www/plugin-i.js 
b/cordova-lib/spec-plugman/plugins/dependencies/I/www/plugin-i.js
new file mode 100644
index 0000000..851273d
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/I/www/plugin-i.js
@@ -0,0 +1 @@
+./dependencies/I/www/plugin-i.js

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/README.md
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/plugins/dependencies/README.md 
b/cordova-lib/spec-plugman/plugins/dependencies/README.md
index 0955be5..4709fc5 100644
--- a/cordova-lib/spec-plugman/plugins/dependencies/README.md
+++ b/cordova-lib/spec-plugman/plugins/dependencies/README.md
@@ -8,3 +8,10 @@ Here's a general overview of how the plugins in this directory 
are dependent on
 
 
    G <-> H
+
+I -> [email protected]
+
+Test1 --> [email protected]
+Test2 --> [email protected]
+Test3 --> [email protected]
+

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/Test1/package.json
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/plugins/dependencies/Test1/package.json 
b/cordova-lib/spec-plugman/plugins/dependencies/Test1/package.json
new file mode 100644
index 0000000..cf952c0
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/Test1/package.json
@@ -0,0 +1,11 @@
+{
+  "name": "test1",
+  "version": "0.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC"
+}

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/Test1/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/plugins/dependencies/Test1/plugin.xml 
b/cordova-lib/spec-plugman/plugins/dependencies/Test1/plugin.xml
new file mode 100644
index 0000000..802ade2
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/Test1/plugin.xml
@@ -0,0 +1,46 @@
+<?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://cordova.apache.org/ns/plugins/1.0";
+    xmlns:android="http://schemas.android.com/apk/res/android";
+    id="Test1"
+    version="0.0.0">
+
+    <name>Plugin Test1</name>
+
+    <dependency id="cordova-plugin-file" version="2.0.0" />
+
+    <asset src="www/plugin-test.js" target="plugin-test.js" />
+
+    <config-file target="config.xml" parent="/*">
+        <access origin="build.phonegap.com" />
+    </config-file>
+
+    <!-- android -->
+    <platform name="android">
+        <config-file target="res/xml/config.xml" parent="plugins">
+            <plugin name="Test1"
+                value="org.test.Test1.Test1"/>
+        </config-file>
+
+        <source-file src="src/android/Test1.java"
+                target-dir="src/com/phonegap/Test1" />
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/Test1/src/android/Test1.java
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/plugins/dependencies/Test1/src/android/Test1.java 
b/cordova-lib/spec-plugman/plugins/dependencies/Test1/src/android/Test1.java
new file mode 100644
index 0000000..2929aaf
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/Test1/src/android/Test1.java
@@ -0,0 +1 @@
+./dependencies/Test1/src/android/Test1.java

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/Test1/www/plugin-test.js
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/plugins/dependencies/Test1/www/plugin-test.js 
b/cordova-lib/spec-plugman/plugins/dependencies/Test1/www/plugin-test.js
new file mode 100644
index 0000000..cc654be
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/Test1/www/plugin-test.js
@@ -0,0 +1 @@
+./dependencies/Test1/www/plugin-test.js

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/Test2/package.json
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/plugins/dependencies/Test2/package.json 
b/cordova-lib/spec-plugman/plugins/dependencies/Test2/package.json
new file mode 100644
index 0000000..4fe99dd
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/Test2/package.json
@@ -0,0 +1,11 @@
+{
+  "name": "test2",
+  "version": "0.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC"
+}

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/Test2/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/plugins/dependencies/Test2/plugin.xml 
b/cordova-lib/spec-plugman/plugins/dependencies/Test2/plugin.xml
new file mode 100644
index 0000000..ccde6c1
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/Test2/plugin.xml
@@ -0,0 +1,46 @@
+<?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://cordova.apache.org/ns/plugins/1.0";
+    xmlns:android="http://schemas.android.com/apk/res/android";
+    id="Test2"
+    version="0.0.0">
+
+    <name>Plugin Test2</name>
+
+    <dependency id="cordova-plugin-file" version="2.X.0" />
+
+    <asset src="www/plugin-test.js" target="plugin-test.js" />
+
+    <config-file target="config.xml" parent="/*">
+        <access origin="build.phonegap.com" />
+    </config-file>
+
+    <!-- android -->
+    <platform name="android">
+        <config-file target="res/xml/config.xml" parent="plugins">
+            <plugin name="Test2"
+                value="org.test.Test2.Test2"/>
+        </config-file>
+
+        <source-file src="src/android/Test2.java"
+                target-dir="src/com/phonegap/Test2" />
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/Test2/src/android/Test2.java
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/plugins/dependencies/Test2/src/android/Test2.java 
b/cordova-lib/spec-plugman/plugins/dependencies/Test2/src/android/Test2.java
new file mode 100644
index 0000000..0774061
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/Test2/src/android/Test2.java
@@ -0,0 +1 @@
+./dependencies/Test2/src/android/Test2.java

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/Test2/www/plugin-test.js
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/plugins/dependencies/Test2/www/plugin-test.js 
b/cordova-lib/spec-plugman/plugins/dependencies/Test2/www/plugin-test.js
new file mode 100644
index 0000000..e4f50d5
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/Test2/www/plugin-test.js
@@ -0,0 +1 @@
+./dependencies/Test2/www/plugin-test.js

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/Test3/package.json
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/plugins/dependencies/Test3/package.json 
b/cordova-lib/spec-plugman/plugins/dependencies/Test3/package.json
new file mode 100644
index 0000000..4d43bd4
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/Test3/package.json
@@ -0,0 +1,11 @@
+{
+  "name": "test3",
+  "version": "0.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC"
+}

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/Test3/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/plugins/dependencies/Test3/plugin.xml 
b/cordova-lib/spec-plugman/plugins/dependencies/Test3/plugin.xml
new file mode 100644
index 0000000..50fd06e
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/Test3/plugin.xml
@@ -0,0 +1,46 @@
+<?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://cordova.apache.org/ns/plugins/1.0";
+    xmlns:android="http://schemas.android.com/apk/res/android";
+    id="Test3"
+    version="0.0.0">
+
+    <name>Plugin Test3</name>
+
+    <dependency id="cordova-plugin-file" version="3.0.0" />
+
+    <asset src="www/plugin-test.js" target="plugin-test.js" />
+
+    <config-file target="config.xml" parent="/*">
+        <access origin="build.phonegap.com" />
+    </config-file>
+
+    <!-- android -->
+    <platform name="android">
+        <config-file target="res/xml/config.xml" parent="plugins">
+            <plugin name="Test3"
+                value="org.test.Test3.Test3"/>
+        </config-file>
+
+        <source-file src="src/android/Test3.java"
+                target-dir="src/com/phonegap/Test3" />
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/Test3/src/android/Test3.java
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/plugins/dependencies/Test3/src/android/Test3.java 
b/cordova-lib/spec-plugman/plugins/dependencies/Test3/src/android/Test3.java
new file mode 100644
index 0000000..cf94c76
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/Test3/src/android/Test3.java
@@ -0,0 +1 @@
+./dependencies/Test3/src/android/Test3.java

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/plugins/dependencies/Test3/www/plugin-test.js
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/plugins/dependencies/Test3/www/plugin-test.js 
b/cordova-lib/spec-plugman/plugins/dependencies/Test3/www/plugin-test.js
new file mode 100644
index 0000000..fde12ae
--- /dev/null
+++ b/cordova-lib/spec-plugman/plugins/dependencies/Test3/www/plugin-test.js
@@ -0,0 +1 @@
+./dependencies/Test3/www/plugin-test.js

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/projects/android_uninstall/cordova/version
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/projects/android_uninstall/cordova/version 
b/cordova-lib/spec-plugman/projects/android_uninstall/cordova/version
index 3b8e2c5..9afe719 100755
--- a/cordova-lib/spec-plugman/projects/android_uninstall/cordova/version
+++ b/cordova-lib/spec-plugman/projects/android_uninstall/cordova/version
@@ -8,9 +8,7 @@
        to you 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
@@ -19,4 +17,4 @@
        under the License.
 */
 
-console.log('9.0.0');
+console.log('9.0.0');
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/projects/android_uninstall/cordova/version.bat
----------------------------------------------------------------------
diff --git 
a/cordova-lib/spec-plugman/projects/android_uninstall/cordova/version.bat 
b/cordova-lib/spec-plugman/projects/android_uninstall/cordova/version.bat
index 09a622a..c637d7c 100644
--- a/cordova-lib/spec-plugman/projects/android_uninstall/cordova/version.bat
+++ b/cordova-lib/spec-plugman/projects/android_uninstall/cordova/version.bat
@@ -1,2 +1,2 @@
 @ECHO OFF
-echo 9.0.0
+echo 9.0.0
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/spec-plugman/uninstall.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/uninstall.spec.js 
b/cordova-lib/spec-plugman/uninstall.spec.js
index 2e8e862..6b81824 100644
--- a/cordova-lib/spec-plugman/uninstall.spec.js
+++ b/cordova-lib/spec-plugman/uninstall.spec.js
@@ -101,8 +101,8 @@ describe('plugman uninstall start', function() {
             done();
         }).fail(function(err){
             expect(err).toBeUndefined();
-        }, 60000);
-    });
+        });
+    }, 60000);
 });
 
 describe('uninstallPlatform', function() {
@@ -182,7 +182,7 @@ describe('uninstallPlatform', function() {
         });
     });
 
-    describe('failure', function() {
+    describe('failure ', function() {
         it('Test 004 : should throw if platform is unrecognized', 
function(done) {
             uninstall.uninstallPlatform('atari', project, 'SomePlugin')
             .then(function(result){

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/src/plugman/install.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/install.js 
b/cordova-lib/src/plugman/install.js
index 4a3838e..e0d82bc 100644
--- a/cordova-lib/src/plugman/install.js
+++ b/cordova-lib/src/plugman/install.js
@@ -120,7 +120,6 @@ function possiblyFetch(id, plugins_dir, options) {
     var opts = underscore.extend({}, options, {
         client: 'plugman'
     });
-
     return plugman.raw.fetch(id, plugins_dir, opts);
 }
 
@@ -416,7 +415,7 @@ function runInstall(actions, platform, project_dir, 
plugin_dir, plugins_dir, opt
             if(error === 'skip') {
                 events.emit('warn', 'Skipping \'' + pluginInfo.id + '\' for ' 
+ platform);
             } else {
-                events.emit('warn', 'Failed to install \'' + pluginInfo.id + 
'\':' + error.stack);
+                events.emit('warn', 'Failed to install \'' + pluginInfo.id + 
'\': ' + error.stack);
                 throw error;
             }
         }
@@ -563,15 +562,45 @@ function tryFetchDependency(dep, install, options) {
 function installDependency(dep, install, options) {
 
     var opts;
-
     dep.install_dir = path.join(install.plugins_dir, dep.id);
-    if ( fs.existsSync(dep.install_dir) ) {
-        events.emit('verbose', 'Plugin dependency "' + dep.id + '" already 
fetched, using that version.');
+
+    events.emit('verbose', 'Requesting plugin "' + (dep.version? 
dep.id+'@'+dep.version : dep.id) + '".' );
+
+    if (fs.existsSync(dep.install_dir) ) {
+        var pluginInfo = new PluginInfo(dep.install_dir);
+        var version_installed = pluginInfo.version;
+        var version_required = dep.version;
+
+        if(dep.version) {
+            if (Number(dep.version.replace('.',''))) {
+                version_required = '^' + dep.version;
+            }
+        }
+
+        if (options.force || 
+            semver.satisfies(version_installed, version_required, 
/*loose=*/true) || 
+            version_required === null || 
+            version_required === undefined ) {
+            events.emit('log', 'Plugin dependency "' + (version_installed ? 
dep.id+'@'+version_installed : dep.id) + '" already fetched, using that 
version.');
+        } else {
+            var msg = 'Version of installed plugin: "' +
+                dep.id + '@'+ version_installed +
+                '" does not satisfy dependency plugin requirement "' +
+                dep.id +'@'+ version_required +
+                 '". Try --force to use installed plugin as dependency.';
+            return Q()
+            .then(function() {
+                // Remove plugin
+                return shell.rm('-rf', path.join(install.plugins_dir, 
install.top_plugin_id));
+            }).then(function() {
+                // Return promise chain and finally reject
+                return Q.reject(new CordovaError(msg));
+            });
+        }
         opts = underscore.extend({}, options, {
             cli_variables: install.filtered_variables,
             is_top_level: false
         });
-
         return runInstall(install.actions, install.platform, 
install.project_dir, dep.install_dir, install.plugins_dir, opts);
 
     } else {
@@ -585,8 +614,8 @@ function installDependency(dep, install, options) {
             expected_id: dep.id
         });
 
-        var dep_src = dep.url.length ? dep.url : dep.id;
 
+        var dep_src = dep.url.length ? dep.url : (dep.version? dep.id + 
'@'+dep.version: dep.id);
         return possiblyFetch(dep_src, install.plugins_dir, opts)
         .then(
             function(plugin_dir) {

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/fd6b9dd4/cordova-lib/src/plugman/plugman.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/plugman.js 
b/cordova-lib/src/plugman/plugman.js
index 3957e7f..3a97824 100644
--- a/cordova-lib/src/plugman/plugman.js
+++ b/cordova-lib/src/plugman/plugman.js
@@ -109,7 +109,8 @@ plugman.commands =  {
             www_dir: cli_opts.www,
             searchpath: cli_opts.searchpath,
             link: cli_opts.link,
-            projectRoot: cli_opts.project
+            projectRoot: cli_opts.project,
+            force: cli_opts.force || false
         };
         var p = Q();
         cli_opts.plugin.forEach(function (pluginSrc) {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to