From 82c972dcfc758d50a088af780a367e148bc8d0cb Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Thu, 10 Mar 2016 01:01:57 +0200 Subject: [PATCH] Fix plugin remove command for invalid plugins When invalid plugin data is written in project's package.json, `tns plugin remove ` command fails. In such cases `npm uninstall --save ` just removes the entry from package.json, so we should do the same. By invalid data I mean invalid version (not existing version or path to non-existing file). Plugin remove command's canExecute method is trying to install all plugins in order to get information about their native code, so it will be removed from `platforms` dir. The installation fails when some plugin's data is invalid. Catch the error and check package.json's dependencies instead. Also make sure plugin variables data is removed from package.json when plugin is removed. Currently it's been removed only when platform is added and plugin has native code. --- lib/commands/plugin/remove-plugin.ts | 17 ++++++++++++++--- lib/definitions/plugins.d.ts | 8 ++++---- lib/services/plugin-variables-service.ts | 12 ++++++------ lib/services/plugins-service.ts | 12 +++++++----- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/lib/commands/plugin/remove-plugin.ts b/lib/commands/plugin/remove-plugin.ts index ca3631b572..2034ae8c0d 100644 --- a/lib/commands/plugin/remove-plugin.ts +++ b/lib/commands/plugin/remove-plugin.ts @@ -3,7 +3,9 @@ export class RemovePluginCommand implements ICommand { constructor(private $pluginsService: IPluginsService, - private $errors: IErrors) { } + private $errors: IErrors, + private $logger: ILogger, + private $projectData: IProjectData) { } execute(args: string[]): IFuture { return this.$pluginsService.remove(args[0]); @@ -15,9 +17,18 @@ export class RemovePluginCommand implements ICommand { this.$errors.fail("You must specify plugin name."); } - let installedPlugins = this.$pluginsService.getAllInstalledPlugins().wait(); + let pluginNames: string[] = []; + try { + // try installing the plugins, so we can get information from node_modules about their native code, libs, etc. + let installedPlugins = this.$pluginsService.getAllInstalledPlugins().wait(); + pluginNames = installedPlugins.map(pl => pl.name); + } catch(err) { + this.$logger.trace("Error while installing plugins. Error is:", err); + pluginNames = _.keys(this.$projectData.dependencies); + } + let pluginName = args[0].toLowerCase(); - if(!_.any(installedPlugins, (plugin: IPluginData) => plugin.name.toLowerCase() === pluginName)) { + if(!_.any(pluginNames, name => name.toLowerCase() === pluginName)) { this.$errors.failWithoutHelp(`Plugin "${pluginName}" is not installed.`); } diff --git a/lib/definitions/plugins.d.ts b/lib/definitions/plugins.d.ts index f991382196..01723fb290 100644 --- a/lib/definitions/plugins.d.ts +++ b/lib/definitions/plugins.d.ts @@ -36,10 +36,10 @@ interface IPluginVariablesService { savePluginVariablesInProjectFile(pluginData: IPluginData): IFuture; /** * Removes plugin variables from project package.json file. - * @param {IPluginData} pluginData for the plugin. + * @param {string} pluginName Name of the plugin. * @return {IFuture} */ - removePluginVariablesFromProjectFile(pluginData: IPluginData): IFuture; + removePluginVariablesFromProjectFile(pluginName: string): IFuture; /** * Replaces all plugin variables with their corresponding values. * @param {IPluginData} pluginData for the plugin. @@ -59,10 +59,10 @@ interface IPluginVariablesService { interpolate(pluginData: IPluginData, pluginConfigurationFilePath: string): IFuture; /** * Returns the - * @param {IPluginData} pluginData for the plugin. + * @param {string} pluginName for the plugin. * @return {IFuture} returns the changed plugin configuration file content. */ - getPluginVariablePropertyName(pluginData: IPluginData): string; + getPluginVariablePropertyName(pluginName: string): string; } diff --git a/lib/services/plugin-variables-service.ts b/lib/services/plugin-variables-service.ts index 60340a73e6..9592c9b84c 100644 --- a/lib/services/plugin-variables-service.ts +++ b/lib/services/plugin-variables-service.ts @@ -13,8 +13,8 @@ export class PluginVariablesService implements IPluginVariablesService { private $prompter: IPrompter, private $fs: IFileSystem) { } - public getPluginVariablePropertyName(pluginData: IPluginData): string { - return `${pluginData.name}-${PluginVariablesService.PLUGIN_VARIABLES_KEY}`; + public getPluginVariablePropertyName(pluginName: string): string { + return `${pluginName}-${PluginVariablesService.PLUGIN_VARIABLES_KEY}`; } public savePluginVariablesInProjectFile(pluginData: IPluginData): IFuture { @@ -29,14 +29,14 @@ export class PluginVariablesService implements IPluginVariablesService { if(!_.isEmpty(values)) { this.$projectDataService.initialize(this.$projectData.projectDir); - this.$projectDataService.setValue(this.getPluginVariablePropertyName(pluginData), values).wait(); + this.$projectDataService.setValue(this.getPluginVariablePropertyName(pluginData.name), values).wait(); } }).future()(); } - public removePluginVariablesFromProjectFile(pluginData: IPluginData): IFuture { + public removePluginVariablesFromProjectFile(pluginName: string): IFuture { this.$projectDataService.initialize(this.$projectData.projectDir); - return this.$projectDataService.removeProperty(this.getPluginVariablePropertyName(pluginData)); + return this.$projectDataService.removeProperty(this.getPluginVariablePropertyName(pluginName)); } public interpolatePluginVariables(pluginData: IPluginData, pluginConfigurationFilePath: string): IFuture { @@ -115,7 +115,7 @@ export class PluginVariablesService implements IPluginVariablesService { variableData.name = pluginVariableName; this.$projectDataService.initialize(this.$projectData.projectDir); - let pluginVariableValues = this.$projectDataService.getValue(this.getPluginVariablePropertyName(pluginData)).wait(); + let pluginVariableValues = this.$projectDataService.getValue(this.getPluginVariablePropertyName(pluginData.name)).wait(); variableData.value = pluginVariableValues ? pluginVariableValues[pluginVariableName] : undefined; return variableData; diff --git a/lib/services/plugins-service.ts b/lib/services/plugins-service.ts index deb800ee05..ec53cf245d 100644 --- a/lib/services/plugins-service.ts +++ b/lib/services/plugins-service.ts @@ -47,7 +47,7 @@ export class PluginsService implements IPluginsService { } catch(err) { // Revert package.json this.$projectDataService.initialize(this.$projectData.projectDir); - this.$projectDataService.removeProperty(this.$pluginVariablesService.getPluginVariablePropertyName(pluginData)).wait(); + this.$projectDataService.removeProperty(this.$pluginVariablesService.getPluginVariablePropertyName(pluginData.name)).wait(); this.$projectDataService.removeDependency(pluginData.name).wait(); throw err; @@ -68,12 +68,10 @@ export class PluginsService implements IPluginsService { let pluginData = this.convertToPluginData(this.getNodeModuleData(pluginName).wait()); platformData.platformProjectService.removePluginNativeCode(pluginData).wait(); - - if(pluginData.pluginVariables) { - this.$pluginVariablesService.removePluginVariablesFromProjectFile(pluginData).wait(); - } }).future()(); }; + + this.$pluginVariablesService.removePluginVariablesFromProjectFile(pluginName.toLowerCase()).wait(); this.executeForAllInstalledPlatforms(removePluginNativeCodeAction).wait(); this.executeNpmCommand(PluginsService.UNINSTALL_COMMAND_NAME, pluginName).wait(); @@ -224,6 +222,10 @@ export class PluginsService implements IPluginsService { result = this.$npm.install(npmCommandArguments, this.$projectData.projectDir, PluginsService.NPM_CONFIG).wait(); } else if(npmCommandName === PluginsService.UNINSTALL_COMMAND_NAME) { result = this.$npm.uninstall(npmCommandArguments, PluginsService.NPM_CONFIG, this.$projectData.projectDir).wait(); + if(!result || !result.length) { + // indicates something's wrong with the data in package.json, for example version of the plugin that we are trying to remove is invalid. + return npmCommandArguments.toLowerCase(); + } } return this.parseNpmCommandResult(result);