From 62a341be07615ca9bbac982f5fbf9d776d3289db Mon Sep 17 00:00:00 2001 From: Florian Greinacher Date: Thu, 12 Nov 2020 13:54:55 +0000 Subject: [PATCH] feat(vscode): add support for "workbench.extensions.installExtension" command Signed-off-by: Florian Greinacher --- .../plugin-vscode-commands-contribution.ts | 11 ++++ .../main/node/plugin-ext-backend-module.ts | 2 + .../resolvers/plugin-local-file-resolver.ts | 56 +++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 packages/plugin-ext/src/main/node/resolvers/plugin-local-file-resolver.ts diff --git a/packages/plugin-ext-vscode/src/browser/plugin-vscode-commands-contribution.ts b/packages/plugin-ext-vscode/src/browser/plugin-vscode-commands-contribution.ts index 440730fb20a6b..0d0f65d7754d2 100755 --- a/packages/plugin-ext-vscode/src/browser/plugin-vscode-commands-contribution.ts +++ b/packages/plugin-ext-vscode/src/browser/plugin-vscode-commands-contribution.ts @@ -53,6 +53,7 @@ import { DiffService } from '@theia/workspace/lib/browser/diff-service'; import { inject, injectable } from 'inversify'; import { Position } from '@theia/plugin-ext/lib/common/plugin-api-rpc'; import { URI } from 'vscode-uri'; +import { PluginServer } from '@theia/plugin-ext/lib/common/plugin-protocol'; import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor'; import { TerminalFrontendContribution } from '@theia/terminal/lib/browser/terminal-frontend-contribution'; import { QuickOpenWorkspace } from '@theia/workspace/lib/browser/quick-open-workspace'; @@ -106,6 +107,8 @@ export class PluginVscodeCommandsContribution implements CommandContribution { protected readonly terminalService: TerminalService; @inject(CodeEditorWidgetUtil) protected readonly codeEditorWidgetUtil: CodeEditorWidgetUtil; + @inject(PluginServer) + protected readonly pluginServer: PluginServer; registerCommands(commands: CommandRegistry): void { commands.registerCommand(VscodeCommands.OPEN, { @@ -208,6 +211,14 @@ export class PluginVscodeCommandsContribution implements CommandContribution { commands.registerCommand({ id: 'workbench.action.openSettings' }, { execute: () => commands.executeCommand(CommonCommands.OPEN_PREFERENCES.id) }); + commands.registerCommand({ id: 'workbench.extensions.installExtension' }, { + execute: async (uriOrId: URI | string) => { + const pluginEntry = URI.isUri(uriOrId) && uriOrId.scheme === 'file' + ? `local-file:${uriOrId.fsPath}` + : `vscode:extension/${uriOrId}`; + await this.pluginServer.deploy(pluginEntry); + } + }); commands.registerCommand({ id: 'workbench.action.files.save', }, { execute: (uri?: monaco.Uri) => { if (uri) { diff --git a/packages/plugin-ext/src/main/node/plugin-ext-backend-module.ts b/packages/plugin-ext/src/main/node/plugin-ext-backend-module.ts index 440e5f138f032..b92fc24f66dac 100644 --- a/packages/plugin-ext/src/main/node/plugin-ext-backend-module.ts +++ b/packages/plugin-ext/src/main/node/plugin-ext-backend-module.ts @@ -25,6 +25,7 @@ import { } from '../../common/plugin-protocol'; import { PluginDeployerImpl } from './plugin-deployer-impl'; import { LocalDirectoryPluginDeployerResolver } from './resolvers/plugin-local-dir-resolver'; +import { LocalFilePluginDeployerResolver } from './resolvers/plugin-local-file-resolver'; import { PluginTheiaFileHandler } from './handlers/plugin-theia-file-handler'; import { PluginTheiaDirectoryHandler } from './handlers/plugin-theia-directory-handler'; import { GithubPluginDeployerResolver } from './plugin-github-resolver'; @@ -47,6 +48,7 @@ export function bindMainBackend(bind: interfaces.Bind): void { bind(BackendApplicationContribution).toService(PluginDeployerContribution); bind(PluginDeployerResolver).to(LocalDirectoryPluginDeployerResolver).inSingletonScope(); + bind(PluginDeployerResolver).to(LocalFilePluginDeployerResolver).inSingletonScope(); bind(PluginDeployerResolver).to(GithubPluginDeployerResolver).inSingletonScope(); bind(PluginDeployerResolver).to(HttpPluginDeployerResolver).inSingletonScope(); diff --git a/packages/plugin-ext/src/main/node/resolvers/plugin-local-file-resolver.ts b/packages/plugin-ext/src/main/node/resolvers/plugin-local-file-resolver.ts new file mode 100644 index 0000000000000..4cbb26ec91e97 --- /dev/null +++ b/packages/plugin-ext/src/main/node/resolvers/plugin-local-file-resolver.ts @@ -0,0 +1,56 @@ +/******************************************************************************** + * Copyright (C) 2018 Red Hat, Inc. and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { PluginDeployerResolver, PluginDeployerResolverContext } from '../../../common/plugin-protocol'; +import { injectable } from 'inversify'; +import * as fs from 'fs'; +import * as path from 'path'; +import { FileUri } from '@theia/core/lib/node'; +import URI from '@theia/core/lib/common/uri'; + +@injectable() +export class LocalFilePluginDeployerResolver implements PluginDeployerResolver { + + static LOCAL_FILE = 'local-file'; + + /** + * Check all files/folder from the local-dir referenced and add them as plugins. + */ + async resolve(pluginResolverContext: PluginDeployerResolverContext): Promise { + // get directory + const localFileUri = new URI(pluginResolverContext.getOriginId()); + if (localFileUri.scheme !== LocalFilePluginDeployerResolver.LOCAL_FILE) { + return; + } + // get fs path + let filePath = FileUri.fsPath(localFileUri); + if (!path.isAbsolute(filePath)) { + filePath = path.resolve(process.cwd(), filePath); + } + // check file exists + if (!fs.existsSync(filePath)) { + console.warn(`The file referenced by ${pluginResolverContext.getOriginId()} does not exist.`); + return; + } + const fileName = path.basename(filePath); + pluginResolverContext.addPlugin(fileName, filePath); + } + accept(pluginId: string): boolean { + return pluginId.startsWith(LocalFilePluginDeployerResolver.LOCAL_FILE); + } +}