cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ste...@apache.org
Subject [02/32] cordova-lib git commit: CB-12021: Added local path support to --fetch and fixed failing tests for adding a relative path
Date Wed, 22 Feb 2017 00:07:33 GMT
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/b3ca3001/cordova-lib/spec-cordova/pkgJson.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/pkgJson.spec.js b/cordova-lib/spec-cordova/pkgJson.spec.js
index 8b3c46c..397f9b6 100644
--- a/cordova-lib/spec-cordova/pkgJson.spec.js
+++ b/cordova-lib/spec-cordova/pkgJson.spec.js
@@ -22,7 +22,8 @@ var helpers = require('./helpers'),
     events = require('cordova-common').events,
     ConfigParser = require('cordova-common').ConfigParser,
     cordova = require('../src/cordova/cordova'),
-    TIMEOUT = 30 * 1000;
+    TIMEOUT = 30 * 1000,
+    semver  = require('semver');
 
 // This group of tests checks if plugins are added and removed as expected from package.json.
 describe('plugin end-to-end', function() {
@@ -30,6 +31,7 @@ describe('plugin end-to-end', function() {
     var tmpDir = helpers.tmpDir('plugin_test_pkgjson');
     var project = path.join(tmpDir, 'project');
     var results;
+    var testRunRoot = process.cwd();
 
     events.on('results', function(res) { results = res; });
 
@@ -224,6 +226,115 @@ describe('plugin end-to-end', function() {
             expect(err).toBeUndefined();
         }).fin(done);
     }, TIMEOUT);
+    // Test #023 : if pkg.json and config.xml have no platforms/plugins/spec.
+    // and --save --fetch is called, use the pinned version or plugin pkg.json version.
+    it('Test#023 : use pinned/lastest version if there is no platform/plugin version passed in and no platform/plugin versions in pkg.json or config.xml', function(done) {
+        var iosPlatform = 'ios';
+        var iosVersion;
+        var cwd = process.cwd();
+        var iosDirectory = path.join(cwd, 'platforms/ios/cordova/version');
+        var configXmlPath = path.join(cwd, 'config.xml');
+        var pkgJsonPath = path.join(cwd,'package.json');
+        delete require.cache[require.resolve(pkgJsonPath)];
+        var cfg = new ConfigParser(configXmlPath);
+        var pkgJson = require(pkgJsonPath);
+        var engines = cfg.getEngines();
+        var engNames;
+        var engSpec;
+        var configPlugins = cfg.getPluginIdList();
+        var configPlugin = cfg.getPlugin(configPlugins);
+        var pluginPkgJsonDir = path.join(cwd, 'plugins/cordova-plugin-camera/package.json');
+        var pluginPkgJsonVersion;
+
+        // Pkg.json has no platform or plugin or specs.
+        expect(pkgJson.cordova).toBeUndefined();
+        expect(pkgJson.dependencies).toBeUndefined();
+        // Config.xml has no platform or plugin or specs.
+        expect(engines.length).toEqual(0);
+        // Add ios without version.
+        return cordova.raw.platform('add', ['ios'], {'save':true, 'fetch':true})
+        .then(function() {
+            // Delete any previous caches of require(package.json).
+            delete require.cache[require.resolve(pkgJsonPath)];
+            pkgJson = require(pkgJsonPath);
+            // Pkg.json has ios.
+            expect(pkgJson.cordova.platforms).toEqual([iosPlatform]);
+            // Config.xml and ios/cordova/version check.
+            var cfg2 = new ConfigParser(configXmlPath);
+            engines = cfg2.getEngines();
+            // ios platform has been added to config.xml.
+            expect(engines.length).toEqual(1);
+            // Config.xml has ios platform.
+            engNames = engines.map(function(elem) {
+                return elem.name;
+            });
+            expect(engNames).toEqual([ 'ios' ]);
+            // delete previous caches of iosVersion;
+            delete require.cache[require.resolve(iosDirectory)];
+            iosVersion = require(iosDirectory);
+            engSpec = engines.map(function(elem) {
+                // Check that config and ios/cordova/version versions "satify" each other.
+                expect(semver.satisfies(iosVersion.version, elem.spec)).toEqual(true);
+            });
+        }).then(function() {
+            // Add camera plugin with --save --fetch.
+            return cordova.raw.plugin('add', 'cordova-plugin-camera', {'save':true, 'fetch':true});
+        }).then(function() {
+            var cfg3 = new ConfigParser(configXmlPath);
+            // Check config.xml for plugins and spec.
+            configPlugins = cfg3.getPluginIdList();
+            configPlugin = cfg3.getPlugin(configPlugins);
+            // Delete previous caches of pluginPkgJson.
+            delete require.cache[require.resolve(pluginPkgJsonDir)];
+            pluginPkgJsonVersion = require(pluginPkgJsonDir);
+            // Check that version in plugin pkg.json and config version "satisfy" each other.
+            expect(semver.satisfies(pluginPkgJsonVersion.version, configPlugin.spec)).toEqual(true);
+            // Delete any previous caches of require(package.json).
+            delete require.cache[require.resolve(pkgJsonPath)];
+            pkgJson = require(pkgJsonPath);
+            // Check that pkg.json and plugin pkg.json versions "satisfy".
+            expect(semver.satisfies(pluginPkgJsonVersion.version, pkgJson.dependencies['cordova-ios']));
+        }).fail(function(err) {
+            expect(err).toBeUndefined();
+        }).fin(done);
+    // Cordova prepare needs extra wait time to complete.
+    },60000);
+    
+    // Test#025: has a pkg.json. Checks if local path is added to pkg.json for platform and plugin add.
+    it('Test#025 : if you add a platform/plugin with local path, pkg.json gets updated', function (done) {
+
+        var cwd = process.cwd();
+        var platformPath = path.join(testRunRoot,'spec-cordova/fixtures/platforms/cordova-browser');
+        var pluginPath = path.join(testRunRoot,'spec-cordova/fixtures/plugins/cordova-lib-test-plugin');
+        var pkgJsonPath = path.join(cwd,'package.json');
+        var pkgJson;
+        delete require.cache[require.resolve(pkgJsonPath)];
+
+        // Run cordova platform add local path --save --fetch.
+        return cordova.raw.platform('add', platformPath, {'save':true, 'fetch':true})
+        .then(function() {
+            // Delete any previous caches of require(package.json).
+            delete require.cache[require.resolve(pkgJsonPath)];
+            pkgJson = require(pkgJsonPath);
+            // Pkg.json has ios.
+            expect(pkgJson.cordova.platforms).toEqual(['browser']);
+            // Pkg.json has platform local path spec.
+            expect(pkgJson.dependencies['cordova-browser'].includes(platformPath)).toEqual(true);
+        }).then(function() {
+            // Run cordova plugin add local path --save --fetch.
+            return cordova.raw.plugin('add', pluginPath, {'save':true, 'fetch':true});
+        }).then(function() {
+            // Delete any previous caches of require(package.json).
+            delete require.cache[require.resolve(pkgJsonPath)];
+            pkgJson = require(pkgJsonPath);
+            // Pkg.json has geolocation plugin.
+            expect(pkgJson.cordova.plugins['cordova-lib-test-plugin']).toBeDefined();
+            // Pkg.json has plugin local path spec.
+            expect(pkgJson.dependencies['cordova-lib-test-plugin'].includes(pluginPath)).toEqual(true);
+        }).fail(function(err) {
+            expect(err).toBeUndefined();
+        }).fin(done);
+    },60000);
 });
 
 // This group of tests checks if platforms are added and removed as expected from package.json.
