diff --git a/packages/core/src/electron-node/hosting/electron-ws-origin-validator.ts b/packages/core/src/electron-node/hosting/electron-ws-origin-validator.ts index 43494b9ffd4c5..d9bceab8db793 100644 --- a/packages/core/src/electron-node/hosting/electron-ws-origin-validator.ts +++ b/packages/core/src/electron-node/hosting/electron-ws-origin-validator.ts @@ -16,7 +16,7 @@ import * as http from 'http'; import { inject, injectable } from 'inversify'; -import { BackendRemoteService } from '../../node/backend-remote-service'; +import { BackendRemoteService } from '../../node/remote/backend-remote-service'; import { WsRequestValidatorContribution } from '../../node/ws-request-validators'; @injectable() diff --git a/packages/core/src/node/backend-application-module.ts b/packages/core/src/node/backend-application-module.ts index a89a7a8a52ea6..f5a17db9bd514 100644 --- a/packages/core/src/node/backend-application-module.ts +++ b/packages/core/src/node/backend-application-module.ts @@ -41,7 +41,8 @@ import { bindNodeStopwatch, bindBackendStopwatchServer } from './performance'; import { OSBackendProviderImpl } from './os-backend-provider'; import { BackendRequestFacade } from './request/backend-request-facade'; import { FileSystemLocking, FileSystemLockingImpl } from './filesystem-locking'; -import { BackendRemoteService } from './backend-remote-service'; +import { BackendRemoteService } from './remote/backend-remote-service'; +import { RemoteCliContribution } from './remote/remote-cli-contribution'; decorate(injectable(), ApplicationPackage); @@ -124,6 +125,7 @@ export const backendApplicationModule = new ContainerModule(bind => { bind(ProxyCliContribution).toSelf().inSingletonScope(); bind(CliContribution).toService(ProxyCliContribution); + bindContributionProvider(bind, RemoteCliContribution); bind(BackendRemoteService).toSelf().inSingletonScope(); bind(BackendRequestFacade).toSelf().inSingletonScope(); bind(ConnectionHandler).toDynamicValue( diff --git a/packages/core/src/node/backend-remote-service.ts b/packages/core/src/node/remote/backend-remote-service.ts similarity index 100% rename from packages/core/src/node/backend-remote-service.ts rename to packages/core/src/node/remote/backend-remote-service.ts diff --git a/packages/core/src/node/remote/remote-cli-contribution.ts b/packages/core/src/node/remote/remote-cli-contribution.ts new file mode 100644 index 0000000000000..7f25cb3fb952c --- /dev/null +++ b/packages/core/src/node/remote/remote-cli-contribution.ts @@ -0,0 +1,34 @@ +// ***************************************************************************** +// Copyright (C) 2024 TypeFox 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-only WITH Classpath-exception-2.0 +// ***************************************************************************** + +import type { OS } from '../../common/os'; +import type { MaybePromise } from '../../common/types'; + +export interface RemotePlatform { + os: OS.Type + arch: string +} + +export interface RemoteCliContext { + platform: RemotePlatform; + directory: string; +} + +export const RemoteCliContribution = Symbol('RemoteCliContribution'); + +export interface RemoteCliContribution { + enhanceArgs(context: RemoteCliContext): MaybePromise; +} diff --git a/packages/core/src/node/remote/remote-copy-contribution.ts b/packages/core/src/node/remote/remote-copy-contribution.ts new file mode 100644 index 0000000000000..c0a746c71679d --- /dev/null +++ b/packages/core/src/node/remote/remote-copy-contribution.ts @@ -0,0 +1,45 @@ +// ***************************************************************************** +// Copyright (C) 2024 TypeFox 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-only WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { MaybePromise } from '../../common/types'; + +export const RemoteCopyContribution = Symbol('RemoteCopyContribution'); + +export interface RemoteCopyContribution { + copy(registry: RemoteCopyRegistry): MaybePromise +} + +export interface RemoteCopyOptions { + /** + * The mode that the file should be set to once copied to the remote. + * + * Only relevant for POSIX-like systems + */ + mode?: number; +} + +export interface RemoteFile { + path: string + target: string + options?: RemoteCopyOptions; +} + +export interface RemoteCopyRegistry { + getFiles(): RemoteFile[]; + glob(pattern: string, target?: string): Promise; + file(file: string, target?: string, options?: RemoteCopyOptions): void; + directory(dir: string, target?: string): Promise; +} diff --git a/packages/plugin-ext/src/common/plugin-protocol.ts b/packages/plugin-ext/src/common/plugin-protocol.ts index 61f457a9a572c..222b699797831 100644 --- a/packages/plugin-ext/src/common/plugin-protocol.ts +++ b/packages/plugin-ext/src/common/plugin-protocol.ts @@ -984,6 +984,7 @@ export interface PluginDeployerHandler { deployFrontendPlugins(frontendPlugins: PluginDeployerEntry[]): Promise; deployBackendPlugins(backendPlugins: PluginDeployerEntry[]): Promise; + getDeployedPlugins(): Promise; getDeployedPluginsById(pluginId: string): DeployedPlugin[]; getDeployedPlugin(pluginId: PluginIdentifiers.VersionedId): DeployedPlugin | undefined; diff --git a/packages/plugin-ext/src/hosted/node/hosted-plugin-deployer-handler.ts b/packages/plugin-ext/src/hosted/node/hosted-plugin-deployer-handler.ts index 4acce219513da..49cce6b693389 100644 --- a/packages/plugin-ext/src/hosted/node/hosted-plugin-deployer-handler.ts +++ b/packages/plugin-ext/src/hosted/node/hosted-plugin-deployer-handler.ts @@ -83,6 +83,12 @@ export class HostedPluginDeployerHandler implements PluginDeployerHandler { return Array.from(this.deployedBackendPlugins.values()); } + async getDeployedPlugins(): Promise { + await this.frontendPluginsMetadataDeferred.promise; + await this.backendPluginsMetadataDeferred.promise; + return [...this.deployedFrontendPlugins.values(), ...this.deployedBackendPlugins.values()]; + } + getDeployedPluginsById(pluginId: string): DeployedPlugin[] { const matches: DeployedPlugin[] = []; const handle = (plugins: Iterable): void => { 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 fc3b6996f458d..fdb6825dc519a 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 @@ -42,6 +42,10 @@ import { PluginUninstallationManager } from './plugin-uninstallation-manager'; import { LocalizationServerImpl } from '@theia/core/lib/node/i18n/localization-server'; import { PluginLocalizationServer } from './plugin-localization-server'; import { PluginMgmtCliContribution } from './plugin-mgmt-cli-contribution'; +import { PluginRemoteCliContribution } from './plugin-remote-cli-contribution'; +import { RemoteCliContribution } from '@theia/core/lib/node/remote/remote-cli-contribution'; +import { PluginRemoteCopyContribution } from './plugin-remote-copy-contribution'; +import { RemoteCopyContribution } from '@theia/core/lib/node/remote/remote-copy-contribution'; export function bindMainBackend(bind: interfaces.Bind, unbind: interfaces.Unbind, isBound: interfaces.IsBound, rebind: interfaces.Rebind): void { bind(PluginApiContribution).toSelf().inSingletonScope(); @@ -89,6 +93,11 @@ export function bindMainBackend(bind: interfaces.Bind, unbind: interfaces.Unbind bind(PluginMgmtCliContribution).toSelf().inSingletonScope(); bind(CliContribution).toService(PluginMgmtCliContribution); + bind(PluginRemoteCliContribution).toSelf().inSingletonScope(); + bind(RemoteCliContribution).toService(PluginRemoteCliContribution); + bind(PluginRemoteCopyContribution).toSelf().inSingletonScope(); + bind(RemoteCopyContribution).toService(PluginRemoteCopyContribution); + bind(WebviewBackendSecurityWarnings).toSelf().inSingletonScope(); bind(BackendApplicationContribution).toService(WebviewBackendSecurityWarnings); diff --git a/packages/plugin-ext/src/main/node/plugin-remote-cli-contribution.ts b/packages/plugin-ext/src/main/node/plugin-remote-cli-contribution.ts new file mode 100644 index 0000000000000..2df189ce8d57a --- /dev/null +++ b/packages/plugin-ext/src/main/node/plugin-remote-cli-contribution.ts @@ -0,0 +1,36 @@ +// ***************************************************************************** +// Copyright (C) 2024 TypeFox 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-only WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { MaybePromise } from '@theia/core'; +import { RemoteCliContext, RemoteCliContribution } from '@theia/core/lib/node/remote/remote-cli-contribution'; +import { inject, injectable } from '@theia/core/shared/inversify'; +import { PluginCliContribution } from './plugin-cli-contribution'; + +@injectable() +export class PluginRemoteCliContribution implements RemoteCliContribution { + + @inject(PluginCliContribution) + protected readonly pluginCliContribution: PluginCliContribution; + + enhanceArgs(context: RemoteCliContext): MaybePromise { + const pluginsFolder = this.pluginCliContribution.localDir(); + if (!pluginsFolder) { + return []; + } else { + return ['--plugins=local-dir:./plugins']; + } + } +} diff --git a/packages/plugin-ext/src/main/node/plugin-remote-copy-contribution.ts b/packages/plugin-ext/src/main/node/plugin-remote-copy-contribution.ts new file mode 100644 index 0000000000000..2b7314f167118 --- /dev/null +++ b/packages/plugin-ext/src/main/node/plugin-remote-copy-contribution.ts @@ -0,0 +1,36 @@ +// ***************************************************************************** +// Copyright (C) 2024 TypeFox 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-only WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { RemoteCopyContribution, RemoteCopyRegistry } from '@theia/core/lib/node/remote/remote-copy-contribution'; +import { inject, injectable } from '@theia/core/shared/inversify'; +import { PluginCliContribution } from './plugin-cli-contribution'; +import { FileUri } from '@theia/core/lib/common/file-uri'; + +@injectable() +export class PluginRemoteCopyContribution implements RemoteCopyContribution { + + @inject(PluginCliContribution) + protected readonly pluginCliContribution: PluginCliContribution; + + async copy(registry: RemoteCopyRegistry): Promise { + const localDir = this.pluginCliContribution.localDir(); + if (localDir) { + const fsPath = FileUri.fsPath(localDir); + await registry.directory(fsPath, 'plugins'); + } + + } +} diff --git a/packages/plugin-ext/src/main/node/plugin-service.ts b/packages/plugin-ext/src/main/node/plugin-service.ts index 91763379a5e0b..756c97975b93f 100644 --- a/packages/plugin-ext/src/main/node/plugin-service.ts +++ b/packages/plugin-ext/src/main/node/plugin-service.ts @@ -26,7 +26,7 @@ import { environment } from '@theia/core/shared/@theia/application-package/lib/e import { WsRequestValidatorContribution } from '@theia/core/lib/node/ws-request-validators'; import { MaybePromise } from '@theia/core/lib/common'; import { ApplicationPackage } from '@theia/core/shared/@theia/application-package'; -import { BackendRemoteService } from '@theia/core/lib/node/backend-remote-service'; +import { BackendRemoteService } from '@theia/core/lib/node/remote/backend-remote-service'; @injectable() export class PluginApiContribution implements BackendApplicationContribution, WsRequestValidatorContribution { diff --git a/packages/remote/src/electron-node/backend-remote-service-impl.ts b/packages/remote/src/electron-node/backend-remote-service-impl.ts index 805481b9eb790..db88035eeb4ef 100644 --- a/packages/remote/src/electron-node/backend-remote-service-impl.ts +++ b/packages/remote/src/electron-node/backend-remote-service-impl.ts @@ -17,7 +17,7 @@ import { CliContribution } from '@theia/core/lib/node'; import { injectable } from '@theia/core/shared/inversify'; import { Arguments, Argv } from '@theia/core/shared/yargs'; -import { BackendRemoteService } from '@theia/core/lib/node/backend-remote-service'; +import { BackendRemoteService } from '@theia/core/lib/node/remote/backend-remote-service'; export const REMOTE_START = 'remote'; diff --git a/packages/remote/src/electron-node/remote-backend-module.ts b/packages/remote/src/electron-node/remote-backend-module.ts index 2197bb28a3d8b..ad0084eb8ae79 100644 --- a/packages/remote/src/electron-node/remote-backend-module.ts +++ b/packages/remote/src/electron-node/remote-backend-module.ts @@ -27,13 +27,14 @@ import { RemoteCopyService } from './setup/remote-copy-service'; import { RemoteSetupService } from './setup/remote-setup-service'; import { RemoteNativeDependencyService } from './setup/remote-native-dependency-service'; import { BackendRemoteServiceImpl } from './backend-remote-service-impl'; -import { BackendRemoteService } from '@theia/core/lib/node/backend-remote-service'; +import { BackendRemoteService } from '@theia/core/lib/node/remote/backend-remote-service'; import { RemoteNodeSetupService } from './setup/remote-node-setup-service'; import { RemotePosixScriptStrategy, RemoteSetupScriptService, RemoteWindowsScriptStrategy } from './setup/remote-setup-script-service'; import { RemoteStatusService, RemoteStatusServicePath } from '../electron-common/remote-status-service'; import { RemoteStatusServiceImpl } from './remote-status-service'; import { ConnectionHandler, RpcConnectionHandler, bindContributionProvider } from '@theia/core'; -import { RemoteCopyContribution, RemoteCopyRegistry } from './setup/remote-copy-contribution'; +import { RemoteCopyRegistryImpl } from './setup/remote-copy-contribution'; +import { RemoteCopyContribution } from '@theia/core/lib/node/remote/remote-copy-contribution'; import { MainCopyContribution } from './setup/main-copy-contribution'; import { RemoteNativeDependencyContribution } from './setup/remote-native-dependency-contribution'; import { AppNativeDependencyContribution } from './setup/app-native-dependency-contribution'; @@ -68,7 +69,7 @@ export default new ContainerModule((bind, _unbind, _isBound, rebind) => { bind(RemotePosixScriptStrategy).toSelf().inSingletonScope(); bind(RemoteSetupScriptService).toSelf().inSingletonScope(); bind(RemoteNativeDependencyService).toSelf().inSingletonScope(); - bind(RemoteCopyRegistry).toSelf().inSingletonScope(); + bind(RemoteCopyRegistryImpl).toSelf().inSingletonScope(); bindContributionProvider(bind, RemoteCopyContribution); bindContributionProvider(bind, RemoteNativeDependencyContribution); bind(MainCopyContribution).toSelf().inSingletonScope(); diff --git a/packages/remote/src/electron-node/remote-connection-service.ts b/packages/remote/src/electron-node/remote-connection-service.ts index ce776b8590fc4..e86612ee60257 100644 --- a/packages/remote/src/electron-node/remote-connection-service.ts +++ b/packages/remote/src/electron-node/remote-connection-service.ts @@ -18,8 +18,8 @@ import { inject, injectable } from '@theia/core/shared/inversify'; import { RemoteConnection } from './remote-types'; import { Disposable } from '@theia/core'; import { RemoteCopyService } from './setup/remote-copy-service'; -import { RemoteNativeDependencyService } from './setup/remote-native-dependency-service'; import { BackendApplicationContribution } from '@theia/core/lib/node'; +import { RemoteSetupService } from './setup/remote-setup-service'; @injectable() export class RemoteConnectionService implements BackendApplicationContribution { @@ -27,8 +27,9 @@ export class RemoteConnectionService implements BackendApplicationContribution { @inject(RemoteCopyService) protected readonly copyService: RemoteCopyService; - @inject(RemoteNativeDependencyService) - protected readonly nativeDependencyService: RemoteNativeDependencyService; + // Workaround for the fact that connection scoped services cannot directly inject these services. + @inject(RemoteSetupService) + protected readonly remoteSetupService: RemoteSetupService; protected readonly connections = new Map(); diff --git a/packages/remote/src/electron-node/remote-types.ts b/packages/remote/src/electron-node/remote-types.ts index 9c829ee201499..c8ab798b1a15a 100644 --- a/packages/remote/src/electron-node/remote-types.ts +++ b/packages/remote/src/electron-node/remote-types.ts @@ -14,14 +14,9 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import { Disposable, Event, OS } from '@theia/core'; +import { Disposable, Event } from '@theia/core'; import * as net from 'net'; -export interface RemotePlatform { - os: OS.Type - arch: string -} - export type RemoteStatusReport = (message: string) => void; export interface ExpressLayer { diff --git a/packages/remote/src/electron-node/setup/app-native-dependency-contribution.ts b/packages/remote/src/electron-node/setup/app-native-dependency-contribution.ts index 1e0d8e52719cb..4e0ffbd3e365a 100644 --- a/packages/remote/src/electron-node/setup/app-native-dependency-contribution.ts +++ b/packages/remote/src/electron-node/setup/app-native-dependency-contribution.ts @@ -16,7 +16,7 @@ import { injectable } from '@theia/core/shared/inversify'; import { RemoteNativeDependencyContribution, DownloadOptions, DependencyDownload } from './remote-native-dependency-contribution'; -import { RemotePlatform } from '../remote-types'; +import { RemotePlatform } from '@theia/core/lib/node/remote/remote-cli-contribution'; import { OS } from '@theia/core'; @injectable() diff --git a/packages/remote/src/electron-node/setup/main-copy-contribution.ts b/packages/remote/src/electron-node/setup/main-copy-contribution.ts index e615af69b33cf..452d0eb15409c 100644 --- a/packages/remote/src/electron-node/setup/main-copy-contribution.ts +++ b/packages/remote/src/electron-node/setup/main-copy-contribution.ts @@ -15,7 +15,7 @@ // ***************************************************************************** import { injectable } from '@theia/core/shared/inversify'; -import { RemoteCopyContribution, RemoteCopyRegistry } from './remote-copy-contribution'; +import { RemoteCopyContribution, RemoteCopyRegistry } from '@theia/core/lib/node/remote/remote-copy-contribution'; @injectable() export class MainCopyContribution implements RemoteCopyContribution { diff --git a/packages/remote/src/electron-node/setup/remote-copy-contribution.ts b/packages/remote/src/electron-node/setup/remote-copy-contribution.ts index 4aecf9e8f0746..9c9130e8c48f9 100644 --- a/packages/remote/src/electron-node/setup/remote-copy-contribution.ts +++ b/packages/remote/src/electron-node/setup/remote-copy-contribution.ts @@ -16,36 +16,15 @@ import { ApplicationPackage } from '@theia/core/shared/@theia/application-package'; import { inject, injectable } from '@theia/core/shared/inversify'; +import { RemoteCopyRegistry, RemoteFile, RemoteCopyOptions } from '@theia/core/lib/node/remote/remote-copy-contribution'; import { glob as globCallback } from 'glob'; import { promisify } from 'util'; import * as path from 'path'; -import { MaybePromise } from '@theia/core'; const promiseGlob = promisify(globCallback); -export const RemoteCopyContribution = Symbol('RemoteCopyContribution'); - -export interface RemoteCopyContribution { - copy(registry: RemoteCopyRegistry): MaybePromise -} - -export interface RemoteCopyOptions { - /** - * The mode that the file should be set to once copied to the remote. - * - * Only relevant for POSIX-like systems - */ - mode?: number; -} - -export interface RemoteFile { - path: string - target: string - options?: RemoteCopyOptions; -} - @injectable() -export class RemoteCopyRegistry { +export class RemoteCopyRegistryImpl implements RemoteCopyRegistry { @inject(ApplicationPackage) protected readonly applicationPackage: ApplicationPackage; @@ -57,14 +36,16 @@ export class RemoteCopyRegistry { } async glob(pattern: string, target?: string): Promise { + return this.doGlob(pattern, this.applicationPackage.projectPath, target); + } + + async doGlob(pattern: string, cwd: string, target?: string): Promise { const projectPath = this.applicationPackage.projectPath; - const globResult = await promiseGlob(pattern, { - cwd: projectPath - }); + const globResult = await promiseGlob(pattern, { cwd, nodir: true }); for (const file of globResult) { const targetFile = this.withTarget(file, target); this.files.push({ - path: file, + path: path.relative(projectPath, path.resolve(cwd, file)), target: targetFile }); } @@ -80,7 +61,11 @@ export class RemoteCopyRegistry { } async directory(dir: string, target?: string): Promise { - return this.glob(dir + '/**', target); + let absoluteDir = dir; + if (!path.isAbsolute(absoluteDir)) { + absoluteDir = path.join(this.applicationPackage.projectPath, dir); + } + return this.doGlob('**/*', absoluteDir, target ?? dir); } protected withTarget(file: string, target?: string): string { diff --git a/packages/remote/src/electron-node/setup/remote-copy-service.ts b/packages/remote/src/electron-node/setup/remote-copy-service.ts index ffe46d40f99e4..4d6200c22f263 100644 --- a/packages/remote/src/electron-node/setup/remote-copy-service.ts +++ b/packages/remote/src/electron-node/setup/remote-copy-service.ts @@ -20,10 +20,12 @@ import * as fs from 'fs'; import * as os from 'os'; import { ApplicationPackage } from '@theia/core/shared/@theia/application-package'; import { inject, injectable, named } from '@theia/core/shared/inversify'; -import { RemoteConnection, RemotePlatform } from '../remote-types'; +import { RemoteConnection } from '../remote-types'; +import { RemotePlatform } from '@theia/core/lib/node/remote/remote-cli-contribution'; import { RemoteNativeDependencyService } from './remote-native-dependency-service'; import { ContributionProvider } from '@theia/core'; -import { RemoteCopyContribution, RemoteCopyRegistry, RemoteFile } from './remote-copy-contribution'; +import { RemoteCopyRegistryImpl } from './remote-copy-contribution'; +import { RemoteCopyContribution, RemoteFile } from '@theia/core/lib/node/remote/remote-copy-contribution'; @injectable() export class RemoteCopyService { @@ -31,8 +33,8 @@ export class RemoteCopyService { @inject(ApplicationPackage) protected readonly applicationPackage: ApplicationPackage; - @inject(RemoteCopyRegistry) - protected readonly copyRegistry: RemoteCopyRegistry; + @inject(RemoteCopyRegistryImpl) + protected readonly copyRegistry: RemoteCopyRegistryImpl; @inject(RemoteNativeDependencyService) protected readonly nativeDependencyService: RemoteNativeDependencyService; diff --git a/packages/remote/src/electron-node/setup/remote-native-dependency-contribution.ts b/packages/remote/src/electron-node/setup/remote-native-dependency-contribution.ts index ece62ba8c45a5..3a5260645658f 100644 --- a/packages/remote/src/electron-node/setup/remote-native-dependency-contribution.ts +++ b/packages/remote/src/electron-node/setup/remote-native-dependency-contribution.ts @@ -16,7 +16,7 @@ import { isObject } from '@theia/core'; import { RequestOptions } from '@theia/core/shared/@theia/request'; -import { RemotePlatform } from '../remote-types'; +import { RemotePlatform } from '@theia/core/lib/node/remote/remote-cli-contribution'; export interface FileDependencyResult { path: string; diff --git a/packages/remote/src/electron-node/setup/remote-native-dependency-service.ts b/packages/remote/src/electron-node/setup/remote-native-dependency-service.ts index 6caa905cbdaa5..579ccd5437327 100644 --- a/packages/remote/src/electron-node/setup/remote-native-dependency-service.ts +++ b/packages/remote/src/electron-node/setup/remote-native-dependency-service.ts @@ -21,7 +21,7 @@ import * as decompress from 'decompress'; import * as path from 'path'; import * as fs from 'fs/promises'; import { DependencyDownload, DirectoryDependencyDownload, RemoteNativeDependencyContribution } from './remote-native-dependency-contribution'; -import { RemotePlatform } from '../remote-types'; +import { RemotePlatform } from '@theia/core/lib/node/remote/remote-cli-contribution'; const decompressTar = require('decompress-tar'); const decompressTargz = require('decompress-targz'); diff --git a/packages/remote/src/electron-node/setup/remote-node-setup-service.ts b/packages/remote/src/electron-node/setup/remote-node-setup-service.ts index f559c2c494cde..49567e537736a 100644 --- a/packages/remote/src/electron-node/setup/remote-node-setup-service.ts +++ b/packages/remote/src/electron-node/setup/remote-node-setup-service.ts @@ -21,7 +21,7 @@ import * as os from 'os'; import { inject, injectable } from '@theia/core/shared/inversify'; import { RequestService } from '@theia/core/shared/@theia/request'; import { RemoteSetupScriptService } from './remote-setup-script-service'; -import { RemotePlatform } from '../remote-types'; +import { RemotePlatform } from '@theia/core/lib/node/remote/remote-cli-contribution'; import { OS } from '@theia/core'; /** diff --git a/packages/remote/src/electron-node/setup/remote-setup-script-service.ts b/packages/remote/src/electron-node/setup/remote-setup-script-service.ts index b6a7011d59ea3..afa606283c2ac 100644 --- a/packages/remote/src/electron-node/setup/remote-setup-script-service.ts +++ b/packages/remote/src/electron-node/setup/remote-setup-script-service.ts @@ -16,7 +16,7 @@ import { OS } from '@theia/core'; import { inject, injectable } from '@theia/core/shared/inversify'; -import { RemotePlatform } from '../remote-types'; +import { RemotePlatform } from '@theia/core/lib/node/remote/remote-cli-contribution'; export interface RemoteScriptStrategy { exec(): string; diff --git a/packages/remote/src/electron-node/setup/remote-setup-service.ts b/packages/remote/src/electron-node/setup/remote-setup-service.ts index 951f62429da8f..9ef150807d985 100644 --- a/packages/remote/src/electron-node/setup/remote-setup-service.ts +++ b/packages/remote/src/electron-node/setup/remote-setup-service.ts @@ -14,12 +14,13 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import { inject, injectable } from '@theia/core/shared/inversify'; -import { RemoteConnection, RemoteExecResult, RemotePlatform, RemoteStatusReport } from '../remote-types'; +import { inject, injectable, named } from '@theia/core/shared/inversify'; +import { RemoteConnection, RemoteExecResult, RemoteStatusReport } from '../remote-types'; +import { RemoteCliContext, RemoteCliContribution, RemotePlatform } from '@theia/core/lib/node/remote/remote-cli-contribution'; import { ApplicationPackage } from '@theia/core/shared/@theia/application-package'; import { RemoteCopyService } from './remote-copy-service'; import { RemoteNativeDependencyService } from './remote-native-dependency-service'; -import { OS, THEIA_VERSION } from '@theia/core'; +import { ContributionProvider, OS, THEIA_VERSION } from '@theia/core'; import { RemoteNodeSetupService } from './remote-node-setup-service'; import { RemoteSetupScriptService } from './remote-setup-script-service'; @@ -52,6 +53,9 @@ export class RemoteSetupService { @inject(ApplicationPackage) protected readonly applicationPackage: ApplicationPackage; + @inject(ContributionProvider) @named(RemoteCliContribution) + protected readonly cliContributions: ContributionProvider; + async setup(options: RemoteSetupOptions): Promise { const { connection, @@ -106,11 +110,21 @@ export class RemoteSetupService { // We might to switch to PowerShell beforehand on Windows prefix = this.scriptService.exec(platform) + ' '; } + const remoteContext: RemoteCliContext = { + platform, + directory: remotePath + }; + const args: string[] = ['--hostname=0.0.0.0', `--port=${connection.remotePort ?? 0}`, '--remote']; + for (const cli of this.cliContributions.getContributions()) { + if (cli.enhanceArgs) { + args.push(...await cli.enhanceArgs(remoteContext)); + } + } // Change to the remote application path and start a node process with the copied main.js file // This way, our current working directory is set as expected const result = await connection.execPartial(`${prefix}cd "${remotePath}";${nodeExecutable}`, stdout => localAddressRegex.test(stdout), - [mainJsFile, '--hostname=0.0.0.0', `--port=${connection.remotePort ?? 0}`, '--remote']); + [mainJsFile, ...args]); const match = localAddressRegex.exec(result.stdout); if (!match) { diff --git a/packages/vsx-registry/src/node/vsx-cli-deployer-participant.ts b/packages/vsx-registry/src/node/vsx-cli-deployer-participant.ts index e3390cc0bb7dc..b7b34c7c1ce08 100644 --- a/packages/vsx-registry/src/node/vsx-cli-deployer-participant.ts +++ b/packages/vsx-registry/src/node/vsx-cli-deployer-participant.ts @@ -29,7 +29,7 @@ export class VsxCliDeployerParticipant implements PluginDeployerParticipant { protected readonly vsxCli: VsxCli; async onWillStart(context: PluginDeployerStartContext): Promise { - const pluginUris = this.vsxCli.pluginsToInstall.map(async id => { + const pluginUris = await Promise.all(this.vsxCli.pluginsToInstall.map(async id => { try { const resolvedPath = path.resolve(id); const stat = await fs.promises.stat(resolvedPath); @@ -40,7 +40,7 @@ export class VsxCliDeployerParticipant implements PluginDeployerParticipant { // expected if file does not exist } return VSXExtensionUri.fromVersionedId(id).toString(); - }); - context.userEntries.push(...await Promise.all(pluginUris)); + })); + context.userEntries.push(...pluginUris); } } diff --git a/packages/vsx-registry/src/node/vsx-remote-cli.ts b/packages/vsx-registry/src/node/vsx-remote-cli.ts new file mode 100644 index 0000000000000..dc75d9c2b16d7 --- /dev/null +++ b/packages/vsx-registry/src/node/vsx-remote-cli.ts @@ -0,0 +1,39 @@ +// ***************************************************************************** +// Copyright (C) 2024 TypeFox 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-only WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { RemoteCliContext, RemoteCliContribution } from '@theia/core/lib/node/remote/remote-cli-contribution'; +import { inject, injectable } from '@theia/core/shared/inversify'; +import { PluginDeployerHandler, PluginType } from '@theia/plugin-ext'; + +@injectable() +export class VsxRemoteCli implements RemoteCliContribution { + + @inject(PluginDeployerHandler) + protected readonly pluginDeployerHandler: PluginDeployerHandler; + + async enhanceArgs(context: RemoteCliContext): Promise { + const deployedPlugins = await this.pluginDeployerHandler.getDeployedPlugins(); + // Plugin IDs can be duplicated between frontend and backend plugins, so we create a set first + const installPluginArgs = Array.from( + new Set( + deployedPlugins + .filter(plugin => plugin.type === PluginType.User) + .map(p => `--install-plugin=${p.metadata.model.id}`) + ) + ); + return installPluginArgs; + } +}