Skip to content

Commit 5e57ac4

Browse files
authored
fix: surface duplicate VSIX installation error to user notification (#17129)
Follow-up to #16963 - Throw `DuplicateExtensionError` from the resolver instead of silently returning - Propagate resolver errors through `resolvePlugins` when no plugins were resolved - Show a localized user-facing notification when a duplicate VSIX install is detected
1 parent d3daec4 commit 5e57ac4

File tree

3 files changed

+18
-5
lines changed

3 files changed

+18
-5
lines changed

packages/plugin-ext-vscode/src/node/local-vsix-file-plugin-deployer-resolver.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ export class LocalVSIXFilePluginDeployerResolver extends LocalPluginDeployerReso
6767
const existingPlugins = this.pluginDeployerHandler.getDeployedPluginsById(unversionedId);
6868
if (existingPlugins.length > 0) {
6969
const existingVersions = existingPlugins.map(p => p.metadata.model.version);
70-
console.log(
71-
'Extension ' + unversionedId + ' (version(s): ' + existingVersions.join(', ') + ') is already installed.\n' +
72-
'Uninstall the existing extension before installing a new version from VSIX.'
70+
const error = new Error(
71+
`Extension ${unversionedId} is already installed (version(s): ${existingVersions.join(', ')}).`
7372
);
74-
return;
73+
error.name = 'DuplicateExtensionError';
74+
throw error;
7575
}
7676

7777
// Check if the deployment directory already exists on disk

packages/plugin-ext/src/main/node/plugin-deployer-impl.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ export class PluginDeployerImpl implements PluginDeployer {
181181
const hasBeenVisited = (id: string) => visited.has(id) || (visited.add(id), false);
182182
const pluginsToDeploy = new Map<PluginIdentifiers.VersionedId, PluginDeployerEntry>();
183183
const unversionedIdsHandled = new Map<PluginIdentifiers.UnversionedId, string[]>();
184+
const errors: Error[] = [];
184185

185186
const queue: UnresolvedPluginEntry[] = [...plugins];
186187
while (queue.length) {
@@ -215,6 +216,7 @@ export class PluginDeployerImpl implements PluginDeployer {
215216
}
216217
} catch (e) {
217218
console.error(`Failed to resolve plugins from '${entry.id}'`, e);
219+
errors.push(e instanceof Error ? e : new Error(String(e)));
218220
}
219221
}));
220222
queue.length = 0;
@@ -229,6 +231,9 @@ export class PluginDeployerImpl implements PluginDeployer {
229231
}
230232
}
231233
}
234+
if (pluginsToDeploy.size === 0 && errors.length > 0) {
235+
throw errors[0];
236+
}
232237
return [...pluginsToDeploy.values()];
233238
}
234239

packages/vsx-registry/src/browser/vsx-extensions-contribution.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,15 @@ export class VSXExtensionsContribution extends AbstractViewContribution<VSXExten
266266
await this.commandRegistry.executeCommand(VscodeCommands.INSTALL_EXTENSION_FROM_ID_OR_URI.id, fileURI);
267267
this.messageService.info(nls.localizeByDefault('Completed installing extension.', extensionName));
268268
} catch (e) {
269-
this.messageService.error(nls.localize('theia/vsx-registry/failedInstallingVSIX', 'Failed to install {0} from VSIX.', extensionName));
269+
if (e instanceof Error && e.name === 'DuplicateExtensionError') {
270+
this.messageService.error(
271+
nls.localize('theia/vsx-registry/duplicateVSIX',
272+
'Failed to install {0} from VSIX. The extension is already installed. Uninstall the existing extension before installing a new version from VSIX.',
273+
extensionName)
274+
);
275+
} else {
276+
this.messageService.error(nls.localize('theia/vsx-registry/failedInstallingVSIX', 'Failed to install {0} from VSIX.', extensionName));
277+
}
270278
console.warn(e);
271279
}
272280
}

0 commit comments

Comments
 (0)