Skip to content
This repository was archived by the owner on Apr 4, 2023. It is now read-only.
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**********************************************************************
* Copyright (c) 2021 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
***********************************************************************/

import { injectable, postConstruct } from 'inversify';

import { DebugConfigurationManager } from '@theia/debug/lib/browser/debug-configuration-manager';

@injectable()
export class CheDebugConfigurationManager extends DebugConfigurationManager {
@postConstruct()
protected async init(): Promise<void> {
super.init();

/**
* Theia creates a DebugConfigurationModel for each workspace folder in a workspace at starting the IDE.
* For the CHE multi-root workspace there no workspace folders at that step:
* CHE clones projects at starting the IDE and adds a workspace folder directly after cloning a project.
* That's why we need the following logic -
* DebugConfigurationManager should create the corresponding model when a workspace is changed (a workspace folder is added)
*/
this.workspaceService.onWorkspaceChanged(() => {
this.updateModels();
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ import {
} from '../common/che-protocol';
import { CheSideCarContentReaderRegistryImpl, CheSideCarResourceResolver } from './che-sidecar-resource';
import { CommandContribution, ResourceResolver } from '@theia/core/lib/common';
import { ContainerModule, interfaces } from 'inversify';
import { WebSocketConnectionProvider, WidgetFactory } from '@theia/core/lib/browser';

import { CheApiProvider } from './che-api-provider';
import { CheDebugConfigurationManager } from './che-debug-configuration-manager';
import { CheLanguagesMainTestImpl } from './che-languages-test-main';
import { ChePluginCommandContribution } from './plugin/che-plugin-command-contribution';
import { ChePluginFrontentService } from './plugin/che-plugin-frontend-service';
Expand All @@ -38,8 +40,8 @@ import { CheTaskClientImpl } from './che-task-client';
import { CheTaskResolver } from './che-task-resolver';
import { CheTaskTerminalWidgetManager } from './che-task-terminal-widget-manager';
import { CheWebviewEnvironment } from './che-webview-environment';
import { ContainerModule } from 'inversify';
import { ContainerPicker } from './container-picker';
import { DebugConfigurationManager } from '@theia/debug/lib/browser/debug-configuration-manager';
import { LanguagesMainFactory } from '@theia/plugin-ext';
import { MainPluginApiProvider } from '@theia/plugin-ext/lib/common/plugin-ext-api-contribution';
import { PluginFrontendViewContribution } from '@theia/plugin-ext/lib/main/browser/plugin-frontend-view-contribution';
Expand All @@ -50,7 +52,6 @@ import { TaskStatusHandler } from './task-status-handler';
import { TaskTerminalWidgetManager } from '@theia/task/lib/browser/task-terminal-widget-manager';
import { WebviewEnvironment } from '@theia/plugin-ext/lib/main/browser/webview/webview-environment';
import { bindChePluginPreferences } from './plugin/che-plugin-preferences';
import { interfaces } from 'inversify';

export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(CheApiProvider).toSelf().inSingletonScope();
Expand Down Expand Up @@ -124,4 +125,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
child.bind(RPCProtocol).toConstantValue(rpc);
return child.get(CheLanguagesMainTestImpl);
});

bind(CheDebugConfigurationManager).toSelf().inSingletonScope();
rebind(DebugConfigurationManager).to(CheDebugConfigurationManager).inSingletonScope();
});
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,22 @@ import pluginExtBackendModule from '@theia/plugin-ext/lib/plugin-ext-backend-mod
import pluginRemoteBackendModule from './plugin-remote-backend-module';
import pluginVscodeBackendModule from '@theia/plugin-ext-vscode/lib/node/plugin-vscode-backend-module';

const DEFAULT_THEIA_HOME_DIR = '/home/theia/';
const DEFAULT_THEIA_DEV_HOME_DIR = '/home/theia-dev';

interface CheckAliveWS extends ws {
alive: boolean;
}