@@ -290,8 +401,7 @@ describe('platform end-to-end with --save', function () {
             pkgJson = require(pkgJsonPath);
             // Checking that the platform removed is in not in the platforms key.
             expect(pkgJson.cordova.platforms.indexOf(helpers.testPlatform)).toEqual(-1);
-        }).then(emptyPlatformList) // platform ls should be empty too.
-        .fail(function(err) {
+        }).fail(function(err) {
             expect(err).toBeUndefined();
         }).fin(done);
     }, TIMEOUT);
@@ -299,12 +409,14 @@ describe('platform end-to-end with --save', function () {
     it('Test#007 : should not remove platforms from package.json when removing without --save', function(done) {
         var pkgJsonPath = path.join(process.cwd(),'package.json');
         expect(pkgJsonPath).toExist();
-        var pkgJson;
+        delete require.cache[require.resolve(pkgJsonPath)];
+        var pkgJson = require(pkgJsonPath);
         emptyPlatformList().then(function() {
             // Add the testing platform with --save.
             return cordova.raw.platform('add', [helpers.testPlatform], {'save':true});
         }).then(function() {
             // Check the platform add was successful.
+            delete require.cache[require.resolve(pkgJsonPath)];
             pkgJson = require(pkgJsonPath);
             expect(pkgJson.cordova.platforms).not.toBeUndefined();
             expect(pkgJson.cordova.platforms.indexOf(helpers.testPlatform)).toBeGreaterThan(-1);
@@ -374,7 +486,8 @@ describe('platform end-to-end with --save', function () {
         })
         .fin(done);
     }, TIMEOUT);
-    it('Test#010 : two platforms are added and removed correctly with --save --fetch', function(done) {
+
+it('Test#010 : two platforms are added and removed correctly with --save --fetch', function(done) {
         var pkgJsonPath = path.join(process.cwd(),'package.json');
         expect(pkgJsonPath).toExist();
         var pkgJson;
@@ -450,3 +563,407 @@ describe('platform end-to-end with --save', function () {
         }).fin(done);
     }, TIMEOUT);
 });
+
+// Test #020 : use basePkgJson15 as pkg.json contains platform/spec and plugin/spec and config.xml does not.
+describe('During add, if pkg.json has a platform/plugin spec, use that one.', function () {
+    var tmpDir = helpers.tmpDir('platform_test_pkgjson');
+    var project = path.join(tmpDir, 'project');
+    var results;
+
+    beforeEach(function() {
+        shell.rm('-rf', tmpDir);
+
+        // cp then mv because we need to copy everything, but that means it'll copy the whole directory.
+        // Using /* doesn't work because of hidden files.
+        shell.cp('-R', path.join(__dirname, 'fixtures', 'basePkgJson15'), tmpDir);
+        shell.mv(path.join(tmpDir, 'basePkgJson15'), project);
+        process.chdir(project);
+        events.on('results', function(res) { results = res; });
+    });
+
+    afterEach(function() {
+        // Delete any previous caches of require(package.json).
+        delete require.cache[require.resolve(path.join(process.cwd(),'package.json'))];
+        process.chdir(path.join(__dirname, '..'));  // Needed to rm the dir on Windows.
+        shell.rm('-rf', tmpDir);
+    });
+
+    // Factoring out some repeated checks.
+    function emptyPlatformList() {
+        return cordova.raw.platform('list').then(function() {
+            var installed = results.match(/Installed platforms:\n  (.*)/);
+            expect(installed).toBeDefined();
+            expect(installed[1].indexOf(helpers.testPlatform)).toBe(-1);
+        });
+    }
+
+    /** Test#020 will check that pkg.json, config.xml, platforms.json, and cordova platform ls
+    *   are updated with the correct (platform and plugin) specs from pkg.json.
+    */
+    it('Test#020 : During add, if pkg.json has a spec, use that one.', function(done) {
+        var iosPlatform = 'ios';
+        var iosVersion;
+        var cwd = process.cwd();
+        var iosDirectory = path.join(cwd, 'platforms/ios/cordova/version');
+        var platformsFolderPath = path.join(cwd,'platforms/platforms.json');
+        var configXmlPath = path.join(cwd, 'config.xml');
+        var pkgJsonPath = path.join(cwd,'package.json');
+        delete require.cache[require.resolve(pkgJsonPath)];
+        var cfg = new ConfigParser(configXmlPath);
+        var pkgJson = require(pkgJsonPath);
+        var engines = cfg.getEngines();
+        var engNames;
+        var engSpec;
+        var platformsJson;
+        var configPlugins = cfg.getPluginIdList();
+        var pluginPkgJsonDir = path.join(cwd, 'plugins/cordova-plugin-splashscreen/package.json');
+        var pluginPkgJsonVersion;
+
+        // Pkg.json has ios and spec '^4.2.1' and splashscreen '^3.2.2'.
+        expect(pkgJson.cordova.platforms).toEqual([ iosPlatform ]);
+        expect(pkgJson.dependencies).toEqual({ 'cordova-plugin-splashscreen' : '^3.2.2', 'cordova-ios' : '^4.2.1' });
+        // Config.xml has no platforms or plugins yet.
+        expect(engines.length).toEqual(0);
+        expect(configPlugins.length).toEqual(0);
+
+        emptyPlatformList().then(function() {
+            // Add ios with --save and --fetch.
+            return cordova.raw.platform('add', [iosPlatform], {'save':true , 'fetch':true});
+        }).then(function() {
+            // Require platformsFolderPath, ios and spec should be in there.
+            delete require.cache[require.resolve(platformsFolderPath)];
+            platformsJson = require(platformsFolderPath);
+            // Delete any previous caches of require(package.json).
+            // ios has been added.
+            delete require.cache[require.resolve(pkgJsonPath)];
+            pkgJson = require(pkgJsonPath);
+            // No change to pkg.json platforms or spec for ios.
+            expect(pkgJson.cordova.platforms).toEqual([iosPlatform]);
+            // Config.xml and ios/cordova/version check.
+            var cfg2 = new ConfigParser(configXmlPath);
+            engines = cfg2.getEngines();
+            // ios platform has been added to config.xml.
+            expect(engines.length).toEqual(1);
+            engNames = engines.map(function(elem) {
+                // ios is added to config
+                expect(elem.name).toEqual(iosPlatform);
+                return elem.name;
+            });
+            engSpec = engines.map(function(elem) {
+                // Check that config and ios/cordova/version versions "satify" each other.
+                delete require.cache[require.resolve(iosDirectory)];
+                iosVersion = require(iosDirectory);
+                expect(semver.satisfies(iosVersion.version, elem.spec)).toEqual(true);
+                // Check that config and platforms.json "satisfy".
+                expect(semver.satisfies(platformsJson[iosPlatform], elem.spec)).toEqual(true);
+            });
+            // Config.xml added ios platform.
+            expect(engNames).toEqual([ 'ios' ]);
+            // Check that pkg.json and ios/cordova/version versions "satisfy" each other.
+            expect(semver.satisfies(iosVersion.version, pkgJson.dependencies['cordova-ios'])).toEqual(true);
+            // Check that pkg.json and platforms.json "satisfy".
+            expect(semver.satisfies(platformsJson[iosPlatform], pkgJson.dependencies['cordova-ios'])).toEqual(true);
+        }).then(function() {
+            // Add splashscreen plugin with --save --fetch.
+            return cordova.raw.plugin('add', 'cordova-plugin-splashscreen', {'save':true, 'fetch':true});
+        }).then(function() {
+            delete require.cache[require.resolve(pluginPkgJsonDir)];
+            pluginPkgJsonVersion = require(pluginPkgJsonDir);
+            // Check that pkg.json version and plugin pkg.json version "satisfy" each other.
+            delete require.cache[require.resolve(pkgJsonPath)];
+            pkgJson = require(pkgJsonPath);
+            expect(semver.satisfies(pluginPkgJsonVersion.version, pkgJson.dependencies['cordova-plugin-splashscreen'])).toEqual(true);
+        }).fail(function(err) {
+            expect(err).toBeUndefined();
+        }).fin(done);
+    // Cordova prepare needs extra wait time to complete.
+    },60000); 
+});
+
+// Test #021 : use basePkgJson16 as config.xml contains platform/spec and plugin/spec pkg.json does not.
+describe('During add, if config.xml has a platform/plugin spec and pkg.json does not, use config.', function () {
+    var tmpDir = helpers.tmpDir('platform_test_pkgjson');
+    var project = path.join(tmpDir, 'project');
+    var results;
+
+    beforeEach(function() {
+        shell.rm('-rf', tmpDir);
+
+        // cp then mv because we need to copy everything, but that means it'll copy the whole directory.
+        // Using /* doesn't work because of hidden files.
+        shell.cp('-R', path.join(__dirname, 'fixtures', 'basePkgJson16'), tmpDir);
+        shell.mv(path.join(tmpDir, 'basePkgJson16'), project);
+        process.chdir(project);
+        events.on('results', function(res) { results = res; });
+    });
+
+    afterEach(function() {
+        // Delete any previous caches of require(package.json).
+        process.chdir(path.join(__dirname, '..'));  // Needed to rm the dir on Windows.
+        shell.rm('-rf', tmpDir);
+    });
+
+    // Factoring out some repeated checks.
+    function emptyPlatformList() {
+        return cordova.raw.platform('list').then(function() {
+            var installed = results.match(/Installed platforms:\n  (.*)/);
+            expect(installed).toBeDefined();
+            expect(installed[1].indexOf(helpers.testPlatform)).toBe(-1);
+        });
+    }
+
+    /** Test#021 during add, this test will check that pkg.json, config.xml, platforms.json, 
+    *   and cordova platform ls are updated with the correct platform/plugin spec from config.xml.
+    */
+    it('Test#021 : If config.xml has a spec (and none was specified and pkg.json does not have one), use config.', function(done) {
+        var iosPlatform = 'ios';
+        var iosVersion;
+        var cwd = process.cwd();
+        var iosDirectory = path.join(cwd, 'platforms/ios/cordova/version');
+        var configXmlPath = path.join(cwd, 'config.xml');
+        var pkgJsonPath = path.join(cwd,'package.json');
+        var cfg = new ConfigParser(configXmlPath);
+        var pkgJson;
+        var engines = cfg.getEngines();
+        var engNames;
+        var engSpec;
+        var configPlugins = cfg.getPluginIdList();
+        var configPlugin = cfg.getPlugin(configPlugins);
+        var pluginPkgJsonDir = path.join(cwd, 'plugins/cordova-plugin-splashscreen/package.json');
+        var pluginPkgJsonVersion;
+
+        // Pkg.json does not have platform or spec yet. Config.xml has ios and spec '~4.2.1'.
+        // Remove for testing purposes so platform is not pre-installed.
+        cordova.raw.platform('rm', [iosPlatform], {'save':true});
+        emptyPlatformList().then(function() {
+            // Add ios with --save and --fetch.
+            return cordova.raw.platform('add', [iosPlatform], {'save':true , 'fetch':true});
+        }).then(function() {
+            // Delete any previous caches of require(package.json).
+            delete require.cache[require.resolve(pkgJsonPath)];
+            pkgJson = require(pkgJsonPath);
+            // pkg.json has new platform.
+            expect(pkgJson.cordova.platforms).toEqual([iosPlatform]);
+            // Config.xml and ios/cordova/version check.
+            var cfg2 = new ConfigParser(configXmlPath);
+            engines = cfg2.getEngines();
+            // ios platform is in config.xml.
+            expect(engines.length).toEqual(1);
+            engNames = engines.map(function(elem) {
+                return elem.name;
+            });
+            // Config.xml has ios platform.
+            expect(engNames).toEqual([ 'ios' ]);
+            engSpec = engines.map(function(elem) {
+                delete require.cache[require.resolve(iosDirectory)];
+                iosVersion = require(iosDirectory);
+                // Config and ios/cordova/version versions "satisfy" each other.
+                expect(semver.satisfies(iosVersion.version, elem.spec)).toEqual(true);
+            });
+        }).then(function() {
+            // Add splashscreen with --save --fetch.
+            return cordova.raw.plugin('add', 'cordova-plugin-splashscreen', {'save':true, 'fetch':true});
+        }).then(function() {
+            var cfg3 = new ConfigParser(configXmlPath);
+            // Check config.xml for plugins and spec.
+            configPlugins = cfg3.getPluginIdList();
+            configPlugin = cfg3.getPlugin(configPlugins);
+            expect(configPlugins.length).toEqual(1);
+            // Splashscreen plugin and spec added.
+            expect(configPlugin.name).toEqual('cordova-plugin-splashscreen');
+            delete require.cache[require.resolve(pluginPkgJsonDir)];
+            pluginPkgJsonVersion = require(pluginPkgJsonDir);
+            // Check that version in plugin pkg.json and config version "satisfy" each other.
+            expect(semver.satisfies(pluginPkgJsonVersion.version, configPlugin.spec)).toEqual(true);
+        }).fail(function(err) {
+            expect(err).toBeUndefined();
+        }).fin(done);
+    // Cordova prepare needs extra wait time to complete.
+    },60000); 
+});
+
+// Test #022 : use basePkgJson17 (config.xml and pkg.json each have ios platform with different specs).
+describe('During add, if add specifies a platform spec, use that one regardless of what is in pkg.json or config.xml', function () {
+    var tmpDir = helpers.tmpDir('platform_test_pkgjson');
+    var project = path.join(tmpDir, 'project');
+    var results;
+
+    beforeEach(function() {
+        shell.rm('-rf', tmpDir);
+        // cp then mv because we need to copy everything, but that means it'll copy the whole directory.
+        // Using /* doesn't work because of hidden files.
+        shell.cp('-R', path.join(__dirname, 'fixtures', 'basePkgJson17'), tmpDir);
+        shell.mv(path.join(tmpDir, 'basePkgJson17'), project);
+        process.chdir(project);
+        events.on('results', function(res) { results = res; });
+    });
+
+    afterEach(function() {
+        // Delete any previous caches of require(package.json).
+        delete require.cache[require.resolve(path.join(process.cwd(),'package.json'))];
+        process.chdir(path.join(__dirname, '..'));  // Needed to rm the dir on Windows.
+        shell.rm('-rf', tmpDir);
+    });
+
+    // Factoring out some repeated checks.
+    function emptyPlatformList() {
+        return cordova.raw.platform('list').then(function() {
+            var installed = results.match(/Installed platforms:\n  (.*)/);
+            expect(installed).toBeDefined();
+            expect(installed[1].indexOf(helpers.testPlatform)).toBe(-1);
+        });
+    }
+
+    /** Test#022 : when adding with a specific platform version, always use that one
+    *   regardless of what is in package.json or config.xml.
+    */
+    it('Test#022 : when adding with a specific platform version, always use that one.', function(done) {
+        var iosPlatform = 'ios';
+        var iosVersion;
+        var cwd = process.cwd();
+        var iosDirectory = path.join(cwd, 'platforms/ios/cordova/version');
+        var configXmlPath = path.join(cwd, 'config.xml');
+        var pkgJsonPath = path.join(cwd,'package.json');
+        delete require.cache[require.resolve(pkgJsonPath)];
+        var cfg = new ConfigParser(configXmlPath);
+        var pkgJson = require(pkgJsonPath);
+        var engines = cfg.getEngines();
+        var engNames;
+        var configPlugins = cfg.getPluginIdList();
+        var configPlugin = cfg.getPlugin(configPlugins);
+        var pluginPkgJsonDir = path.join(cwd, 'plugins/cordova-plugin-splashscreen/package.json');
+        var pluginPkgJsonVersion;
+
+        // Pkg.json has ios and spec '^4.2.1'.
+        expect(pkgJson.cordova.platforms).toEqual([ iosPlatform ]);
+        expect(pkgJson.dependencies).toEqual({ 'cordova-ios' : '^4.2.1', 'cordova-plugin-splashscreen' : '~3.2.2' });
+        // Config.xml has ios and spec ~4.2.1.
+        expect(engines.length).toEqual(1);
+        expect(engines).toEqual([ { name: 'ios', spec: '~4.2.1' } ]);
+        emptyPlatformList().then(function() {
+            // Add ios with --save and --fetch.
+            return cordova.raw.platform('add', ['ios@4.3.0'], {'save':true , 'fetch':true});
+        }).then(function() {
+            // Delete any previous caches of require(package.json).
+            delete require.cache[require.resolve(pkgJsonPath)];
+            pkgJson = require(pkgJsonPath);
+            // Pkg.json has ios.
+            expect(pkgJson.cordova.platforms).toEqual([iosPlatform]);
+            // Config.xml and ios/cordova/version check.
+            var cfg2 = new ConfigParser(configXmlPath);
+            engines = cfg2.getEngines();
+            // ios platform has been added to config.xml.
+            expect(engines.length).toEqual(1);
+            engNames = engines.map(function(elem) {
+                return elem.name;
+            });
+            // Config.xml has ios platform.
+            expect(engNames).toEqual([ 'ios' ]);
+            // delete previous caches of iosVersion;
+            delete require.cache[require.resolve(iosDirectory)];
+            iosVersion = require(iosDirectory);
+            // Check that pkg.json and ios/cordova/version versions "satisfy" each other.
+            expect(semver.satisfies(iosVersion.version, pkgJson.dependencies['cordova-ios'])).toEqual(true);
+        }).then(function() {
+            // Add splashscreen with --save --fetch.
+            return cordova.raw.plugin('add', 'cordova-plugin-splashscreen@4.0.0', {'save':true, 'fetch':true});
+        }).then(function() {
+            var cfg3 = new ConfigParser(configXmlPath);
+            // Check config.xml for plugins and spec.
+            configPlugins = cfg3.getPluginIdList();
+
+            configPlugin = cfg3.getPlugin(configPlugins);
+            // Delete previous caches of pluginPkgJson.
+            delete require.cache[require.resolve(pluginPkgJsonDir)];
+            pluginPkgJsonVersion = require(pluginPkgJsonDir);
+            // Check that version in plugin pkg.json and config version "satisfy" each other.
+            expect(semver.satisfies(pluginPkgJsonVersion.version, configPlugin.spec)).toEqual(true);
+            // Delete any previous caches of require(package.json).
+            delete require.cache[require.resolve(pkgJsonPath)];
+            pkgJson = require(pkgJsonPath);
+            // Check that pkg.json and plugin pkg.json versions "satisfy".
+            expect(semver.satisfies(pluginPkgJsonVersion.version, pkgJson.dependencies['cordova-ios']));
+        }).fail(function(err) {
+            expect(err).toBeUndefined();
+        }).fin(done);
+    // Cordova prepare needs extra wait time to complete.
+    },60000); 
+});
+
+// No pkg.json included in test file.
+describe('local path is added to config.xml without pkg.json', function () {
+    var tmpDir = helpers.tmpDir('platform_test_pkgjson');
+    var project = path.join(tmpDir, 'project');
+    var results;
+    var testRunRoot = process.cwd();
+
+
+    beforeEach(function() {
+        shell.rm('-rf', tmpDir);
+
+        // cp then mv because we need to copy everything, but that means it'll copy the whole directory.
+        // Using /* doesn't work because of hidden files.
+        shell.cp('-R', path.join(__dirname, 'fixtures', 'basePkgJson13'), tmpDir);
+        shell.mv(path.join(tmpDir, 'basePkgJson13'), project);
+        process.chdir(project);
+        events.on('results', function(res) { results = res; });
+    });
+
+    afterEach(function() {
+        process.chdir(path.join(__dirname, '..'));  // Needed to rm the dir on Windows.
+        shell.rm('-rf', tmpDir);
+    });
+
+    // Test#026: has NO pkg.json. Checks if local path is added to config.xml and has no errors.
+    it('Test#026 : if you add a platform with local path, pkg.json gets updated', function (done) {
+        var cwd = process.cwd();
+        var configXmlPath = path.join(cwd, 'config.xml');
+        var cfg = new ConfigParser(configXmlPath);
+        var engines = cfg.getEngines();
+        var engNames;
+        var engSpec;
+        var platformPath = path.join(testRunRoot,'spec-cordova/fixtures/platforms/cordova-browser');
+
+        // Run cordova platform add local path --save --fetch.
+        return cordova.raw.platform('add', platformPath, {'save':true, 'fetch':true})
+        .then(function() {
+            var cfg2 = new ConfigParser(configXmlPath);
+            engines = cfg2.getEngines();
+            // ios platform and spec have been added to config.xml.
+            engNames = engines.map(function(elem) {
+                return elem.name;
+            });
+            engSpec = engines.map(function(elem) {  
+                if (elem.name === 'browser') {
+                    expect(elem.spec.includes(platformPath)).toEqual(true);
+                }
+            });
+        }).fail(function(err) {
+            expect(err).toBeUndefined();
+        }).fin(done);
+    },60000);
+
+    // Test#027: has NO pkg.json. Checks if local path is added to config.xml and has no errors.
+    it('Test#027 : if you add a plugin with local path, pkg.json gets updated', function (done) {
+        var cwd = process.cwd();
+        var pluginPath = path.join(testRunRoot,'spec-cordova/fixtures/plugins/cordova-lib-test-plugin');
+        var configXmlPath = path.join(cwd, 'config.xml');
+        var cfg = new ConfigParser(configXmlPath);
+        var configPlugins = cfg.getPluginIdList();
+        var configPlugin = cfg.getPlugin(configPlugins);
+        // Run platform add with local path.
+        return cordova.raw.plugin('add', pluginPath, {'save':true, 'fetch':true})
+        .then(function() {
+            var cfg2 = new ConfigParser(configXmlPath);
+            // Check config.xml for plugins and spec.
+            configPlugins = cfg2.getPluginIdList();
+            configPlugin = cfg2.getPlugin(configPlugins[1]);
+            // Plugin is added.
+            expect(configPlugin.name).toEqual('cordova-lib-test-plugin');
+            // Spec for geolocation plugin is added.
+            expect(configPlugin.spec.includes(pluginPath)).toEqual(true);
+        }).fail(function(err) {
+            expect(err).toBeUndefined();
+        }).fin(done);
+    },60000);
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/b3ca3001/cordova-lib/spec-cordova/platform.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/platform.spec.js b/cordova-lib/spec-cordova/platform.spec.js
index b7843ce..fd6416a 100644
--- a/cordova-lib/spec-cordova/platform.spec.js
+++ b/cordova-lib/spec-cordova/platform.spec.js
@@ -26,8 +26,6 @@ var helpers = require('./helpers'),
     cordova = require('../src/cordova/cordova'),
     plugman = require('../src/plugman/plugman'),
     rewire = require('rewire'),
-    prepare = require('../src/cordova/prepare'),
-    platforms = require('../src/platforms/platforms'),
     platform = rewire('../src/cordova/platform.js');
 
 var projectRoot = 'C:\\Projects\\cordova-projects\\move-tracker';
@@ -92,34 +90,6 @@ describe('platform end-to-end', function () {
             expect(installed[1].indexOf(helpers.testPlatform)).toBeGreaterThan(-1);
         });
     }
-    // Runs: list, add, list
-    function addPlugin(target, id, options) {
-        // Check there are no plugins yet.
-        return cordova.raw.plugin('list').then(function() {
-            expect(results).toMatch(/No plugins added/gi);
-        }).then(function() {
-            // Add a fake plugin from fixtures.
-            return cordova.raw.plugin('add', target, options);
-        }).then(function() {
-            expect(path.join(project, 'plugins', id, 'plugin.xml')).toExist();
-        }).then(function() {
-            return cordova.raw.plugin('ls');
-        }).then(function() {
-            expect(results).toContain(id);
-        });
-    }
-    // Runs: remove, list
-    function removePlugin(id) {
-        return cordova.raw.plugin('rm', id)
-        .then(function() {
-            // The whole dir should be gone.
-            expect(path.join(project, 'plugins', id)).not.toExist();
-        }).then(function() {
-            return cordova.raw.plugin('ls');
-        }).then(function() {
-            expect(results).toMatch(/No plugins added/gi);
-        });
-    }        
 
     // The flows we want to test are add, rm, list, and upgrade.
     // They should run the appropriate hooks.
@@ -132,7 +102,6 @@ describe('platform end-to-end', function () {
             // Add the testing platform.
             return cordova.raw.platform('add', [helpers.testPlatform]);
         }).then(function() {
-            console.log("!!!");
             // Check the platform add was successful.
             expect(path.join(project, 'platforms', helpers.testPlatform)).toExist();
             expect(path.join(project, 'platforms', helpers.testPlatform, 'cordova')).toExist();
@@ -148,6 +117,7 @@ describe('platform end-to-end', function () {
             // And now remove it.
             return cordova.raw.platform('rm', [helpers.testPlatform]);
         }).then(function() {
+            // It should be gone.
             expect(path.join(project, 'platforms', helpers.testPlatform)).not.toExist();
         }).then(emptyPlatformList) // platform ls should be empty too.
         .fail(function(err) {
@@ -384,3 +354,4 @@ describe('plugin add and rm end-to-end --fetch', function () {
         .fin(done);
     }, 60000);
 });
+

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/b3ca3001/cordova-lib/src/cordova/platform.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/platform.js b/cordova-lib/src/cordova/platform.js
index 445493c..78dc8d7 100644
--- a/cordova-lib/src/cordova/platform.js
+++ b/cordova-lib/src/cordova/platform.js
@@ -6,9 +6,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
@@ -85,14 +83,26 @@ function addHelper(cmd, hooksRunner, projectRoot, targets, opts) {
     .then(function() {
         
         var platformsToSave = []; 
-
-	return promiseutil.Q_chainmap(targets, function(target) {
+        // If statement to see if pkgJsonPath exists in the filesystem
+        var pkgJson;
+        var pkgJsonPath = path.join(projectRoot, 'package.json');
+        // If statement to see if pkgJsonPath exists in the filesystem
+        if(fs.existsSync(pkgJsonPath)) {
+            pkgJson = require(pkgJsonPath);
+        } else {
+            // Create package.json in cordova@7
+        }
+        
+        return promiseutil.Q_chainmap(targets, function(target) {
             // For each platform, download it and call its helper script.
             var parts = target.split('@');
             var platform = parts[0];
             var spec = parts[1];
-
+            var pkgJson;
+            var pkgJsonPath = path.join(projectRoot, 'package.json');
+            
             return Q.when().then(function() {
+                var prefixCordovaPlatform = 'cordova-'+platform;
                 if (!(platform in platforms)) {
                     spec = platform;
                     platform = null;
@@ -104,6 +114,28 @@ function addHelper(cmd, hooksRunner, projectRoot, targets, opts) {
                 if(platform === 'wp8') {
                     events.emit('warn', 'wp8 has been deprecated. Please use windows instead.');
                 }
+
+                if(spec && pkgJson && pkgJson.dependencies && (pkgJson.dependencies[prefixCordovaPlatform] || pkgJson.dependencies[platform])) {
+                    if ((semver.satisfies(spec, pkgJson.dependencies[prefixCordovaPlatform])) || (semver.satisfies(spec, pkgJson.dependencies[platform]))) {
+                    } else {
+                        if (pkgJson.dependencies[prefixCordovaPlatform]) {
+                            pkgJson.dependencies[prefixCordovaPlatform] = '^'+spec;
+                        } else if (pkgJson.dependencies[platform]) {
+                            pkgJson.dependencies[platform] = '^'+spec;
+                        }
+                        fs.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 4), 'utf8');
+                    }
+                }
+
+                // If there is no spec specified during add, use the one from pkg.json.
+                if (spec === undefined && pkgJson && pkgJson.dependencies) {
+                    if (pkgJson.dependencies[prefixCordovaPlatform]) {
+                        spec = pkgJson.dependencies[prefixCordovaPlatform];
+                    } else if (pkgJson.dependencies[platform]) {
+                        spec = pkgJson.dependencies[platform];
+                    }
+                }
+
                 if (platform && !spec && cmd == 'add') {
                     events.emit('verbose', 'No version supplied. Retrieving version from config.xml...');
                     spec = getVersionFromConfigFile(platform, cfg);
@@ -118,7 +150,14 @@ function addHelper(cmd, hooksRunner, projectRoot, targets, opts) {
                 if (spec) {
                     var maybeDir = cordova_util.fixRelativePath(spec);
                     if (cordova_util.isDirectory(maybeDir)) {
-                        return getPlatformDetailsFromDir(maybeDir, platform);
+                        if (opts.fetch) {
+                            return fetch(path.resolve(maybeDir), projectRoot, opts)
+                            .then(function (directory) {
+                                return getPlatformDetailsFromDir(directory, platform);
+                            });
+                        } else {
+                            return getPlatformDetailsFromDir(maybeDir, platform);
+                        }
                     }
                 }
                 return downloadPlatform(projectRoot, platform, spec, opts);
@@ -220,7 +259,6 @@ function addHelper(cmd, hooksRunner, projectRoot, targets, opts) {
                 .then(function() {
                     var saveVersion = !spec || semver.validRange(spec, true);
 
-
                     // Save platform@spec into platforms.json, where 'spec' is a version or a soure location. If a
                     // source location was specified, we always save that. Otherwise we save the version that was
                     // actually installed.
@@ -231,6 +269,9 @@ function addHelper(cmd, hooksRunner, projectRoot, targets, opts) {
                     if(opts.save || autosave){
                         // Similarly here, we save the source location if that was specified, otherwise the version that
                         // was installed. However, we save it with the "~" attribute (this allows for patch updates).
+                        if (spec.charAt(0) !== '~' && spec.charAt(0) !== '^') {
+                            spec = saveVersion ? '~' + platDetails.version : spec;
+                        }
                         spec = saveVersion ? '~' + platDetails.version : spec;
 
                         // Save target into config.xml, overriding already existing settings
@@ -274,7 +315,7 @@ function addHelper(cmd, hooksRunner, projectRoot, targets, opts) {
                     } 
                 });
             }
-            //save to package.json
+            // Save to package.json.
             if (modifiedPkgJson === true) {
                 pkgJson.cordova.platforms = pkgJson.cordova.platforms.sort();
                 fs.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 4), 'utf8');
@@ -438,10 +479,10 @@ function remove(hooksRunner, projectRoot, targets, opts) {
                 events.emit('log', 'Removing platform ' + target + ' from config.xml file...');
                 cfg.removeEngine(platformName);
                 cfg.write();
-                // If package.json exists and contains a specified platform in cordova.platforms, it will be removed
+                // If package.json exists and contains a specified platform in cordova.platforms, it will be removed.
                 if(pkgJson !== undefined && pkgJson.cordova !== undefined && pkgJson.cordova.platforms !== undefined) {
                     var index = pkgJson.cordova.platforms.indexOf(platformName);
-                    //Check if platform exists in platforms array
+                    // Check if platform exists in platforms array.
                     if (pkgJson.cordova.platforms !== undefined && index > -1) {
                         events.emit('log', 'Removing ' + platformName + ' from cordova.platforms array in package.json');
                         pkgJson.cordova.platforms.splice(index, 1);
@@ -449,25 +490,25 @@ function remove(hooksRunner, projectRoot, targets, opts) {
                     }
                 }
             });
-            //Write out new package.json if changes have been made
+            //Write out new package.json if changes have been made.
             if(modifiedPkgJson === true) {
                 fs.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 4), 'utf8');
             }
         }
     }).then(function() {
-        // Remove targets from platforms.json
+        // Remove targets from platforms.json.
         targets.forEach(function(target) {
             events.emit('verbose', 'Removing platform ' + target + ' from platforms.json file...');
             platformMetadata.remove(projectRoot, target);
         });
     }).then(function() {
-        //Remove from node_modules if it exists and --fetch was used
+        // Remove from node_modules if it exists and --fetch was used.
         if(opts.fetch) {
             return promiseutil.Q_chainmap(targets, function(target) {
                 if(target in platforms) {
                     target = 'cordova-'+target;
                 }
-                //edits package.json
+                // Edits package.json.
                 return npmUninstall(target, projectRoot, opts);
             });
         }

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/b3ca3001/cordova-lib/src/cordova/plugin.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/plugin.js b/cordova-lib/src/cordova/plugin.js
index c03207e..15492df 100644
--- a/cordova-lib/src/cordova/plugin.js
+++ b/cordova-lib/src/cordova/plugin.js
@@ -19,7 +19,6 @@
 
 var cordova_util  = require('./util'),
     path          = require('path'),
-    semver        = require('semver'),
     config        = require('./config'),
     Q             = require('q'),
     CordovaError  = require('cordova-common').CordovaError,
@@ -35,11 +34,11 @@ var cordova_util  = require('./util'),
     registry      = require('../plugman/registry/registry'),
     chainMap      = require('../util/promise-util').Q_chainmap,
     pkgJson       = require('../../package.json'),
+    semver        = require('semver'),
     opener        = require('opener');
 
 // For upper bounds in cordovaDependencies
 var UPPER_BOUND_REGEX = /^<\d+\.\d+\.\d+$/;
-
 // Returns a promise.
 module.exports = function plugin(command, targets, opts) {
     // CB-10519 wrap function code into promise so throwing error
@@ -96,7 +95,6 @@ module.exports = function plugin(command, targets, opts) {
                 opts.plugins.push(targets[i]);
             }
         }
-
         // Assume we don't need to run prepare by default
         var shouldRunPrepare = false;
 
@@ -227,7 +225,6 @@ module.exports = function plugin(command, targets, opts) {
                                         attributes.spec = ver;
                                     }
                                 }
-
                                 xml = cordova_util.projectConfig(projectRoot);
                                 cfg = new ConfigParser(xml);
                                 cfg.removePlugin(pluginInfo.id);
@@ -256,7 +253,6 @@ module.exports = function plugin(command, targets, opts) {
                                 pkgJson.cordova.plugins = pkgJson.cordova.plugins || {};
                                 // Plugin and variables are added.
                                 pkgJson.cordova.plugins[pluginInfo.id] = opts.cli_variables;
-
                                 events.emit('log','Adding '+pluginInfo.id+ ' to package.json');
                                 // Write to package.json
                                 fs.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 4), 'utf8');
@@ -335,7 +331,7 @@ module.exports = function plugin(command, targets, opts) {
                                 }
                                 // If package.json exists and contains a specified plugin in cordova['plugins'], it will be removed    
                                 if(pkgJson !== undefined && pkgJson.cordova !== undefined && pkgJson.cordova.plugins !== undefined) {
-                                    events.emit('log', 'Removing [' + target + '] from package.json');
+                                    events.emit('log', 'Removing '  + target +  ' from package.json');
                                     // Remove plugin from package.json
                                     delete pkgJson.cordova.plugins[target];
                                     //Write out new package.json with plugin removed correctly.
@@ -388,26 +384,54 @@ module.exports = function plugin(command, targets, opts) {
 
 function determinePluginTarget(projectRoot, cfg, target, fetchOptions) {
     var parsedSpec = pluginSpec.parse(target);
-
     var id = parsedSpec.package || target;
-
     // CB-10975 We need to resolve relative path to plugin dir from app's root before checking whether if it exists
     var maybeDir = cordova_util.fixRelativePath(id);
     if (parsedSpec.version || cordova_util.isUrl(id) || cordova_util.isDirectory(maybeDir)) {
         return Q(target);
     }
+    // Require project pkgJson.
+    var pkgJsonPath = path.join(projectRoot, 'package.json');
+    if(fs.existsSync(pkgJsonPath)) {
+        delete require.cache[require.resolve(pkgJsonPath)]; 
+        pkgJson = require(pkgJsonPath);
+    }
 
-    // If no version is specified, retrieve the version (or source) from config.xml
-    events.emit('verbose', 'No version specified for ' + parsedSpec.package + ', retrieving version from config.xml');
-    var ver = getVersionFromConfigFile(id, cfg);
+    // If no parsedSpec.version, use the one from pkg.json or config.xml.
+    if (!parsedSpec.version) {
+        // Retrieve from pkg.json.
+        if(pkgJson && pkgJson.dependencies && pkgJson.dependencies[id]) {
+            events.emit('verbose', 'No version specified for ' + id + ', retrieving version from package.json');
+            parsedSpec.version = pkgJson.dependencies[id];
+        } else {
+            // If no version is specified, retrieve the version (or source) from config.xml.
+            events.emit('verbose', 'No version specified for ' + id + ', retrieving version from config.xml');
+            parsedSpec.version = getVersionFromConfigFile(id, cfg);
+        }
+    }
+
+    // If parsedSpec.version satisfies pkgJson version, no writing to pkg.json. Only write when
+    // it does not satisfy.
+    if(parsedSpec.version) {
+        if(pkgJson && pkgJson.dependencies && pkgJson.dependencies[parsedSpec.package]) {
+            var noSymbolVersion;
+            if (parsedSpec.version.charAt(0) === '^' || parsedSpec.version.charAt(0) === '~') {
+                noSymbolVersion = parsedSpec.version.slice(1);
+            }
+            if (!semver.satisfies(noSymbolVersion, pkgJson.dependencies[parsedSpec.package])) {
+                pkgJson.dependencies[parsedSpec.package] = parsedSpec.version;
+                fs.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 4), 'utf8');
+            }
+        }
+    }
 
-    if (cordova_util.isUrl(ver) || cordova_util.isDirectory(ver) || pluginSpec.parse(ver).scope) {
-        return Q(ver);
+    if (cordova_util.isUrl(parsedSpec.version) || cordova_util.isDirectory(parsedSpec.version) || pluginSpec.parse(parsedSpec.version).scope) {
+        return Q(parsedSpec.version);
     }
 
-    // If version exists in config.xml, use that
-    if (ver) {
-        return Q(id + '@' + ver);
+    // If version exists in pkg.json or config.xml, use that.
+    if (parsedSpec.version) {
+        return Q(id + '@' + parsedSpec.version);
     }
 
     // If no version is given at all and we are fetching from npm, we

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/b3ca3001/cordova-lib/src/plugman/fetch.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/plugman/fetch.js b/cordova-lib/src/plugman/fetch.js
index 6e80c68..b55bbfc 100644
--- a/cordova-lib/src/plugman/fetch.js
+++ b/cordova-lib/src/plugman/fetch.js
@@ -36,6 +36,8 @@ var shell   = require('shelljs'),
     fetch = require('cordova-fetch'),
     cordovaUtil = require('../cordova/util');
 
+var projectRoot;
+
 // Cache of PluginInfo objects for plugins in search path.
 var localPlugins = null;
 
@@ -69,7 +71,7 @@ function fetchPlugin(plugin_src, plugins_dir, options) {
                 options.subdir = result[2];
             //if --fetch was used, throw error for subdirectories
 
-            if (options.subdir && options.subdir !== '.') {
+            if(options.subdir) {
                 events.emit('warn', 'support for subdirectories is deprecated and will be removed in Cordova@7');
                 if (options.fetch) {
                     return Q.reject(new CordovaError('--fetch does not support subdirectories'));
@@ -86,7 +88,6 @@ function fetchPlugin(plugin_src, plugins_dir, options) {
             }
         }
     }
-
     return Q.when().then(function() {
         // If it looks like a network URL, git clone it
         // skip git cloning if user passed in --fetch flag
@@ -115,19 +116,40 @@ function fetchPlugin(plugin_src, plugins_dir, options) {
                 };
             });
         }
-        // If it's not a network URL, it's either a local path or a plugin ID.
+            // If it's not a network URL, it's either a local path or a plugin ID.
         var plugin_dir = cordovaUtil.fixRelativePath(path.join(plugin_src, options.subdir));
-
         return Q.when().then(function() {
+
             if (fs.existsSync(plugin_dir)) {
-                return {
-                    pinfo: pluginInfoProvider.get(plugin_dir),
-                    fetchJsonSource: {
-                        type: 'local',
-                        path: plugin_dir
+
+                if (options.fetch) {
+                    projectRoot = path.join(plugins_dir, '..');
+                    //Plugman projects need to go up two directories to reach project root. 
+                    //Plugman projects have an options.projectRoot variable
+                    if(options.projectRoot) {
+                        projectRoot = options.projectRoot;
                     }
-                };
+                    return fetch(path.resolve(plugin_dir), projectRoot, options)
+                    .then(function(directory) {
+                        return {
+                            pinfo: pluginInfoProvider.get(directory),
+                            fetchJsonSource: {
+                                type: 'local',
+                                path: directory
+                            }
+                        };
+                    });
+                } else {
+                    return {
+                        pinfo: pluginInfoProvider.get(plugin_dir),
+                        fetchJsonSource: {
+                            type: 'local',
+                            path: plugin_dir
+                        }
+                    };
+                }
             }
+
             // If there is no such local path, it's a plugin id or id@versionspec.
             // First look for it in the local search path (if provided).
             var pinfo = findLocalPlugin(plugin_src, options.searchpath, pluginInfoProvider);
@@ -174,7 +196,7 @@ function fetchPlugin(plugin_src, plugins_dir, options) {
                     }
                     //use cordova-fetch if --fetch was passed in
                     if(options.fetch) {
-                        var projectRoot = path.join(plugins_dir, '..');
+                        projectRoot = path.join(plugins_dir, '..');
                         //Plugman projects need to go up two directories to reach project root. 
                         //Plugman projects have an options.projectRoot variable
                         if(options.projectRoot) {


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


Mime
View raw message