Skip to content

Commit

Permalink
Added extensionDependency automatically downloading. Fixes: #4504
Browse files Browse the repository at this point in the history
Signed-off-by: Josh Pinkney <joshpinkney@gmail.com>
  • Loading branch information
JPinkney committed Jun 10, 2019
1 parent 92cfe9a commit e9b6699
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 5 deletions.
58 changes: 55 additions & 3 deletions packages/plugin-ext-vscode/src/node/plugin-vscode-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,30 @@

// tslint:disable:no-any

import { PluginDeployerResolver, PluginDeployerResolverContext } from '@theia/plugin-ext';
import { injectable } from 'inversify';
import { PluginDeployerResolver, PluginDeployerResolverContext, PluginDeployerEntry } from '@theia/plugin-ext';
import { injectable, inject } from 'inversify';
import * as request from 'request';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { PluginDeployerHandler } from '@theia/plugin-ext/lib/common/plugin-protocol';
import { PluginVsCodeFileHandler } from './plugin-vscode-file-handler';
import { PluginDeployerFileHandlerContextImpl } from '@theia/plugin-ext/lib/main/node/plugin-deployer-file-handler-context-impl';
import { PluginDeployerEntryImpl } from '@theia/plugin-ext/lib/main/node/plugin-deployer-entry-impl';
import { ProxyPluginDeployerEntry } from '@theia/plugin-ext/lib/main/node/plugin-deployer-proxy-entry-impl';
import { PluginDeployerDirectoryHandlerContextImpl } from '@theia/plugin-ext/lib/main/node/plugin-deployer-directory-handler-context-impl';
import { PluginVsCodeDirectoryHandler } from './plugin-vscode-directory-handler';
import { PluginDeployerResolverContextImpl } from '@theia/plugin-ext/lib/main/node/plugin-deployer-resolver-context-impl';

