Repository: cordova-lib Updated Branches: refs/heads/master b82ee86c3 -> 5c8b4cac0
CB-11985 Check if cached platform/plugin exists before 'npm cache' This avoids unnecessary npm call with long timeout if not connected to the internet. Project: http://git-wip-us.apache.org/repos/asf/cordova-lib/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-lib/commit/5c8b4cac Tree: http://git-wip-us.apache.org/repos/asf/cordova-lib/tree/5c8b4cac Diff: http://git-wip-us.apache.org/repos/asf/cordova-lib/diff/5c8b4cac Branch: refs/heads/master Commit: 5c8b4cac007c21703e182978a403e67a752a9bd2 Parents: b82ee86 Author: TimBarham <tim.bar...@microsoft.com> Authored: Sat Oct 8 15:26:14 2016 +1000 Committer: TimBarham <tim.bar...@microsoft.com> Committed: Mon Oct 17 23:57:16 2016 +1000 ---------------------------------------------------------------------- cordova-lib/spec-cordova/lazy_load.spec.js | 9 +-- cordova-lib/spec-cordova/util.spec.js | 2 +- cordova-lib/src/cordova/lazy_load.js | 25 +------- cordova-lib/src/cordova/remote_load.js | 70 +---------------------- cordova-lib/src/cordova/util.js | 54 +++++++++++++---- cordova-lib/src/plugman/registry/registry.js | 21 +++---- cordova-lib/src/util/npm-helper.js | 54 +++++++++++++++++ 7 files changed, 113 insertions(+), 122 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/5c8b4cac/cordova-lib/spec-cordova/lazy_load.spec.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/lazy_load.spec.js b/cordova-lib/spec-cordova/lazy_load.spec.js index 410c99c..0560649 100644 --- a/cordova-lib/spec-cordova/lazy_load.spec.js +++ b/cordova-lib/spec-cordova/lazy_load.spec.js @@ -20,6 +20,7 @@ /* jshint sub:true */ var lazy_load = require('../src/cordova/lazy_load'), + npmHelper = require('../src/util/npm-helper'), config = require('../src/cordova/config'), shell = require('shelljs'), npm = require('npm'), @@ -31,11 +32,11 @@ var lazy_load = require('../src/cordova/lazy_load'), platforms = require('../src/platforms/platforms'); describe('lazy_load module', function() { - var custom_path, npm_cache_add, fakeLazyLoad; + var custom_path, cachePackage, fakeLazyLoad; beforeEach(function() { custom_path = spyOn(config, 'has_custom_path').andReturn(false); - npm_cache_add = spyOn(lazy_load, 'npm_cache_add').andReturn(Q(path.join('lib','dir'))); - fakeLazyLoad = function(id, platform, version) { + cachePackage = spyOn(npmHelper, 'cachePackage').andReturn(Q(path.join('lib', 'dir'))); + fakeLazyLoad = function (id, platform, version) { if (platform == 'wp7' || platform == 'wp8') { return Q(path.join('lib', 'wp', id, version, platform)); } else { @@ -63,7 +64,7 @@ describe('lazy_load module', function() { }); 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(dir) { - expect(npm_cache_add).toHaveBeenCalled(); + expect(cachePackage).toHaveBeenCalled(); expect(dir).toBeDefined(); done(); }); http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/5c8b4cac/cordova-lib/spec-cordova/util.spec.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/util.spec.js b/cordova-lib/spec-cordova/util.spec.js index e0799f7..2bcdae4 100644 --- a/cordova-lib/spec-cordova/util.spec.js +++ b/cordova-lib/spec-cordova/util.spec.js @@ -248,7 +248,7 @@ describe('util module', function() { }); it('should pick buildConfig if no option is provided, but buildConfig.json exists', function() { - spyOn(fs, 'existsSync').andReturn(true); + spyOn(util, 'existsSync').andReturn(true); // Using path.join below to normalize path separators expect(util.preProcessOptions()) .toEqual(jasmine.objectContaining({options: {buildConfig: path.join('/fake/path/build.json')}})); http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/5c8b4cac/cordova-lib/src/cordova/lazy_load.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/cordova/lazy_load.js b/cordova-lib/src/cordova/lazy_load.js index 47677b7..379f447 100644 --- a/cordova-lib/src/cordova/lazy_load.js +++ b/cordova-lib/src/cordova/lazy_load.js @@ -35,7 +35,6 @@ var path = require('path'), Q = require('q'), npm = require('npm'), npmhelper = require('../util/npm-helper'), - unpack = require('../util/unpack'), util = require('./util'), gitclone = require('../gitclone'), stubplatform = { @@ -49,7 +48,6 @@ exports.cordova = cordova; exports.cordova_git = cordova_git; exports.git_clone = git_clone_platform; exports.cordova_npm = cordova_npm; -exports.npm_cache_add = npm_cache_add; exports.custom = custom; exports.based_on_config = based_on_config; @@ -137,28 +135,7 @@ function cordova_npm(platform) { // Note that because the version of npm we use internally doesn't support caret versions, in order to allow them // from the command line and in config.xml, we use the actual version returned by getLatestMatchingNpmVersion(). - var pkg = platform.packageName + '@' + version; - return exports.npm_cache_add(pkg); - }); -} - -// Equivalent to a command like -// npm cache add cordova-android@3.5.0 -// Returns a promise that resolves to directory containing the package. -function npm_cache_add(pkg) { - var npm_cache_dir = path.join(util.libDirectory, 'npm_cache'); - var platformNpmConfig = { - cache: npm_cache_dir - }; - - return npmhelper.loadWithSettingsThenRestore(platformNpmConfig, function () { - return Q.ninvoke(npm.commands, 'cache', ['add', pkg]) - .then(function (info) { - var pkgDir = path.resolve(npm.cache, info.name, info.version, 'package'); - // Unpack the package that was added to the cache (CB-8154) - var package_tgz = path.resolve(npm.cache, info.name, info.version, 'package.tgz'); - return unpack.unpackTgz(package_tgz, pkgDir); - }); + return npmhelper.cachePackage(platform.packageName, version); }); } http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/5c8b4cac/cordova-lib/src/cordova/remote_load.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/cordova/remote_load.js b/cordova-lib/src/cordova/remote_load.js index 8d5342e..90aa0b1 100644 --- a/cordova-lib/src/cordova/remote_load.js +++ b/cordova-lib/src/cordova/remote_load.js @@ -20,9 +20,7 @@ var path = require('path'); var shell = require('shelljs'); var Q = require('q'); -var npm = require('npm'); var npmHelper = require('../util/npm-helper'); -var unpack = require('../util/unpack'); var util = require('./util'); var git = require('../gitclone'); @@ -34,72 +32,7 @@ passed containing a packageName, name, and version. options - Package options */ function npmFetch(packageName, packageVersion) { - var versionCallback; // Resultant callback - var downloadDir; // Download directory - var npmPackage; // NPM package information - - // Get the latest matching version from NPM if a version range is specified - versionCallback = util.getLatestMatchingNpmVersion(packageName, packageVersion).then( - function (latestVersion) { - downloadDir = path.join(util.libDirectory, packageName, 'cordova', latestVersion); - npmPackage = packageName + '@' + latestVersion; - - return exports.npmCacheAdd(npmPackage); - }, - function (err) { - return Q.reject(err); - } - ); - - return versionCallback; -} - -/* -Invokes "npm cache add," and then returns a promise that resolves to a -directory containing the downloaded, or cached package. NPM package information -must be passed in the form of package@version. - -npmPackage - NPM package details - */ -function npmCacheAdd(npmPackage) { - var loadCallback; // Resultant callback - var cacheAddCallback; // Callback for cache - var cacheDir; // Cache directory - var npmConfig; // NPM Configuration - var packageDir; // Downloaded package directory - var packageTGZ; // Downloaded TGZ directory - - cacheDir = path.join(util.libDirectory, 'npm_cache'); - - npmConfig = { - 'cache': cacheDir - }; - - // Load with NPM configuration - loadCallback = npmHelper.loadWithSettingsThenRestore(npmConfig, - function () { - - // Invoke NPM Cache Add - cacheAddCallback = Q.ninvoke(npm.commands, 'cache', ['add', npmPackage]).then( - function (info) { - packageDir = path.resolve(npm.cache, info.name, info.version, 'package'); - packageTGZ = path.resolve(npm.cache, info.name, info.version, 'package.tgz'); - - return unpack.unpackTgz(packageTGZ, packageDir); - }, - function (err) { - return Q.reject(err); - } - ); - - return cacheAddCallback; - }, - function (err) { - return Q.reject(err); - } - ); - - return loadCallback; + return npmHelper.fetchPackage(packageName, packageVersion); } /* @@ -143,4 +76,3 @@ function gitClone(gitURL, branch) { exports.gitClone = gitClone; exports.npmFetch = npmFetch; -exports.npmCacheAdd = npmCacheAdd; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/5c8b4cac/cordova-lib/src/cordova/util.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/cordova/util.js b/cordova-lib/src/cordova/util.js index 1dffcd8..e77ea56 100644 --- a/cordova-lib/src/cordova/util.js +++ b/cordova-lib/src/cordova/util.js @@ -75,6 +75,7 @@ exports.isUrl = isUrl; exports.getLatestMatchingNpmVersion = getLatestMatchingNpmVersion; exports.getAvailableNpmVersions = getAvailableNpmVersions; exports.getInstalledPlatformsWithVersions = getInstalledPlatformsWithVersions; +exports.existsSync = existsSync; function isUrl(value) { var u = value && url.parse(value); @@ -82,23 +83,34 @@ function isUrl(value) { } function isRootDir(dir) { - if (fs.existsSync(path.join(dir, 'www'))) { - if (fs.existsSync(path.join(dir, 'config.xml'))) { + if (exports.existsSync(path.join(dir, 'www'))) { + if (exports.existsSync(path.join(dir, 'config.xml'))) { // For sure is. - if (fs.existsSync(path.join(dir, 'platforms'))) { + if (exports.existsSync(path.join(dir, 'platforms'))) { return 2; } else { return 1; } } // Might be (or may be under platforms/). - if (fs.existsSync(path.join(dir, 'www', 'config.xml'))) { + if (exports.existsSync(path.join(dir, 'www', 'config.xml'))) { return 1; } } return 0; } +function existsSync(fileSpec) { + // Since fs.existsSync() is deprecated + try { + fs.statSync(fileSpec); + return true; + } catch (error) { + return false; + } +} + + // Runs up the directory chain looking for a .cordova directory. // IF it is found we are in a Cordova project. // Omit argument to use CWD. @@ -169,7 +181,7 @@ function fixRelativePath(value, /* optional */ cwd) { // Resolve any symlinks in order to avoid relative path issues. See https://issues.apache.org/jira/browse/CB-8757 function convertToRealPathSafe(path) { - if (path && fs.existsSync(path)) { + if (path && exports.existsSync(path)) { return fs.realpathSync(path); } @@ -192,7 +204,7 @@ function deleteSvnFolders(dir) { function listPlatforms(project_dir) { var core_platforms = require('../platforms/platforms'); var platforms_dir = path.join(project_dir, 'platforms'); - if ( !fs.existsSync(platforms_dir)) { + if ( !exports.existsSync(platforms_dir)) { return []; } var subdirs = fs.readdirSync(platforms_dir); @@ -223,7 +235,7 @@ function findPlugins(pluginPath) { var plugins = [], stats; - if (fs.existsSync(pluginPath)) { + if (exports.existsSync(pluginPath)) { plugins = fs.readdirSync(pluginPath).filter(function (fileName) { stats = fs.statSync(path.join(pluginPath, fileName)); return fileName != '.svn' && fileName != 'CVS' && stats.isDirectory(); @@ -244,9 +256,9 @@ function projectWww(projectDir) { function projectConfig(projectDir) { var rootPath = path.join(projectDir, 'config.xml'); var wwwPath = path.join(projectDir, 'www', 'config.xml'); - if (fs.existsSync(rootPath)) { + if (exports.existsSync(rootPath)) { return rootPath; - } else if (fs.existsSync(wwwPath)) { + } else if (exports.existsSync(wwwPath)) { return wwwPath; } return false; @@ -283,7 +295,7 @@ function preProcessOptions (inputOptions) { result.platforms = projectPlatforms; } - if (!result.options.buildConfig && fs.existsSync(path.join(projectRoot, 'build.json'))) { + if (!result.options.buildConfig && exports.existsSync(path.join(projectRoot, 'build.json'))) { result.options.buildConfig = path.join(projectRoot, 'build.json'); } @@ -383,6 +395,11 @@ function addModuleProperty(module, symbol, modulePath, opt_wrap, opt_obj) { * @returns {Promise} Promise for version (a valid semver version if one is found, otherwise whatever was provided). */ function getLatestMatchingNpmVersion(module_name, version) { + if (!version) { + // If no version specified, get the latest + return getLatestNpmVersion(module_name); + } + var validVersion = semver.valid(version, /* loose */ true); if (validVersion) { // This method is really intended to work with ranges, so if a version rather than a range is specified, we just @@ -417,3 +434,20 @@ function getAvailableNpmVersions(module_name) { }); }); } + +/** + * Returns a promise for the latest version available for the specified npm module. + * @param {string} module_name - npm module name. + * @returns {Promise} Promise for an array of versions. + */ +function getLatestNpmVersion(module_name) { + var npm = require('npm'); + return Q.nfcall(npm.load).then(function () { + return Q.ninvoke(npm.commands, 'view', [module_name, 'version'], /* silent = */ true).then(function (result) { + // result is an object in the form: + // {'<version>': {version: '<version>'}} + // (where <version> is the latest version) + return Object.keys(result)[0]; + }); + }); +} http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/5c8b4cac/cordova-lib/src/plugman/registry/registry.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/plugman/registry/registry.js b/cordova-lib/src/plugman/registry/registry.js index 2772524..c11eba5 100644 --- a/cordova-lib/src/plugman/registry/registry.js +++ b/cordova-lib/src/plugman/registry/registry.js @@ -20,10 +20,10 @@ /* jshint laxcomma:true */ var npm = require('npm'), - path = require('path'), Q = require('q'), npmhelper = require('../../util/npm-helper'), - events = require('cordova-common').events; + events = require('cordova-common').events, + pluginSpec = require('../../cordova/plugin_spec_parser'); module.exports = { settings: null, @@ -114,19 +114,12 @@ function initThenLoadSettingsWithRestore(promises) { } /** -* @param {Array} with one element - the plugin id or "id@version" +* @param {string} plugin - the plugin id or "id@version" * @return {Promise.<string>} Promised path to fetched package. */ function fetchPlugin(plugin) { - return initThenLoadSettingsWithRestore(function () { - events.emit('log', 'Fetching plugin "' + plugin + '" via npm'); - return Q.ninvoke(npm.commands, 'cache', ['add', plugin]) - .then(function (info) { - var unpack = require('../../util/unpack'); - var pluginDir = path.resolve(npm.cache, info.name, info.version, 'package'); - // Unpack the plugin that was added to the cache (CB-8154) - var package_tgz = path.resolve(npm.cache, info.name, info.version, 'package.tgz'); - return unpack.unpackTgz(package_tgz, pluginDir); - }); - }); + events.emit('log', 'Fetching plugin "' + plugin + '" via npm'); + var parsedSpec = pluginSpec.parse(plugin); + var scope = parsedSpec.scope || ''; + return npmhelper.fetchPackage(scope + parsedSpec.id, parsedSpec.version); } http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/5c8b4cac/cordova-lib/src/util/npm-helper.js ---------------------------------------------------------------------- diff --git a/cordova-lib/src/util/npm-helper.js b/cordova-lib/src/util/npm-helper.js index e8c5b18..4bd0ea1 100644 --- a/cordova-lib/src/util/npm-helper.js +++ b/cordova-lib/src/util/npm-helper.js @@ -20,7 +20,10 @@ // Helper methods to help keep npm operations separated. var npm = require('npm'), + path = require('path'), Q = require('q'), + unpack = require('./unpack'), + util = require('../cordova/util'), cachedSettings = null, cachedSettingsValues = null; @@ -72,4 +75,55 @@ function restoreSettings() { } } +/** + * Fetches the latest version of a package from NPM that matches the specified version. Returns a promise that + * resolves to the directory the NPM package is located in. + * @param packageName - name of an npm package + * @param packageVersion - requested version or version range + */ +function fetchPackage(packageName, packageVersion) { + // Get the latest matching version from NPM if a version range is specified + return util.getLatestMatchingNpmVersion(packageName, packageVersion).then( + function (latestVersion) { + return cachePackage(packageName, latestVersion); + } + ); +} + +/** + * Invokes "npm cache add," and then returns a promise that resolves to a directory containing the downloaded, + * or cached package. + * @param packageName - name of an npm package + * @param packageVersion - requested version (not a version range) + */ +function cachePackage(packageName, packageVersion) { + return Q().then(function () { + var cacheDir = path.join(util.libDirectory, 'npm_cache'); + + // If already cached, use that rather than calling 'npm cache add' again. + var packageCacheDir = path.resolve(cacheDir, packageName, packageVersion); + var packageTGZ = path.resolve(packageCacheDir, 'package.tgz'); + if (util.existsSync(packageTGZ)) { + return unpack.unpackTgz(packageTGZ, path.resolve(packageCacheDir, 'package')); + } + + // Load with NPM configuration + return loadWithSettingsThenRestore({'cache': cacheDir}, + function () { + // Invoke NPM Cache Add + return Q.ninvoke(npm.commands, 'cache', ['add', (packageName + '@' + packageVersion)]).then( + function (info) { + var packageDir = path.resolve(npm.cache, info.name, info.version, 'package'); + var packageTGZ = path.resolve(npm.cache, info.name, info.version, 'package.tgz'); + + return unpack.unpackTgz(packageTGZ, packageDir); + } + ); + } + ); + }); +} + module.exports.loadWithSettingsThenRestore = loadWithSettingsThenRestore; +module.exports.fetchPackage = fetchPackage; +module.exports.cachePackage = cachePackage; --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cordova.apache.org For additional commands, e-mail: commits-h...@cordova.apache.org