mirror of
https://github.com/apache/cordova-android.git
synced 2025-02-26 03:53:09 +08:00
CB-11138 Reuse PluginManager from common to add/rm plugins
This closes #301
This commit is contained in:
parent
dc6384d063
commit
d351e316bf
224
bin/templates/cordova/Api.js
vendored
224
bin/templates/cordova/Api.js
vendored
@ -17,19 +17,11 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var Q = require('q');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var shell = require('shelljs');
|
||||
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
var PlatformJson = require('cordova-common').PlatformJson;
|
||||
var ActionStack = require('cordova-common').ActionStack;
|
||||
var AndroidProject = require('./lib/AndroidProject');
|
||||
var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
|
||||
var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
|
||||
var PluginManager = require('cordova-common').PluginManager;
|
||||
|
||||
var pluginHandlers = require('./lib/pluginHandlers');
|
||||
var CordovaLogger = require('cordova-common').CordovaLogger;
|
||||
var selfEvents = require('cordova-common').events;
|
||||
|
||||
@ -65,10 +57,6 @@ function Api(platform, platformRootDir, events) {
|
||||
|
||||
setupEvents(events);
|
||||
|
||||
this._platformJson = PlatformJson.load(this.root, platform);
|
||||
this._pluginInfoProvider = new PluginInfoProvider();
|
||||
this._munger = new PlatformMunger(this.platform, this.root, this._platformJson, this._pluginInfoProvider);
|
||||
|
||||
var self = this;
|
||||
|
||||
this.locations = {
|
||||
@ -197,59 +185,25 @@ Api.prototype.prepare = function (cordovaProject) {
|
||||
* CordovaError instance.
|
||||
*/
|
||||
Api.prototype.addPlugin = function (plugin, installOptions) {
|
||||
|
||||
if (!plugin || plugin.constructor.name !== 'PluginInfo')
|
||||
return Q.reject(new CordovaError('The parameter is incorrect. The first parameter to addPlugin should be a PluginInfo instance'));
|
||||
var project = AndroidProject.getProjectFile(this.root);
|
||||
|
||||
installOptions = installOptions || {};
|
||||
installOptions.variables = installOptions.variables || {};
|
||||
// Add PACKAGE_NAME variable into vars
|
||||
if (!installOptions.variables.PACKAGE_NAME) {
|
||||
installOptions.variables.PACKAGE_NAME = project.getPackageName();
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var actions = new ActionStack();
|
||||
var project = AndroidProject.getProjectFile(this.root);
|
||||
return PluginManager.get(this.platform, this.locations, project)
|
||||
.addPlugin(plugin, installOptions)
|
||||
.then(function () {
|
||||
if (plugin.getFrameworks(this.platform).length === 0) return;
|
||||
|
||||
// gather all files needs to be handled during install
|
||||
plugin.getFilesAndFrameworks(this.platform)
|
||||
.concat(plugin.getAssets(this.platform))
|
||||
.concat(plugin.getJsModules(this.platform))
|
||||
.forEach(function(item) {
|
||||
actions.push(actions.createAction(
|
||||
pluginHandlers.getInstaller(item.itemType), [item, plugin, project, installOptions],
|
||||
pluginHandlers.getUninstaller(item.itemType), [item, plugin, project, installOptions]));
|
||||
});
|
||||
|
||||
// run through the action stack
|
||||
return actions.process(this.platform)
|
||||
.then(function () {
|
||||
if (project) {
|
||||
project.write();
|
||||
}
|
||||
|
||||
// Add PACKAGE_NAME variable into vars
|
||||
if (!installOptions.variables.PACKAGE_NAME) {
|
||||
installOptions.variables.PACKAGE_NAME = project.getPackageName();
|
||||
}
|
||||
|
||||
self._munger
|
||||
// Ignore passed `is_top_level` option since platform itself doesn't know
|
||||
// anything about managing dependencies - it's responsibility of caller.
|
||||
.add_plugin_changes(plugin, installOptions.variables, /*is_top_level=*/true, /*should_increment=*/true)
|
||||
.save_all();
|
||||
|
||||
if (plugin.getFrameworks(self.platform).length > 0) {
|
||||
selfEvents.emit('verbose', 'Updating build files since android plugin contained <framework>');
|
||||
require('./lib/builders/builders').getBuilder('gradle').prepBuildFiles();
|
||||
}
|
||||
|
||||
var targetDirs = [self.locations.www];
|
||||
// CB-11022 if usePlatformWww is specified we need to mirror modules metadata to both directories
|
||||
if (installOptions.usePlatformWww) targetDirs.push(self.locations.platformWww);
|
||||
self._addModulesInfo(plugin, targetDirs);
|
||||
|
||||
// CB-11022 Indicate to caller that we have copied js-files and assets
|
||||
// to both 'www' and 'platform_www' so prepare is not needed
|
||||
return true;
|
||||
});
|
||||
}.bind(this))
|
||||
// CB-11022 Return truthy value to prevent running prepare after
|
||||
.thenResolve(true);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -266,51 +220,17 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
|
||||
* CordovaError instance.
|
||||
*/
|
||||
Api.prototype.removePlugin = function (plugin, uninstallOptions) {
|
||||
|
||||
if (!plugin || plugin.constructor.name !== 'PluginInfo')
|
||||
return Q.reject(new CordovaError('The parameter is incorrect. The first parameter to addPlugin should be a PluginInfo instance'));
|
||||
|
||||
var self = this;
|
||||
var actions = new ActionStack();
|
||||
var project = AndroidProject.getProjectFile(this.root);
|
||||
return PluginManager.get(this.platform, this.locations, project)
|
||||
.removePlugin(plugin, uninstallOptions)
|
||||
.then(function () {
|
||||
if (plugin.getFrameworks(this.platform).length === 0) return;
|
||||
|
||||
// queue up plugin files
|
||||
plugin.getFilesAndFrameworks(this.platform)
|
||||
.concat(plugin.getAssets(this.platform))
|
||||
.concat(plugin.getJsModules(this.platform))
|
||||
.forEach(function(item) {
|
||||
actions.push(actions.createAction(
|
||||
pluginHandlers.getUninstaller(item.itemType), [item, plugin, project, uninstallOptions],
|
||||
pluginHandlers.getInstaller(item.itemType), [item, plugin, project, uninstallOptions]));
|
||||
});
|
||||
|
||||
// run through the action stack
|
||||
return actions.process(this.platform)
|
||||
.then(function() {
|
||||
if (project) {
|
||||
project.write();
|
||||
}
|
||||
|
||||
self._munger
|
||||
// Ignore passed `is_top_level` option since platform itself doesn't know
|
||||
// anything about managing dependencies - it's responsibility of caller.
|
||||
.remove_plugin_changes(plugin, /*is_top_level=*/true)
|
||||
.save_all();
|
||||
|
||||
if (plugin.getFrameworks(self.platform).length > 0) {
|
||||
selfEvents.emit('verbose', 'Updating build files since android plugin contained <framework>');
|
||||
this.events.emit('verbose', 'Updating build files since android plugin contained <framework>');
|
||||
require('./lib/builders/builders').getBuilder('gradle').prepBuildFiles();
|
||||
}
|
||||
|
||||
var targetDirs = [self.locations.www];
|
||||
// CB-11022 if usePlatformWww is specified we need to mirror modules metadata to both directories
|
||||
if (uninstallOptions.usePlatformWww) targetDirs.push(self.locations.platformWww);
|
||||
self._removeModulesInfo(plugin, targetDirs);
|
||||
|
||||
// CB-11022 Indicate to caller that we have copied js-files and assets
|
||||
// to both 'www' and 'platform_www' so prepare is not needed
|
||||
return true;
|
||||
});
|
||||
}.bind(this))
|
||||
// CB-11022 Return truthy value to prevent running prepare after
|
||||
.thenResolve(true);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -424,105 +344,3 @@ Api.prototype.requirements = function() {
|
||||
};
|
||||
|
||||
module.exports = Api;
|
||||
|
||||
/**
|
||||
* Removes the specified modules from list of installed modules and updates
|
||||
* platform_json and cordova_plugins.js on disk.
|
||||
*
|
||||
* @param {PluginInfo} plugin PluginInfo instance for plugin, which modules
|
||||
* needs to be added.
|
||||
* @param {String[]} targetDirs The directories, where updated cordova_plugins.js
|
||||
* should be written to.
|
||||
*/
|
||||
Api.prototype._addModulesInfo = function(plugin, targetDirs) {
|
||||
var installedModules = this._platformJson.root.modules || [];
|
||||
|
||||
var installedPaths = installedModules.map(function (installedModule) {
|
||||
return installedModule.file;
|
||||
});
|
||||
|
||||
var modulesToInstall = plugin.getJsModules(this.platform)
|
||||
.filter(function (moduleToInstall) {
|
||||
return installedPaths.indexOf(moduleToInstall.file) === -1;
|
||||
}).map(function (moduleToInstall) {
|
||||
var moduleName = plugin.id + '.' + ( moduleToInstall.name || moduleToInstall.src.match(/([^\/]+)\.js/)[1] );
|
||||
var obj = {
|
||||
file: ['plugins', plugin.id, moduleToInstall.src].join('/'),
|
||||
id: moduleName
|
||||
};
|
||||
if (moduleToInstall.clobbers.length > 0) {
|
||||
obj.clobbers = moduleToInstall.clobbers.map(function(o) { return o.target; });
|
||||
}
|
||||
if (moduleToInstall.merges.length > 0) {
|
||||
obj.merges = moduleToInstall.merges.map(function(o) { return o.target; });
|
||||
}
|
||||
if (moduleToInstall.runs) {
|
||||
obj.runs = true;
|
||||
}
|
||||
|
||||
return obj;
|
||||
});
|
||||
|
||||
this._platformJson.root.modules = installedModules.concat(modulesToInstall);
|
||||
if (!this._platformJson.root.plugin_metadata) {
|
||||
this._platformJson.root.plugin_metadata = {};
|
||||
}
|
||||
this._platformJson.root.plugin_metadata[plugin.id] = plugin.version;
|
||||
|
||||
this._writePluginModules(targetDirs);
|
||||
this._platformJson.save();
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the specified modules from list of installed modules and updates
|
||||
* platform_json and cordova_plugins.js on disk.
|
||||
*
|
||||
* @param {PluginInfo} plugin PluginInfo instance for plugin, which modules
|
||||
* needs to be removed.
|
||||
* @param {String[]} targetDirs The directories, where updated cordova_plugins.js
|
||||
* should be written to.
|
||||
*/
|
||||
Api.prototype._removeModulesInfo = function(plugin, targetDirs) {
|
||||
var installedModules = this._platformJson.root.modules || [];
|
||||
var modulesToRemove = plugin.getJsModules(this.platform)
|
||||
.map(function (jsModule) {
|
||||
return ['plugins', plugin.id, jsModule.src].join('/');
|
||||
});
|
||||
|
||||
var updatedModules = installedModules
|
||||
.filter(function (installedModule) {
|
||||
return (modulesToRemove.indexOf(installedModule.file) === -1);
|
||||
});
|
||||
|
||||
this._platformJson.root.modules = updatedModules;
|
||||
if (this._platformJson.root.plugin_metadata) {
|
||||
delete this._platformJson.root.plugin_metadata[plugin.id];
|
||||
}
|
||||
|
||||
this._writePluginModules(targetDirs);
|
||||
this._platformJson.save();
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetches all installed modules, generates cordova_plugins contents and writes
|
||||
* it to cordova_plugins.js file at specified directories.
|
||||
*
|
||||
* @param {String[]} targetDirs Directories, where write cordova_plugins.js to.
|
||||
* Ususally it is either <platform>/www or <platform>/platform_www or both.
|
||||
*/
|
||||
Api.prototype._writePluginModules = function (targetDirs) {
|
||||
// Write out moduleObjects as JSON wrapped in a cordova module to cordova_plugins.js
|
||||
var final_contents = 'cordova.define(\'cordova/plugin_list\', function(require, exports, module) {\n';
|
||||
final_contents += 'module.exports = ' + JSON.stringify(this._platformJson.root.modules, null, ' ') + ';\n';
|
||||
final_contents += 'module.exports.metadata = \n';
|
||||
final_contents += '// TOP OF METADATA\n';
|
||||
|
||||
final_contents += JSON.stringify(this._platformJson.root.plugin_metadata, null, 4) + ';\n';
|
||||
final_contents += '// BOTTOM OF METADATA\n';
|
||||
final_contents += '});'; // Close cordova.define.
|
||||
|
||||
targetDirs.forEach(function (targetDir) {
|
||||
shell.mkdir('-p', targetDir);
|
||||
fs.writeFileSync(path.join(targetDir, 'cordova_plugins.js'), final_contents, 'utf-8');
|
||||
});
|
||||
};
|
||||
|
9
bin/templates/cordova/lib/AndroidProject.js
vendored
9
bin/templates/cordova/lib/AndroidProject.js
vendored
@ -21,6 +21,7 @@ var fs = require('fs');
|
||||
var path = require('path');
|
||||
var properties_parser = require('properties-parser');
|
||||
var AndroidManifest = require('./AndroidManifest');
|
||||
var pluginHandlers = require('./pluginHandlers');
|
||||
|
||||
var projectFileCache = {};
|
||||
|
||||
@ -180,5 +181,13 @@ AndroidProject.prototype._getPropertiesFile = function (filename) {
|
||||
return this._propertiesEditors[filename];
|
||||
};
|
||||
|
||||
AndroidProject.prototype.getInstaller = function (type) {
|
||||
return pluginHandlers.getInstaller(type);
|
||||
};
|
||||
|
||||
AndroidProject.prototype.getUninstaller = function (type) {
|
||||
return pluginHandlers.getUninstaller(type);
|
||||
};
|
||||
|
||||
|
||||
module.exports = AndroidProject;
|
||||
|
9
bin/templates/cordova/lib/prepare.js
vendored
9
bin/templates/cordova/lib/prepare.js
vendored
@ -26,13 +26,18 @@ var AndroidManifest = require('./AndroidManifest');
|
||||
var xmlHelpers = require('cordova-common').xmlHelpers;
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
var ConfigParser = require('cordova-common').ConfigParser;
|
||||
var PlatformJson = require('cordova-common').PlatformJson;
|
||||
var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
|
||||
var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
|
||||
|
||||
module.exports.prepare = function (cordovaProject) {
|
||||
|
||||
var self = this;
|
||||
|
||||
this._config = updateConfigFilesFrom(cordovaProject.projectConfig,
|
||||
this._munger, this.locations);
|
||||
var platformJson = PlatformJson.load(this.locations.root, this.platform);
|
||||
var munger = new PlatformMunger(this.platform, this.locations.root, platformJson, new PluginInfoProvider());
|
||||
|
||||
this._config = updateConfigFilesFrom(cordovaProject.projectConfig, munger, this.locations);
|
||||
|
||||
// Update own www dir with project's www assets and plugins' assets and js-files
|
||||
return Q.when(updateWwwFrom(cordovaProject, this.locations))
|
||||
|
@ -36,20 +36,16 @@ describe('addPlugin method', function () {
|
||||
var api, fail, gradleBuilder;
|
||||
|
||||
beforeEach(function() {
|
||||
var ActionStack = jasmine.createSpyObj('ActionStack', ['createAction', 'push', 'process']);
|
||||
ActionStack.process.andReturn(Q());
|
||||
spyOn(common, 'ActionStack').andReturn(ActionStack);
|
||||
var pluginManager = jasmine.createSpyObj('pluginManager', ['addPlugin']);
|
||||
pluginManager.addPlugin.andReturn(Q());
|
||||
spyOn(common.PluginManager, 'get').andReturn(pluginManager);
|
||||
|
||||
spyOn(AndroidProject, 'getProjectFile')
|
||||
.andReturn(jasmine.createSpyObj('AndroidProject', ['getPackageName', 'write']));
|
||||
var projectSpy = jasmine.createSpyObj('AndroidProject', ['getPackageName', 'write']);
|
||||
spyOn(AndroidProject, 'getProjectFile').andReturn(projectSpy);
|
||||
|
||||
var Api = require('../../bin/templates/cordova/Api');
|
||||
api = new Api('android', FAKE_PROJECT_DIR);
|
||||
|
||||
spyOn(api, '_addModulesInfo');
|
||||
spyOn(api._munger, 'add_plugin_changes')
|
||||
.andReturn(jasmine.createSpyObj('munger', ['save_all']));
|
||||
|
||||
fail = jasmine.createSpy('fail');
|
||||
gradleBuilder = jasmine.createSpyObj('gradleBuilder', ['prepBuildFiles']);
|
||||
spyOn(builders, 'getBuilder').andReturn(gradleBuilder);
|
||||
|
Loading…
Reference in New Issue
Block a user