/**
* Resolver that handle the vscode: protocol
*/
@injectable()
export class VsCodePluginDeployerResolver implements PluginDeployerResolver {

@inject(PluginDeployerHandler)
protected readonly pluginDeployerHandler: PluginDeployerHandler;

private static PREFIX_VSCODE_EXTENSION = 'vscode:extension/';

private static PREFIX_EXT_INSTALL = 'ext install ';
Expand All @@ -40,6 +51,9 @@ export class VsCodePluginDeployerResolver implements PluginDeployerResolver {
'Accept': 'application/json;api-version=3.0-preview.1'
};

// All the plugins that are set to install
private toInstall = new Set();

private vscodeExtensionsFolder: string;
constructor() {
this.vscodeExtensionsFolder = process.env.VSCODE_PLUGINS || path.resolve(os.tmpdir(), 'vscode-extension-marketplace');
Expand Down Expand Up @@ -105,7 +119,11 @@ export class VsCodePluginDeployerResolver implements PluginDeployerResolver {

const shortName = extensionName.replace(/\W/g, '_');
const extensionPath = path.resolve(this.vscodeExtensionsFolder, path.basename(shortName + '.vsix'));
const finish = () => {
const finish = async () => {
const pluginEntry = new PluginDeployerEntryImpl(extensionName, originId, extensionPath);
pluginEntry.setResolvedBy((this as any).constructor.name);
this.toInstall.add(extensionName);
await this.downloadVSCodeExtension(pluginResolverContext, pluginEntry);
pluginResolverContext.addPlugin(originId, extensionPath);
resolve();
};
Expand All @@ -125,6 +143,40 @@ export class VsCodePluginDeployerResolver implements PluginDeployerResolver {

}

/**
* Download and resolve the extension so that we can inspect the extensionDependencies
*/
private async downloadVSCodeExtension(pluginResolverContext: PluginDeployerResolverContext, plugin: PluginDeployerEntry) {

const fileHandler = new PluginVsCodeFileHandler();
const proxyPluginDeployerEntry = new ProxyPluginDeployerEntry(fileHandler, plugin as PluginDeployerEntryImpl);
if (fileHandler.accept(proxyPluginDeployerEntry)) {
const pluginDeployerFileHandlerContext = new PluginDeployerFileHandlerContextImpl(proxyPluginDeployerEntry);
await fileHandler.handle(pluginDeployerFileHandlerContext);
}

const directoryHandler = new PluginVsCodeDirectoryHandler();
if (directoryHandler.accept(proxyPluginDeployerEntry)) {
const pluginDeployerDirectoryHandlerContext = new PluginDeployerDirectoryHandlerContextImpl(proxyPluginDeployerEntry);
await directoryHandler.handle(pluginDeployerDirectoryHandlerContext);
}

const deployDependencies = await this.pluginDeployerHandler.readDeployDependencies(plugin);

for (const depedency of deployDependencies) {
if (!this.toInstall.has(depedency)) {
const newPluginDeployerContext = new PluginDeployerResolverContextImpl(this, VsCodePluginDeployerResolver.PREFIX_VSCODE_EXTENSION + depedency);
await this.resolve(newPluginDeployerContext);
for (const availablePlugin of newPluginDeployerContext.getPlugins()) {
pluginResolverContext.addPlugin(depedency, availablePlugin.path());
}
}
}

this.toInstall.clear();
return Promise.resolve();
}

/**
* Handle only the plugins that starts with vscode:
*/
Expand Down
3 changes: 2 additions & 1 deletion packages/plugin-ext-vscode/src/node/scanner-vscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ export class VsCodePluginScanner extends TheiaPluginScanner implements PluginSca
},
entryPoint: {
backend: plugin.main
}
},
extensionDependencies: plugin.extensionDependencies
};
result.contributes = this.readContributions(plugin);
return result;
Expand Down
6 changes: 6 additions & 0 deletions packages/plugin-ext/src/common/plugin-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export interface PluginPackage {
description: string;
contributes?: PluginPackageContribution;
packagePath: string;
extensionDependencies?: string[];
}
export namespace PluginPackage {
export function toPluginUrl(pck: PluginPackage, relativePath: string): string {
Expand Down Expand Up @@ -242,6 +243,8 @@ export interface PluginDeployerResolverContext {

addPlugin(pluginId: string, path: string): void;

getPlugins(): PluginDeployerEntry[];

getOriginId(): string;

}
Expand Down Expand Up @@ -347,6 +350,7 @@ export interface PluginModel {
backend?: string;
};
contributes?: PluginContribution;
extensionDependencies?: string[];
}

/**
Expand Down Expand Up @@ -575,6 +579,8 @@ export const PluginDeployerHandler = Symbol('PluginDeployerHandler');
export interface PluginDeployerHandler {
deployFrontendPlugins(frontendPlugins: PluginDeployerEntry[]): Promise<void>;
deployBackendPlugins(backendPlugins: PluginDeployerEntry[]): Promise<void>;

readDeployDependencies(pluginsToBeInstalled: PluginDeployerEntry): Promise<string[]>
}

export const HostedPluginServer = Symbol('HostedPluginServer');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ export class HostedPluginDeployerHandler implements PluginDeployerHandler {
return this.currentBackendPluginsMetadata;
}

async readDeployDependencies(plugin: PluginDeployerEntry): Promise<string[]> {
const metadata = await this.reader.getPluginMetadata(plugin.path());
if (metadata) {
if (metadata.model.extensionDependencies) {
return metadata.model.extensionDependencies;
}
}
return [];
}

async deployFrontendPlugins(frontendPlugins: PluginDeployerEntry[]): Promise<void> {
for (const plugin of frontendPlugins) {
const metadata = await this.reader.getPluginMetadata(plugin.path());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ export class TheiaPluginScanner implements PluginScanner {
entryPoint: {
frontend: plugin.theiaPlugin!.frontend,
backend: plugin.theiaPlugin!.backend
}
},
extensionDependencies: plugin.extensionDependencies
};
result.contributes = this.readContributions(plugin);
return result;
Expand Down

0 comments on commit e9b6699

Please sign in to comment.