You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by br...@apache.org on 2013/10/23 22:17:59 UTC

git commit: [CB-4976] Don't symlink into ~/.cordova/lib for local libs

Updated Branches:
  refs/heads/master 237d0060b -> d75c0585c


[CB-4976] Don't symlink into ~/.cordova/lib for local libs

If the user specifies a local URI in his config.json, we don't want to
symlink that lib into $HOME/.cordova/lib, just use it in-place as the
source of the platform.

lazy_load calls now return a promise for the path to the target, and all
logic in other modules that was recomputing the path into the global lib
directory has been fixed to just use that return value. This is more
flexible and supports this feature nicely.


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

Branch: refs/heads/master
Commit: d75c0585c88ee9283db400f0c946027bd9d6e1ea
Parents: 237d006
Author: Braden Shepherdson <br...@gmail.com>
Authored: Tue Oct 22 13:10:51 2013 -0400
Committer: Braden Shepherdson <br...@gmail.com>
Committed: Wed Oct 23 16:15:22 2013 -0400

----------------------------------------------------------------------
 spec/create.spec.js                     |  4 +--
 spec/lazy_load.spec.js                  | 13 +++++----
 spec/metadata/android_parser.spec.js    | 15 +++-------
 spec/metadata/blackberry_parser.spec.js | 14 +++-------
 spec/metadata/ios_parser.spec.js        | 14 +++-------
 spec/metadata/windows8_parser.spec.js   | 15 +++-------
 spec/metadata/wp7_parser.spec.js        | 15 +++-------
 spec/metadata/wp8_parser.spec.js        | 15 +++-------
 spec/platform.spec.js                   | 28 +++++++++++++++----
 src/create.js                           | 41 ++++++++++++++--------------
 src/lazy_load.js                        | 20 ++++++--------
 src/metadata/android_parser.js          | 11 ++------
 src/metadata/blackberry10_parser.js     |  7 ++---
 src/metadata/firefoxos_parser.js        |  9 ++----
 src/metadata/ios_parser.js              |  8 ++----
 src/metadata/windows8_parser.js         |  7 ++---
 src/metadata/wp7_parser.js              |  8 ++----
 src/metadata/wp8_parser.js              |  7 ++---
 src/platform.js                         | 29 ++++++--------------
 src/prepare.js                          |  4 +--
 20 files changed, 110 insertions(+), 174 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/spec/create.spec.js