function modifyPathToLocal(origPath: string): string {
return path.join(os.homedir(), origPath.substr(0, '/home/theia/'.length));
function modifyPathToLocal(originalPath: string): string {
if (originalPath.startsWith(DEFAULT_THEIA_HOME_DIR)) {
return path.join(os.homedir(), originalPath.substring(DEFAULT_THEIA_HOME_DIR.length));
}

if (originalPath.startsWith(DEFAULT_THEIA_DEV_HOME_DIR)) {
return path.join(os.homedir(), originalPath.substring(DEFAULT_THEIA_DEV_HOME_DIR.length));
}
return originalPath;
}

@injectable()
Expand Down Expand Up @@ -127,10 +137,22 @@ export class PluginRemoteInit {
const originalStart = PluginManagerExtImpl.prototype.$start;
PluginManagerExtImpl.prototype.$start = async function (params: PluginManagerStartParams): Promise<void> {
const { hostLogPath, hostStoragePath, hostGlobalStoragePath } = params.configStorage;

const overriddenLogPath = modifyPathToLocal(hostLogPath);
await fs.ensureDir(overriddenLogPath);

const overriddenStoragePath = hostStoragePath ? modifyPathToLocal(hostStoragePath) : undefined;
if (overriddenStoragePath) {
await fs.ensureDir(overriddenStoragePath);
}

const overriddenGlobalStoragePath = modifyPathToLocal(hostGlobalStoragePath);
await fs.ensureDir(overriddenGlobalStoragePath);

params.configStorage = {
hostLogPath: modifyPathToLocal(hostLogPath),
hostStoragePath: hostStoragePath ? modifyPathToLocal(hostStoragePath) : undefined,
hostGlobalStoragePath: modifyPathToLocal(hostGlobalStoragePath),
hostLogPath: overriddenLogPath,
hostStoragePath: overriddenStoragePath,
hostGlobalStoragePath: overriddenGlobalStoragePath,
};
// call original method
return originalStart.call(this, params);
Expand Down
4 changes: 3 additions & 1 deletion extensions/eclipse-che-theia-workspace/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"src"
],
"dependencies": {
"@theia/core": "next",
"@eclipse-che/api": "latest",
"@theia/workspace": "next",
"@eclipse-che/theia-remote-api": "^0.0.1",
Expand All @@ -31,7 +32,8 @@
"license": "EPL-2.0",
"theiaExtensions": [
{
"frontend": "lib/browser/che-workspace-module"
"frontend": "lib/browser/che-workspace-module",
"backend": "lib/node/workspace-backend-module"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**********************************************************************
* Copyright (c) 2021 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
***********************************************************************/

import * as React from 'react';

import { injectable } from 'inversify';

import { FileNavigatorWidget } from '@theia/navigator/lib/browser/navigator-widget';

@injectable()
export class CheFileNavigatorWidget extends FileNavigatorWidget {
protected renderEmptyMultiRootWorkspace(): React.ReactNode {
return (
<div className="theia-navigator-container">
<div className="center">No projects in the workspace yet</div>
</div>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,31 @@
*
* SPDX-License-Identifier: EPL-2.0
***********************************************************************/

import { CommandContribution, MenuContribution } from '@theia/core/lib/common';
import { Container, ContainerModule, interfaces } from 'inversify';
import { FileTree, FileTreeModel, FileTreeWidget, createFileTreeContainer } from '@theia/filesystem/lib/browser';
import {
FrontendApplicationContribution,
Tree,
TreeDecoratorService,
TreeModel,
TreeProps,
} from '@theia/core/lib/browser';
import {
NavigatorDecoratorService,
NavigatorTreeDecorator,
} from '@theia/navigator/lib/browser/navigator-decorator-service';

import { CheFileNavigatorWidget } from './che-navigator-widget';
import { CheWorkspaceContribution } from './che-workspace-contribution';
import { CheWorkspaceController } from './che-workspace-controller';
import { ContainerModule } from 'inversify';
import { ExplorerContribution } from './explorer-contribution';
import { FrontendApplicationContribution } from '@theia/core/lib/browser';
import { FILE_NAVIGATOR_PROPS } from '@theia/navigator/lib/browser/navigator-container';
import { FileNavigatorModel } from '@theia/navigator/lib/browser/navigator-model';
import { FileNavigatorTree } from '@theia/navigator/lib/browser/navigator-tree';
import { FileNavigatorWidget } from '@theia/navigator/lib/browser/navigator-widget';
import { QuickOpenCheWorkspace } from './che-quick-open-workspace';
import { bindContributionProvider } from '@theia/core/lib/common/contribution-provider';

export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(QuickOpenCheWorkspace).toSelf().inSingletonScope();
Expand All @@ -27,4 +43,33 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {

bind(ExplorerContribution).toSelf().inSingletonScope();
bind(FrontendApplicationContribution).to(ExplorerContribution);

rebind(FileNavigatorWidget).toDynamicValue(ctx => createFileNavigatorWidget(ctx.container));
});

export function createFileNavigatorContainer(parent: interfaces.Container): Container {
const child = createFileTreeContainer(parent);

child.unbind(FileTree);
child.bind(FileNavigatorTree).toSelf();
child.rebind(Tree).toService(FileNavigatorTree);

child.unbind(FileTreeModel);
child.bind(FileNavigatorModel).toSelf();
child.rebind(TreeModel).toService(FileNavigatorModel);

child.unbind(FileTreeWidget);
child.bind(CheFileNavigatorWidget).toSelf();

child.rebind(TreeProps).toConstantValue(FILE_NAVIGATOR_PROPS);

child.bind(NavigatorDecoratorService).toSelf().inSingletonScope();
child.rebind(TreeDecoratorService).toService(NavigatorDecoratorService);
bindContributionProvider(child, NavigatorTreeDecorator);

return child;
}

export function createFileNavigatorWidget(parent: interfaces.Container): CheFileNavigatorWidget {
return createFileNavigatorContainer(parent).get(CheFileNavigatorWidget);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**********************************************************************
* Copyright (c) 2021 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
***********************************************************************/

import * as fs from 'fs-extra';
import * as path from 'path';

import { Workspace, WorkspaceService } from '@eclipse-che/theia-remote-api/lib/common/workspace-service';
import { inject, injectable } from 'inversify';

import { DefaultWorkspaceServer } from '@theia/workspace/lib/node/default-workspace-server';
import { FileUri } from '@theia/core/lib/node';

interface TheiaWorkspace {
folders: TheiaWorkspacePath[];
}

interface TheiaWorkspacePath {
path: string;
}

@injectable()
export class CheWorkspaceServer extends DefaultWorkspaceServer {
@inject(WorkspaceService)
protected workspaceService: WorkspaceService;

// override any workspace that could have been defined through CLI and use entries from the devfile
// if not possible, use default method
protected async getRoot(): Promise<string | undefined> {
const workspace = await this.workspaceService.currentWorkspace();
if (!isMultiRoot(workspace)) {
return super.getRoot();
}

const projectsRootEnvVariable = process.env.CHE_PROJECTS_ROOT;
const projectsRoot = projectsRootEnvVariable ? projectsRootEnvVariable : '/projects';

// first, check if we have a che.theia-workspace file
const cheTheiaWorkspaceFile = path.resolve(projectsRoot, 'che.theia-workspace');
const cheTheiaWorkspaceFileUri = FileUri.create(cheTheiaWorkspaceFile);
const exists = await fs.pathExists(cheTheiaWorkspaceFile);
if (!exists) {
// no, then create the file
const theiaWorkspace: TheiaWorkspace = { folders: [] };
await fs.writeFile(cheTheiaWorkspaceFile, JSON.stringify(theiaWorkspace), { encoding: 'utf8' });
}

return cheTheiaWorkspaceFileUri.toString();
}
}

function isMultiRoot(workspace: Workspace): boolean {
const devfile = workspace.devfile;
return !!devfile && !!devfile.attributes && !!devfile.attributes.multiRoot && devfile.attributes.multiRoot === 'on';
}
11 changes: 11 additions & 0 deletions extensions/eclipse-che-theia-workspace/src/node/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**********************************************************************
* Copyright (c) 2021 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
***********************************************************************/

export * from './workspace-backend-module';
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**********************************************************************
* Copyright (c) 2021 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
***********************************************************************/

import { CheWorkspaceServer } from './che-workspace-server';
import { ContainerModule } from 'inversify';
import { WorkspaceServer } from '@theia/workspace/lib/common';

export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(CheWorkspaceServer).toSelf().inSingletonScope();
rebind(WorkspaceServer).toService(CheWorkspaceServer);
});
1 change: 1 addition & 0 deletions plugins/task-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"vscode-uri": "2.1.1",
"vscode-ws-jsonrpc": "0.2.0",
"ws": "^5.2.2",
"fs-extra": "^8.1.0",
"jsonc-parser": "^2.0.2"
}
}
3 changes: 2 additions & 1 deletion plugins/task-plugin/src/che-task-backend-module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**********************************************************************
* Copyright (c) 2019-2020 Red Hat, Inc.
* Copyright (c) 2019-2021 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -49,6 +49,7 @@ container.bind(ProjectPathVariableResolver).toSelf().inSingletonScope();
container.bind(CheWorkspaceClient).toSelf().inSingletonScope();
container.bind(CheTaskPreviewMode).toSelf().inSingletonScope();
container.bind(PreviewUrlOpenService).toSelf().inSingletonScope();
container.bind(LaunchConfigurationsExporter).toSelf().inSingletonScope();
container.bind<ConfigurationsExporter>(ConfigurationsExporter).to(TaskConfigurationsExporter).inSingletonScope();
container.bind<ConfigurationsExporter>(ConfigurationsExporter).to(LaunchConfigurationsExporter).inSingletonScope();
container.bind(ExportConfigurationsManager).toSelf().inSingletonScope();
Expand Down
17 changes: 14 additions & 3 deletions plugins/task-plugin/src/export/export-configs-manager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**********************************************************************
* Copyright (c) 2019-2020 Red Hat, Inc.
* Copyright (c) 2019-2021 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand All @@ -11,6 +11,7 @@
import { inject, injectable, multiInject } from 'inversify';

import { CheWorkspaceClient } from '../che-workspace-client';
import { LaunchConfigurationsExporter } from './launch-configs-exporter';
import { che as cheApi } from '@eclipse-che/api';

export const ConfigurationsExporter = Symbol('ConfigurationsExporter');
Expand Down Expand Up @@ -42,11 +43,21 @@ export class ExportConfigurationsManager {
@multiInject(ConfigurationsExporter)
protected readonly exporters: ConfigurationsExporter[];

@inject(LaunchConfigurationsExporter)
protected readonly launchConfigurationsExporter: LaunchConfigurationsExporter;

protected cheCommands: cheApi.workspace.Command[] = [];

async init(): Promise<void> {
this.cheCommands = await this.cheWorkspaceClient.getCommands();
this.launchConfigurationsExporter.init(this.cheCommands);
this.export();
}

async export(): Promise<void> {
const exportPromises = [];
const cheCommands = await this.cheWorkspaceClient.getCommands();
for (const exporter of this.exporters) {
exportPromises.push(this.doExport(cheCommands, exporter));
exportPromises.push(this.doExport(this.cheCommands, exporter));
}

await Promise.all(exportPromises);
Expand Down
Loading