Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugin-ext: lookup plugins in user home dir #7086

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Change Log

## v0.16.0

- [plugin-ext] Plugins are now looked up in `$HOME/.theia/extensions` by default.
- [plugin-ext] You can specify lookup paths for plugins from the `BackendApplicationConfig.plugins` entry.

## v0.15.0

- [application-manager] added config to disable reloading windows [#6981](https://github.com/eclipse-theia/theia/pull/6981)
Expand Down
8 changes: 8 additions & 0 deletions packages/plugin-ext/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Theia - Theia - Plugin API

You can configure paths to folders containing plugins:

- Environment variables: `DEFAULT_THEIA_PLUGINS`, `THEIA_PLUGINS`. Use comma-separated paths.
- CLI argument: `--plugins`. Use comma-separated paths.
- Backend configuration: `plugins` entry. Array or single string.

Use the `local-dir:` file scheme to refer to paths on your local disk (where the backend is hosted).

See [here](https://www.theia-ide.org/doc/index.html) for a detailed documentation.

## License
Expand Down
41 changes: 39 additions & 2 deletions packages/plugin-ext/src/main/node/plugin-deployer-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import { injectable, optional, multiInject, inject } from 'inversify';
import { PluginPathsService } from '../common/plugin-paths-protocol';
import {
PluginDeployerResolver, PluginDeployerFileHandler, PluginDeployerDirectoryHandler,
PluginDeployerEntry, PluginDeployer, PluginDeployerResolverInit, PluginDeployerFileHandlerContext,
Expand All @@ -30,9 +31,11 @@ import {
import { ProxyPluginDeployerEntry } from './plugin-deployer-proxy-entry-impl';
import { PluginDeployerFileHandlerContextImpl } from './plugin-deployer-file-handler-context-impl';
import { PluginDeployerDirectoryHandlerContextImpl } from './plugin-deployer-directory-handler-context-impl';
import { BackendApplicationConfigProvider } from '@theia/core/lib/node/backend-application-config-provider';
import { ILogger, Emitter } from '@theia/core';
import { PluginCliContribution } from './plugin-cli-contribution';
import { performance } from 'perf_hooks';
import * as path from 'path';

@injectable()
export class PluginDeployerImpl implements PluginDeployer {
Expand All @@ -49,6 +52,9 @@ export class PluginDeployerImpl implements PluginDeployer {
@inject(PluginCliContribution)
protected readonly cliContribution: PluginCliContribution;

@inject(PluginPathsService)
protected readonly pluginPathsService: PluginPathsService;

/**
* Inject all plugin resolvers found at runtime.
*/
Expand Down Expand Up @@ -91,24 +97,55 @@ export class PluginDeployerImpl implements PluginDeployer {

// check THEIA_DEFAULT_PLUGINS or THEIA_PLUGINS env var
const defaultPluginsValue = process.env.THEIA_DEFAULT_PLUGINS || undefined;
const pluginsValueViaConfig = BackendApplicationConfigProvider.get().plugins;
const pluginsValue = process.env.THEIA_PLUGINS || undefined;
// check the `--plugins` CLI option
const defaultPluginsValueViaCli = this.cliContribution.localDir();

this.logger.debug('Found the list of default plugins ID on env:', defaultPluginsValue);
this.logger.debug('Found the list of plugins ID from config:', pluginsValueViaConfig);
this.logger.debug('Found the list of plugins ID on env:', pluginsValue);
this.logger.debug('Found the list of default plugins ID from CLI:', defaultPluginsValueViaCli);

// transform it to array
const defaultPluginIdList = defaultPluginsValue ? defaultPluginsValue.split(',') : [];
const pluginIdList = pluginsValue ? pluginsValue.split(',') : [];
const pluginsList = defaultPluginIdList.concat(pluginIdList).concat(defaultPluginsValueViaCli ? defaultPluginsValueViaCli.split(',') : []);
const pluginIdListViaConfig = await this.validatePluginIdListViaConfig(pluginsValueViaConfig);
const pluginIdListViaCli = defaultPluginsValueViaCli ? defaultPluginsValueViaCli.split(',') : [];
const pluginsList = await this.resolvePluginIdList([pluginIdListViaCli, pluginIdList, pluginIdListViaConfig, defaultPluginIdList]);

const startDeployTime = performance.now();
await this.deployMultipleEntries(pluginsList);
this.logMeasurement('Deploy plugins list', startDeployTime);
}

/**
* @param plugins BackendApplicationConfig.plugins
*/
protected async validatePluginIdListViaConfig(plugins: any): Promise<string[]> {
if (!plugins) {
return [];
} else if (typeof plugins === 'string') {
return [plugins];
} else if (Array.isArray(plugins)) {
return plugins;
} else {
throw new TypeError(`expected pluginFolder to be "string | string[]", got "${typeof plugins}"`);
}
}

/**
* Puts together user-configurable and non-user-configurable plugin paths.
*
* @param pluginIdLists
*/
protected async resolvePluginIdList(pluginIdLists: string[][]): Promise<string[]> {
return ([] as string[]).concat(
[`local-dir:${path.join(await this.pluginPathsService.getTheiaDirPath(), 'extensions')}`],
...pluginIdLists
);
}

public async deploy(pluginEntry: string): Promise<void> {
const startDeployTime = performance.now();
await this.deployMultipleEntries([pluginEntry]);
Expand All @@ -121,7 +158,7 @@ export class PluginDeployerImpl implements PluginDeployer {

let queue = [...pluginEntries];
while (queue.length) {
const dependenciesChunk: Array< Map<string, string>> = [];
const dependenciesChunk: Array<Map<string, string>> = [];
const workload: string[] = [];
while (queue.length) {
const current = queue.shift()!;
Expand Down