----------------------------------------------------------------------
diff --git a/spec/create.spec.js b/spec/create.spec.js
index 3d387fb..b4096c7 100644
--- a/spec/create.spec.js
+++ b/spec/create.spec.js
@@ -36,8 +36,8 @@ describe('create command', function () {
         config_read = spyOn(config, 'read').andReturn({});
         config_write = spyOn(config, 'write').andReturn({});
         exists = spyOn(fs, 'existsSync').andReturn(false);
-        load_cordova = spyOn(lazy_load, 'cordova').andReturn(Q());
-        load_custom = spyOn(lazy_load, 'custom').andReturn(Q());
+        load_cordova = spyOn(lazy_load, 'cordova').andReturn(Q('lib/dir'));
+        load_custom = spyOn(lazy_load, 'custom').andReturn(Q('lib/dir'));
         package = jasmine.createSpy('config.packageName');
         name = jasmine.createSpy('config.name');
         parser = spyOn(util, 'config_parser').andReturn({

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/spec/lazy_load.spec.js
----------------------------------------------------------------------
diff --git a/spec/lazy_load.spec.js b/spec/lazy_load.spec.js
index f77ab9d..44fa3c0 100644
--- a/spec/lazy_load.spec.js
+++ b/spec/lazy_load.spec.js
@@ -36,7 +36,7 @@ describe('lazy_load module', function() {
     describe('cordova method (loads stock cordova libs)', function() {
         var custom;
         beforeEach(function() {
-            custom = spyOn(lazy_load, 'custom').andReturn(Q());
+            custom = spyOn(lazy_load, 'custom').andReturn(Q('lib/dir'));
         });
         it('should throw if platform is not a stock cordova platform', function(done) {
             lazy_load.cordova('atari').then(function() {
@@ -46,8 +46,9 @@ describe('lazy_load module', function() {
             }).fin(done);
         });
         it('should invoke lazy_load.custom with appropriate url, platform, and version as specified in platforms manifest', function(done) {
-            lazy_load.cordova('android').then(function() {
+            lazy_load.cordova('android').then(function(dir) {
                 expect(custom).toHaveBeenCalledWith(platforms.android.url + ';a=snapshot;h=' + platforms.android.version + ';sf=tgz', 'cordova', 'android', platforms.android.version);
+                expect(dir).toBeDefined();
                 done();
             });
         });
@@ -147,16 +148,16 @@ describe('lazy_load module', function() {
         });
 
         describe('local paths for libraries', function() {
-            it('should symlink to local path', function(done) {
-                lazy_load.custom('/some/random/lib', 'id', 'X', 'three point five').then(function() {
-                    expect(sym).toHaveBeenCalledWith('/some/random/lib', path.join(util.libDirectory, 'X', 'id', 'three point five'), 'dir');
+            it('should return the local path, no symlink', function(done) {
+                lazy_load.custom('/some/random/lib', 'id', 'X', 'three point five').then(function(dir) {
+                    expect(dir).toEqual('/some/random/lib');
                 }, function(err) {
                     expect(err).toBeUndefined();
                 }).fin(done);
             });
             it('should fire after hook once done', function(done) {
                 lazy_load.custom('/some/random/lib', 'id', 'X', 'three point five').then(function() {
-                    expect(fire).toHaveBeenCalledWith('after_library_download', {platform:'X',url:'/some/random/lib',id:'id',version:'three point five',path:path.join(util.libDirectory, 'X', 'id', 'three point five'), symlink:true});
+                    expect(fire).toHaveBeenCalledWith('after_library_download', {platform:'X',url:'/some/random/lib',id:'id',version:'three point five',path:'/some/random/lib', symlink:false});
                 }, function(err) {
                     expect(err).toBeUndefined();
                 }).fin(done);

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/spec/metadata/android_parser.spec.js
----------------------------------------------------------------------
diff --git a/spec/metadata/android_parser.spec.js b/spec/metadata/android_parser.spec.js
index 55e431f..4afb52d 100644
--- a/spec/metadata/android_parser.spec.js
+++ b/spec/metadata/android_parser.spec.js
@@ -201,21 +201,14 @@ describe('android project parser', function() {
         });
         describe('update_www method', function() {
             it('should rm project-level www and cp in platform agnostic www', function() {
-                p.update_www();
+                p.update_www('lib/dir');
                 expect(rm).toHaveBeenCalled();
                 expect(cp).toHaveBeenCalled();
             });
-            it('should copy in a fresh cordova.js from stock cordova lib if no custom lib is specified', function() {
-                p.update_www();
+            it('should copy in a fresh cordova.js from the given cordova lib', function() {
+                p.update_www('lib/dir');
                 expect(write).toHaveBeenCalled();
-                expect(read.mostRecentCall.args[0]).toContain(util.libDirectory);
-            });
-            it('should copy in a fresh cordova.js from custom cordova lib if custom lib is specified', function() {
-                var custom_path = path.join('custom', 'path');
-                custom.andReturn(custom_path);
-                p.update_www();
-                expect(write).toHaveBeenCalled();
-                expect(read.mostRecentCall.args[0]).toContain(custom_path);
+                expect(read.mostRecentCall.args[0]).toContain('lib/dir');
             });
         });
         describe('update_overrides method', function() {

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/spec/metadata/blackberry_parser.spec.js
----------------------------------------------------------------------
diff --git a/spec/metadata/blackberry_parser.spec.js b/spec/metadata/blackberry_parser.spec.js
index eb63b79..3353eb1 100644
--- a/spec/metadata/blackberry_parser.spec.js
+++ b/spec/metadata/blackberry_parser.spec.js
@@ -180,20 +180,14 @@ describe('blackberry10 project parser', function() {
             });
 
             it('should rm project-level www and cp in platform agnostic www', function() {
-                p.update_www();
+                p.update_www('lib/dir');
                 expect(rm).toHaveBeenCalled();
                 expect(cp).toHaveBeenCalled();
                 expect(backup_cfg_parser.update).toHaveBeenCalled();
             });
-            it('should copy in a fresh cordova.js from stock cordova lib if no custom lib is specified', function() {
-                p.update_www();
-                expect(cp).toHaveBeenCalledWith('-f', path.join(util.libDirectory, 'blackberry10', 'cordova', platforms.blackberry10.version, 'javascript', 'cordova.blackberry10.js'), path.join(proj, 'platforms', 'blackberry10', 'www', 'cordova.js'));
-            });
-            it('should copy in a fresh cordova.js from custom cordova lib if custom lib is specified', function() {
-                var custom_path = '/custom/path';
-                custom.andReturn(custom_path);
-                p.update_www();
-                expect(cp).toHaveBeenCalledWith('-f', path.join(custom_path, 'javascript', 'cordova.blackberry10.js'), path.join(proj, 'platforms', 'blackberry10', 'www', 'cordova.js'));
+            it('should copy in a fresh cordova.js from given cordova lib', function() {
+                p.update_www(path.join('lib', 'dir'));
+                expect(cp).toHaveBeenCalledWith('-f', path.join('lib', 'dir', 'javascript', 'cordova.blackberry10.js'), path.join(proj, 'platforms', 'blackberry10', 'www', 'cordova.js'));
             });
         });
         describe('update_overrides method', function() {

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/spec/metadata/ios_parser.spec.js
----------------------------------------------------------------------
diff --git a/spec/metadata/ios_parser.spec.js b/spec/metadata/ios_parser.spec.js
index a39c44d..17206c6 100644
--- a/spec/metadata/ios_parser.spec.js
+++ b/spec/metadata/ios_parser.spec.js
@@ -214,19 +214,13 @@ describe('ios project parser', function () {
         });
         describe('update_www method', function() {
             it('should rm project-level www and cp in platform agnostic www', function() {
-                p.update_www();
+                p.update_www('lib/dir');
                 expect(rm).toHaveBeenCalled();
                 expect(cp).toHaveBeenCalled();
             });
-            it('should copy in a fresh cordova.js from stock cordova lib if no custom lib is specified', function() {
-                p.update_www();
-                expect(cp.mostRecentCall.args[1]).toContain(util.libDirectory);
-            });
-            it('should copy in a fresh cordova.js from custom cordova lib if custom lib is specified', function() {
-                var custom_path = path.join('custom', 'path');
-                custom.andReturn(custom_path);
-                p.update_www();
-                expect(cp.mostRecentCall.args[1]).toContain(custom_path);
+            it('should copy in a fresh cordova.js from given cordova lib', function() {
+                p.update_www('lib/dir');
+                expect(cp.mostRecentCall.args[1]).toContain('lib/dir');
             });
         });
         describe('update_overrides method', function() {

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/spec/metadata/windows8_parser.spec.js
----------------------------------------------------------------------
diff --git a/spec/metadata/windows8_parser.spec.js b/spec/metadata/windows8_parser.spec.js
index 9f1b138..5639317 100644
--- a/spec/metadata/windows8_parser.spec.js
+++ b/spec/metadata/windows8_parser.spec.js
@@ -207,21 +207,14 @@ describe('windows8 project parser', function() {
                 update_jsproj = spyOn(p, 'update_jsproj');
             });
             it('should rm project-level www and cp in platform agnostic www', function() {
-                p.update_www();
+                p.update_www('lib/dir');
                 expect(rm).toHaveBeenCalled();
                 expect(cp).toHaveBeenCalled();
             });
-            it('should copy in a fresh cordova.js from stock cordova lib if no custom lib is specified', function() {
-                p.update_www();
+            it('should copy in a fresh cordova.js from given cordova lib', function() {
+                p.update_www('lib/dir');
                 expect(write).toHaveBeenCalled();
-                expect(read.mostRecentCall.args[0]).toContain(util.libDirectory);
-            });
-            it('should copy in a fresh cordova.js from custom cordova lib if custom lib is specified', function() {
-                var custom_path = path.join('custom','path');
-                custom.andReturn(custom_path);
-                p.update_www();
-                expect(write).toHaveBeenCalled();
-                expect(read.mostRecentCall.args[0]).toContain(custom_path);
+                expect(read.mostRecentCall.args[0]).toContain('lib/dir');
             });
         });
         describe('update_staging method', function() {

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/spec/metadata/wp7_parser.spec.js
----------------------------------------------------------------------
diff --git a/spec/metadata/wp7_parser.spec.js b/spec/metadata/wp7_parser.spec.js
index 064b573..6b69d09 100644
--- a/spec/metadata/wp7_parser.spec.js
+++ b/spec/metadata/wp7_parser.spec.js
@@ -186,21 +186,14 @@ describe('wp7 project parser', function() {
                 update_csproj = spyOn(p, 'update_csproj');
             });
             it('should rm project-level www and cp in platform agnostic www', function() {
-                p.update_www();
+                p.update_www('lib/dir');
                 expect(rm).toHaveBeenCalled();
                 expect(cp).toHaveBeenCalled();
             });
-            it('should copy in a fresh cordova.js from stock cordova lib if no custom lib is specified', function() {
-                p.update_www();
+            it('should copy in a fresh cordova.js from given cordova lib', function() {
+                p.update_www('lib/dir');
                 expect(write).toHaveBeenCalled();
-                expect(read.mostRecentCall.args[0]).toContain(util.libDirectory);
-            });
-            it('should copy in a fresh cordova.js from custom cordova lib if custom lib is specified', function() {
-                var custom_path = path.join('custom', 'path');
-                custom.andReturn(custom_path);
-                p.update_www();
-                expect(write).toHaveBeenCalled();
-                expect(read.mostRecentCall.args[0]).toContain(custom_path);
+                expect(read.mostRecentCall.args[0]).toContain('lib/dir');
             });
         });
         describe('update_staging method', function() {

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/spec/metadata/wp8_parser.spec.js
----------------------------------------------------------------------
diff --git a/spec/metadata/wp8_parser.spec.js b/spec/metadata/wp8_parser.spec.js
index 5bf1057..02372cc 100644
--- a/spec/metadata/wp8_parser.spec.js
+++ b/spec/metadata/wp8_parser.spec.js
@@ -186,21 +186,14 @@ describe('wp8 project parser', function() {
                 update_csproj = spyOn(p, 'update_csproj');
             });
             it('should rm project-level www and cp in platform agnostic www', function() {
-                p.update_www();
+                p.update_www('lib/dir');
                 expect(rm).toHaveBeenCalled();
                 expect(cp).toHaveBeenCalled();
             });
-            it('should copy in a fresh cordova.js from stock cordova lib if no custom lib is specified', function() {
-                p.update_www();
+            it('should copy in a fresh cordova.js from given cordova lib', function() {
+                p.update_www('lib/dir');
                 expect(write).toHaveBeenCalled();
-                expect(read.mostRecentCall.args[0]).toContain(util.libDirectory);
-            });
-            it('should copy in a fresh cordova.js from custom cordova lib if custom lib is specified', function() {
-                var custom_path = path.join('custom','path');
-                custom.andReturn(custom_path);
-                p.update_www();
-                expect(write).toHaveBeenCalled();
-                expect(read.mostRecentCall.args[0]).toContain(custom_path);
+                expect(read.mostRecentCall.args[0]).toContain('lib/dir');
             });
         });
         describe('update_staging method', function() {

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/spec/platform.spec.js
----------------------------------------------------------------------
diff --git a/spec/platform.spec.js b/spec/platform.spec.js
index cc89eb7..e6925a2 100644
--- a/spec/platform.spec.js
+++ b/spec/platform.spec.js
@@ -54,8 +54,24 @@ describe('platform command', function() {
         list_platforms = spyOn(util, 'listPlatforms').andReturn(supported_platforms);
         util.libDirectory = path.join('HOMEDIR', '.cordova', 'lib');
         config_read = spyOn(config, 'read').andReturn({});
-        load = spyOn(lazy_load, 'based_on_config').andReturn(Q());
-        load_custom = spyOn(lazy_load, 'custom').andReturn(Q());
+
+        fakeLazyLoad = function(id, platform, version) {
+            if (platform == 'wp7' || platform == 'wp8') {
+                return Q(path.join('lib', 'wp', id, version, platform));
+            } else if (platform == 'windows8') {
+                return Q(path.join('lib', 'windows8', id, version, 'windows8'));
+            } else {
+                return Q(path.join('lib', platform, id, version));
+            }
+        };
+        lazyLoadVersion = '3.1.0';
+        load = spyOn(lazy_load, 'based_on_config').andCallFake(function(root, platform) {
+            return fakeLazyLoad('cordova', platform, lazyLoadVersion);
+        });
+        load_custom = spyOn(lazy_load, 'custom').andCallFake(function(url, id, platform, version) {
+            return fakeLazyLoad(id, platform, version);
+        });
+
         rm = spyOn(shell, 'rm');
         mkdir = spyOn(shell, 'mkdir');
         existsSync = spyOn(fs, 'existsSync').andReturn(false);
@@ -245,14 +261,14 @@ describe('platform command', function() {
             if(!require('os').platform().match(/^win/)) {
                 describe('success', function() {
                     it('should shell out to the platform update script', function(done) {
-                        var oldVersion = platforms['ios'].version;
-                        platforms['ios'].version = '1.0.0';
+                        var oldVersion = lazyLoadVersion;
+                        lazyLoadVersion = '1.0.0';
                         cordova.raw.platform('update', ['ios']).then(function() {
-                            expect(exec).toHaveBeenCalledWith('HOMEDIR/.cordova/lib/ios/cordova/1.0.0/bin/update "some/path/platforms/ios"', jasmine.any(Function));
+                            expect(exec).toHaveBeenCalledWith('lib/ios/cordova/1.0.0/bin/update "some/path/platforms/ios"', jasmine.any(Function));
                         }, function(err) {
                             expect(err).toBeUndefined();
                         }).fin(function() {
-                            platforms['ios'].version = oldVersion;
+                            lazyLoadVersion = oldVersion;
                             done();
                         });
                     });

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/src/create.js
----------------------------------------------------------------------
diff --git a/src/create.js b/src/create.js
index 9dc6eaf..1fdc271 100644
--- a/src/create.js
+++ b/src/create.js
@@ -101,8 +101,25 @@ module.exports = function create (dir, id, name, cfg) {
     // Write out .cordova/config.json file.
     var config_json = config(dir, cfg);
 
-    // Returns a promise.
-    var finalize = function(www_lib) {
+    var p;
+    if (config_json.lib && config_json.lib.www) {
+        events.emit('log', 'Using custom www assets ('+config_json.lib.www.id+').');
+        p = lazy_load.custom(config_json.lib.www.uri, config_json.lib.www.id, 'www', config_json.lib.www.version)
+        .then(function(dir) {
+            events.emit('verbose', 'Copying custom www assets into "' + www_dir + '"');
+            return dir;
+        });
+    } else {
+        // Nope, so use stock cordova-hello-world-app one.
+        events.emit('verbose', 'Using stock cordova hello-world application.');
+        p = lazy_load.cordova('www')
+        .then(function(dir) {
+            events.emit('verbose', 'Copying stock Cordova www assets into "' + www_dir + '"');
+            return dir;
+        });
+    }
+
+    return p.then(function(www_lib) {
         // Keep going into child "www" folder if exists in stock app package.
         while (fs.existsSync(path.join(www_lib, 'www'))) {
             www_lib = path.join(www_lib, 'www');
@@ -120,23 +137,5 @@ module.exports = function create (dir, id, name, cfg) {
         config.packageName(id);
         config.name(name);
         return Q();
-    };
-
-    // Check if www assets to use was overridden.
-    if (config_json.lib && config_json.lib.www) {
-        events.emit('log', 'Using custom www assets ('+config_json.lib.www.id+').');
-        return lazy_load.custom(config_json.lib.www.uri, config_json.lib.www.id, 'www', config_json.lib.www.version)
-        .then(function() {
-            events.emit('verbose', 'Copying custom www assets into "' + www_dir + '"');
-            return finalize(path.join(util.libDirectory, 'www', config_json.lib.www.id, config_json.lib.www.version));
-        });
-    } else {
-        // Nope, so use stock cordova-hello-world-app one.
-        events.emit('verbose', 'Using stock cordova hello-world application.');
-        return lazy_load.cordova('www')
-        .then(function() {
-            events.emit('verbose', 'Copying stock Cordova www assets into "' + www_dir + '"');
-            return finalize(path.join(util.libDirectory, 'www', 'cordova', platforms.www.version));
-        });
-    }
+    });
 };

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/src/lazy_load.js
----------------------------------------------------------------------
diff --git a/src/lazy_load.js b/src/lazy_load.js
index b34105d..c53e19f 100644
--- a/src/lazy_load.js
+++ b/src/lazy_load.js
@@ -23,7 +23,6 @@ var path          = require('path'),
     npm           = require('npm'),
     events        = require('./events'),
     request       = require('request'),
-    //http          = require('http'),
     config        = require('./config'),
     hooker        = require('./hooker'),
     https         = require('follow-redirects').https,
@@ -34,7 +33,7 @@ var path          = require('path'),
     util          = require('./util');
 
 module.exports = {
-    // Returns a promise.
+    // Returns a promise for the path to the lazy-loaded directory.
     cordova:function lazy_load(platform) {
         if (!(platform in platforms)) {
             return Q.reject(new Error('Cordova library "' + platform + '" not recognized.'));
@@ -43,12 +42,13 @@ module.exports = {
         var url = platforms[platform].url + ';a=snapshot;h=' + platforms[platform].version + ';sf=tgz';
         return module.exports.custom(url, 'cordova', platform, platforms[platform].version);
     },
+    // Returns a promise for the path to the lazy-loaded directory.
     custom:function(url, id, platform, version) {
         var download_dir = (platform == 'wp7' || platform == 'wp8' ? path.join(util.libDirectory, 'wp', id, version) :
                                                                      path.join(util.libDirectory, platform, id, version));
         if (fs.existsSync(download_dir)) {
             events.emit('verbose', id + ' library for "' + platform + '" already exists. No need to download. Continuing.');
-            return Q();
+            return Q(download_dir);
         }
         events.emit('log', 'Downloading ' + id + ' library for ' + platform + '...');
         return hooker.fire('before_library_download', {
@@ -113,24 +113,22 @@ module.exports = {
                     });
                 });
             } else {
-                // local path
-                // symlink instead of copying
-                // TODO: Unixy platforms only! We should fall back to copying on Windows.
-                shell.mkdir('-p', path.join(download_dir, '..'));
-                fs.symlinkSync((uri.protocol && uri.protocol[1] == ':' ? uri.href : uri.path), download_dir, 'dir');
+                // Local path.
+                // Do nothing here; users of this code should be using the returned path.
+                download_dir = uri.protocol && uri.protocol[1] == ':' ? uri.href : uri.path;
                 d.resolve(hooker.fire('after_library_download', {
                     platform:platform,
                     url:url,
                     id:id,
                     version:version,
                     path:download_dir,
-                    symlink:true
+                    symlink:false
                 }));
             }
-            return d.promise;
+            return d.promise.then(function() { return download_dir; });
         });
     },
-    // Returns a promise.
+    // Returns a promise for the path to the lazy-loaded directory.
     based_on_config:function(project_root, platform) {
         var custom_path = config.has_custom_path(project_root, platform);
         if (custom_path) {

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/src/metadata/android_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/android_parser.js b/src/metadata/android_parser.js
index cb4bbb0..df446e1 100644
--- a/src/metadata/android_parser.js
+++ b/src/metadata/android_parser.js
@@ -132,7 +132,8 @@ module.exports.prototype = {
         return this.android_config;
     },
 
-    update_www:function() {
+    // Takes the directory where the lazy-loaded platform can be found.
+    update_www:function(libDir) {
         var projectRoot = util.isCordova(this.path);
         var www = util.projectWww(projectRoot);
         var platformWww = path.join(this.path, 'assets');
@@ -142,13 +143,7 @@ module.exports.prototype = {
         shell.cp('-rf', www, platformWww);
 
         // write out android lib's cordova.js
-        var custom_path = project_config.has_custom_path(projectRoot, 'android');
-        var jsPath;
-        if (custom_path) {
-            jsPath = path.resolve(path.join(custom_path, 'framework', 'assets', 'www', 'cordova.js'));
-        } else {
-            jsPath = path.join(util.libDirectory, 'android', 'cordova', require('../../platforms').android.version, 'framework', 'assets', 'www', 'cordova.js');
-        }
+        var jsPath = path.resolve(path.join(libDir, 'framework', 'assets', 'www', 'cordova.js'));
         fs.writeFileSync(path.join(this.www_dir(), 'cordova.js'), fs.readFileSync(jsPath, 'utf-8'), 'utf-8');
     },
 

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/src/metadata/blackberry10_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/blackberry10_parser.js b/src/metadata/blackberry10_parser.js
index da8c40e..d9f71f3 100644
--- a/src/metadata/blackberry10_parser.js
+++ b/src/metadata/blackberry10_parser.js
@@ -83,7 +83,7 @@ module.exports.prototype = {
         return this.config_path;
     },
 
-    update_www:function() {
+    update_www:function(libDir) {
         var projectRoot = util.isCordova(this.path),
             www = util.projectWww(projectRoot),
             platformWww = this.www_dir(),
@@ -97,11 +97,8 @@ module.exports.prototype = {
         //Re-Write config.xml
         platform_cfg_backup.update();
 
-        var custom_path = config.has_custom_path(projectRoot, 'blackberry10');
-        var lib_path = path.join(util.libDirectory, 'blackberry10', 'cordova', require('../../platforms').blackberry10.version);
-        if (custom_path) lib_path = custom_path;
         // add cordova.js
-        shell.cp('-f', path.join(lib_path, 'javascript', 'cordova.blackberry10.js'), path.join(this.www_dir(), 'cordova.js'));
+        shell.cp('-f', path.join(libDir, 'javascript', 'cordova.blackberry10.js'), path.join(this.www_dir(), 'cordova.js'));
     },
 
     // update the overrides folder into the www folder

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/src/metadata/firefoxos_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/firefoxos_parser.js b/src/metadata/firefoxos_parser.js
index 31cd01f..c3edd7b 100644
--- a/src/metadata/firefoxos_parser.js
+++ b/src/metadata/firefoxos_parser.js
@@ -70,7 +70,7 @@ module.exports.prototype = {
         return path.join(this.path, 'www');
     },
 
-    update_www: function() {
+    update_www: function(libDir) {
         var projectRoot = util.isCordova(this.path);
         var projectWww = util.projectWww(projectRoot);
         var platformWww = this.www_dir();
@@ -78,13 +78,8 @@ module.exports.prototype = {
         shell.rm('-rf', platformWww);
         shell.cp('-rf', projectWww, this.path);
 
-        var customPath = config.has_custom_path(projectRoot, 'firefoxos');
-        var libPath = (customPath ?
-                       customPath :
-                       path.join(util.libDirectory, 'firefoxos', 'cordova',
-                                 require('../../platforms').ios.version));
         shell.cp('-f',
-                 path.join(libPath, 'cordova-lib', 'cordova.js'),
+                 path.join(libDir, 'cordova-lib', 'cordova.js'),
                  path.join(platformWww, 'cordova.js'));
     },
 

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/src/metadata/ios_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/ios_parser.js b/src/metadata/ios_parser.js
index f552227..20e985c 100644
--- a/src/metadata/ios_parser.js
+++ b/src/metadata/ios_parser.js
@@ -157,7 +157,7 @@ module.exports.prototype = {
         return this.config_path;
     },
 
-    update_www:function() {
+    update_www:function(libDir) {
         var projectRoot = util.isCordova(this.path);
         var www = util.projectWww(projectRoot);
         var project_www = this.www_dir();
@@ -169,11 +169,7 @@ module.exports.prototype = {
         shell.cp('-rf', www, this.path);
 
         // write out proper cordova.js
-        var custom_path = config.has_custom_path(projectRoot, 'ios');
-        var lib_path = path.join(util.libDirectory, 'ios', 'cordova', require('../../platforms').ios.version);
-        if (custom_path) lib_path = custom_path;
-        shell.cp('-f', path.join(lib_path, 'CordovaLib', 'cordova.js'), path.join(project_www, 'cordova.js'));
-
+        shell.cp('-f', path.join(libDir, 'CordovaLib', 'cordova.js'), path.join(project_www, 'cordova.js'));
     },
 
     // update the overrides folder into the www folder

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/src/metadata/windows8_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/windows8_parser.js b/src/metadata/windows8_parser.js
index 120faef..68520fc 100644
--- a/src/metadata/windows8_parser.js
+++ b/src/metadata/windows8_parser.js
@@ -144,7 +144,7 @@ module.exports.prototype = {
         }
     },
     // copies the app www folder into the windows8 project's www folder and updates the jsproj file.
-    update_www:function() {
+    update_www:function(libDir) {
         var project_root = util.isCordova(this.windows8_proj_dir);
         var project_www = util.projectWww(project_root);
         // remove stock platform assets
@@ -156,10 +156,7 @@ module.exports.prototype = {
         this.copy_merges('windows8');
 
         // copy over windows8 lib's cordova.js
-        var lib_path = path.join(util.libDirectory, 'windows8', 'cordova', require('../../platforms').windows8.version);
-        var custom_path = config.has_custom_path(project_root, 'windows8');
-        if (custom_path) lib_path = custom_path;
-        var cordovajs_path = path.join(lib_path, 'windows8', "template", 'www', 'cordova.js');
+        var cordovajs_path = path.join(libDir, 'windows8', "template", 'www', 'cordova.js');
         fs.writeFileSync(path.join(this.www_dir(), 'cordova.js'), fs.readFileSync(cordovajs_path, 'utf-8'), 'utf-8');
         this.update_jsproj();
     },

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/src/metadata/wp7_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/wp7_parser.js b/src/metadata/wp7_parser.js
index 508ca5d..b19dc32 100644
--- a/src/metadata/wp7_parser.js
+++ b/src/metadata/wp7_parser.js
@@ -152,7 +152,7 @@ module.exports.prototype = {
         }
     },
     // copies the app www folder into the wp7 project's www folder and updates the csproj file.
-    update_www:function() {
+    update_www:function(libDir) {
         var project_root = util.isCordova(this.wp7_proj_dir);
         var project_www = util.projectWww(project_root);
         // remove stock platform assets
@@ -165,10 +165,8 @@ module.exports.prototype = {
         this.copy_merges('wp7');
 
         // copy over wp7 lib's cordova.js
-        var lib_path = path.join(util.libDirectory, 'wp', 'cordova', require('../../platforms').wp7.version);
-        var custom_path = config.has_custom_path(project_root, 'wp7');
-        if (custom_path) lib_path = custom_path;
-        var cordovajs_path = path.join(lib_path, 'common', 'www', 'cordova.js');
+
+        var cordovajs_path = path.join(libDir, 'common', 'www', 'cordova.js');
         fs.writeFileSync(path.join(this.www_dir(), 'cordova.js'), fs.readFileSync(cordovajs_path, 'utf-8'), 'utf-8');
 
     },

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/src/metadata/wp8_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/wp8_parser.js b/src/metadata/wp8_parser.js
index 2274b7e..3bdef16 100644
--- a/src/metadata/wp8_parser.js
+++ b/src/metadata/wp8_parser.js
@@ -155,7 +155,7 @@ module.exports.prototype = {
         }
     },
     // copies the app www folder into the wp8 project's www folder and updates the csproj file.
-    update_www:function() {
+    update_www:function(libDir) {
         var project_root = util.isCordova(this.wp8_proj_dir);
         var project_www = util.projectWww(project_root);
         // remove stock platform assets
@@ -168,10 +168,7 @@ module.exports.prototype = {
         this.copy_merges('wp8');
 
         // copy over wp8 lib's cordova.js
-        var lib_path = path.join(util.libDirectory, 'wp', 'cordova', require('../../platforms').wp8.version);
-        var custom_path = config.has_custom_path(project_root, 'wp8');
-        if (custom_path) lib_path = custom_path;
-        var cordovajs_path = path.join(lib_path, 'common', 'www', 'cordova.js');
+        var cordovajs_path = path.join(libDir, 'common', 'www', 'cordova.js');
         fs.writeFileSync(path.join(this.www_dir(), 'cordova.js'), fs.readFileSync(cordovajs_path, 'utf-8'), 'utf-8');
         this.update_csproj();
     },

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/src/platform.js
----------------------------------------------------------------------
diff --git a/src/platform.js b/src/platform.js
index 60fb6e6..65c533c 100644
--- a/src/platform.js
+++ b/src/platform.js
@@ -71,12 +71,9 @@ module.exports = function platform(command, targets) {
                 return targets.reduce(function(soFar, t) {
                     return soFar.then(function() {
                         return lazy_load.based_on_config(projectRoot, t)
-                        .then(function() {
-                            if (config_json.lib && config_json.lib[t]) {
-                                return call_into_create(t, projectRoot, cfg, config_json.lib[t].id, config_json.lib[t].version, config_json.lib[t].template);
-                            } else {
-                                return call_into_create(t, projectRoot, cfg, 'cordova', platforms[t].version, null);
-                            }
+                        .then(function(libDir) {
+                            var template = config_json.lib && config_json.lib[t] && config_json.lib[t].template || null;
+                            return call_into_create(t, projectRoot, cfg, libDir, template);
                         }, function(err) {
                             throw new Error('Unable to fetch platform ' + t + ': ' + err);
                         });
@@ -122,9 +119,8 @@ module.exports = function platform(command, targets) {
                 return hooks.fire('before_platform_update', opts)
                 .then(function() {
                     return lazy_load.based_on_config(projectRoot, plat);
-                }).then(function() {
-                    var platDir = plat == 'wp7' || plat == 'wp8' ? 'wp' : plat;
-                    var script = path.join(cordova_util.libDirectory, platDir, 'cordova', platforms[plat].version, 'bin', 'update');
+                }).then(function(libDir) {
+                    var script = path.join(libDir, 'bin', 'update');
                     var d = Q.defer();
                     child_process.exec(script + ' "' + path.join(projectRoot, 'platforms', plat) + '"', function(err, stdout, stderr) {
                         if (err) {
@@ -219,7 +215,7 @@ function createOverrides(projectRoot, target) {
 };
 
 // Returns a promise.
-function call_into_create(target, projectRoot, cfg, id, version, template_dir) {
+function call_into_create(target, projectRoot, cfg, libDir, template_dir) {
     var output = path.join(projectRoot, 'platforms', target);
 
     // Check if output directory already exists.
@@ -232,16 +228,7 @@ function call_into_create(target, projectRoot, cfg, id, version, template_dir) {
         .then(function() {
             // Create a platform app using the ./bin/create scripts that exist in each repo.
             // Run platform's create script
-            var bin = path.join(cordova_util.libDirectory, target, id, version, 'bin', 'create');
-            if(target == 'wp7') {
-                bin = path.join(cordova_util.libDirectory, 'wp', id, version, 'wp7', 'bin', 'create');
-            }
-            else if(target == 'wp8') {
-                bin = path.join(cordova_util.libDirectory, 'wp', id, version, 'wp8', 'bin', 'create');
-            }
-            else if(target == 'windows8') {
-                bin = path.join(cordova_util.libDirectory, 'windows8', id, version, 'windows8', 'bin', 'create');
-            }
+            var bin = path.join(libDir, 'bin', 'create');
             var args = (target=='ios') ? '--arc' : '';
             var pkg = cfg.packageName().replace(/[^\w.]/g,'_');
             var name = cfg.name();
@@ -256,7 +243,7 @@ function call_into_create(target, projectRoot, cfg, id, version, template_dir) {
             child_process.exec(command, function(err, create_output, stderr) {
                 events.emit('verbose', create_output);
                 if (err) {
-                    d.reject(new Error('An error occured during creation of ' + target + ' sub-project. ' + create_output));
+                    d.reject(new Error('An error occured during creation of ' + target + ' sub-project. ' + create_output + '\n' + stderr));
                 } else {
                     d.resolve(require('../cordova').raw.prepare(target));
                 }

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d75c0585/src/prepare.js
----------------------------------------------------------------------
diff --git a/src/prepare.js b/src/prepare.js
index 738445c..4ea22c5 100644
--- a/src/prepare.js
+++ b/src/prepare.js
@@ -67,7 +67,7 @@ module.exports = function prepare(options) {
         return Q.all(options.platforms.map(function(platform) {
             var platformPath = path.join(projectRoot, 'platforms', platform);
             return lazy_load.based_on_config(projectRoot, platform)
-            .then(function() {
+            .then(function(libDir) {
                 var parser = new platforms[platform].parser(platformPath),
                     defaults_xml_path = path.join(platformPath, "cordova", "defaults.xml");
                 //If defaults.xml is present, overwrite platform config.xml with it
@@ -85,7 +85,7 @@ module.exports = function prepare(options) {
                 }
 
                 // Replace the existing web assets with the app master versions
-                parser.update_www();
+                parser.update_www(libDir);
 
                 // Call plugman --prepare for this platform. sets up js-modules appropriately.
                 var plugins_dir = path.join(projectRoot, 'plugins');