Skip to content
This repository has been archived by the owner on Apr 4, 2023. It is now read-only.

Commit

Permalink
An ability to switch (turn on and turn off ) multi-root mode on a dev…
Browse files Browse the repository at this point in the history
…file level

Signed-off-by: Roman Nikitenko <rnikiten@redhat.com>
  • Loading branch information
RomanNikitenko committed Feb 17, 2021
1 parent 49d0896 commit f08c3ea
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
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';
import { WorkspaceService } from '@eclipse-che/theia-remote-api/lib/common/workspace-service';

interface TheiaWorkspace {
folders: TheiaWorkspacePath[];
Expand All @@ -33,33 +33,29 @@ export class CheWorkspaceServer extends DefaultWorkspaceServer {
// 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> {
let projectsRoot: string;
if (process.env.CHE_PROJECTS_ROOT) {
projectsRoot = process.env.CHE_PROJECTS_ROOT;
} else {
projectsRoot = '/projects';
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) {
return FileUri.create(cheTheiaWorkspaceFile).toString();
}

// no, then create the file

const workspace = await this.workspaceService.currentWorkspace();
const devfile = workspace.devfile;
if (devfile) {
const projects = devfile.projects;
if (projects) {
const theiaWorkspace: TheiaWorkspace = { folders: [] };
await fs.writeFile(cheTheiaWorkspaceFile, JSON.stringify(theiaWorkspace), { encoding: 'utf8' });
return FileUri.create(cheTheiaWorkspaceFile).toString();
}
if (!exists) {
// no, then create the file
const theiaWorkspace: TheiaWorkspace = { folders: [] };
await fs.writeFile(cheTheiaWorkspaceFile, JSON.stringify(theiaWorkspace), { encoding: 'utf8' });
}

return super.getRoot();
return cheTheiaWorkspaceFileUri.toString();
}
}

function isMultiRoot(workspace: Workspace): boolean {
const devfile = workspace.devfile;
return !!devfile && !!devfile.attributes && !!devfile.attributes.multiRoot && devfile.attributes.multiRoot === 'on';
}
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
29 changes: 11 additions & 18 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 @@ -8,12 +8,10 @@
* SPDX-License-Identifier: EPL-2.0
***********************************************************************/

import * as startPoint from '../task-plugin-backend';
import * as theia from '@theia/plugin';

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 @@ -45,26 +43,21 @@ export class ExportConfigurationsManager {
@multiInject(ConfigurationsExporter)
protected readonly exporters: ConfigurationsExporter[];

init(): void {
this.export();
@inject(LaunchConfigurationsExporter)
protected readonly launchConfigurationsExporter: LaunchConfigurationsExporter;

theia.workspace.onDidChangeWorkspaceFolders(
event => {
const workspaceFolders = event.added;
if (workspaceFolders && workspaceFolders.length > 0) {
this.export();
}
},
undefined,
startPoint.getSubscriptions()
);
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
23 changes: 19 additions & 4 deletions plugins/task-plugin/src/export/launch-configs-exporter.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 @@ -8,6 +8,7 @@
* SPDX-License-Identifier: EPL-2.0
***********************************************************************/

import * as startPoint from '../task-plugin-backend';
import * as theia from '@theia/plugin';

import { ensureDirExists, modify, writeFile } from '../utils';
Expand All @@ -32,14 +33,28 @@ export class LaunchConfigurationsExporter implements ConfigurationsExporter {
@inject(VsCodeLaunchConfigsExtractor)
protected readonly vsCodeLaunchConfigsExtractor: VsCodeLaunchConfigsExtractor;

async export(commands: cheApi.workspace.Command[]): Promise<void> {
if (!theia.workspace.workspaceFolders) {
async init(commands: cheApi.workspace.Command[]): Promise<void> {
theia.workspace.onDidChangeWorkspaceFolders(
event => {
const workspaceFolders: theia.WorkspaceFolder[] | undefined = event.added;
if (workspaceFolders && workspaceFolders.length > 0) {
this.export(commands, workspaceFolders);
}
},
undefined,
startPoint.getSubscriptions()
);
}

async export(commands: cheApi.workspace.Command[], workspaceFolders?: theia.WorkspaceFolder[]): Promise<void> {
workspaceFolders = workspaceFolders ? workspaceFolders : theia.workspace.workspaceFolders;
if (!workspaceFolders) {
return;
}

const exportConfigsPromises: Promise<void>[] = [];

for (const workspaceFolder of theia.workspace.workspaceFolders) {
for (const workspaceFolder of workspaceFolders) {
exportConfigsPromises.push(this.doExport(workspaceFolder, commands));
}
await Promise.all(exportConfigsPromises);
Expand Down
82 changes: 59 additions & 23 deletions plugins/welcome-plugin/src/welcome-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**********************************************************************
* Copyright (c) 2020 Red Hat, Inc.
* Copyright (c) 2020-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 @@ -53,22 +53,33 @@ async function getHtmlForWebview(context: theia.PluginContext): Promise<string>
}

// Open Readme file is there is one
export async function handleReadmeFiles(roots: theia.WorkspaceFolder[]): Promise<void> {
// In case of only one workspace
if (roots && roots.length === 1) {
const children = await theia.workspace.findFiles('README.md', 'node_modules/**', 1);
const updatedChildren = children.filter((child: theia.Uri) => {
if (child.fsPath.indexOf('node_modules') === -1) {
return child;
}
});
export async function handleReadmeFiles(
readmeHandledCallback?: () => void,
roots?: theia.WorkspaceFolder[]
): Promise<void> {
roots = roots ? roots : theia.workspace.workspaceFolders;
if (!roots || roots.length < 1) {
return;
}

if (updatedChildren.length >= 1) {
const openPath = theia.Uri.parse(updatedChildren[0] + '?open-handler=code-editor-preview');
const doc: theia.TextDocument | undefined = await theia.workspace.openTextDocument(openPath);
if (doc) {
theia.window.showTextDocument(doc);
}
const children = await theia.workspace.findFiles('README.md', 'node_modules/**', 1);
const updatedChildren = children.filter((child: theia.Uri) => {
if (child.fsPath.indexOf('node_modules') === -1) {
return child;
}
});

if (updatedChildren.length < 1) {
return;
}

const openPath = theia.Uri.parse(updatedChildren[0] + '?open-handler=code-editor-preview');
const doc: theia.TextDocument | undefined = await theia.workspace.openTextDocument(openPath);
if (doc) {
theia.window.showTextDocument(doc);

if (readmeHandledCallback) {
readmeHandledCallback();
}
}
}
Expand Down Expand Up @@ -121,15 +132,40 @@ export function start(context: theia.PluginContext): void {
showWelcomePage = configuration.get(Settings.SHOW_WELCOME_PAGE);
}

if (showWelcomePage && theia.window.visibleTextEditors.length === 0) {
setTimeout(async () => {
addPanel(context);
if (!showWelcomePage || theia.window.visibleTextEditors.length > 0) {
return;
}

theia.workspace.onDidChangeWorkspaceFolders(event => {
handleReadmeFiles(event.added);
}, context.subscriptions);
}, 100);
addPanel(context);

let cloneSourcesDisposable: theia.Disposable | undefined = undefined;
const workspacePlugin = theia.plugins.getPlugin('Eclipse Che.@eclipse-che/workspace-plugin');
if (workspacePlugin) {
// it handles the case when the multi-root mode is OFF
// we should remove this logic when we switch to the multi-root mode is ON by default
cloneSourcesDisposable = workspacePlugin.exports.onDidCloneSources(
() => handleReadmeFiles(readmeHandledCallback),
undefined,
context.subscriptions
);
} else {
handleReadmeFiles();
}

// handles the case when the multi-root mode is ON
const changeWorkspaceFoldersDisposable = theia.workspace.onDidChangeWorkspaceFolders(
event => handleReadmeFiles(readmeHandledCallback, event.added),
undefined,
context.subscriptions
);

const readmeHandledCallback = () => {
changeWorkspaceFoldersDisposable.dispose();

if (cloneSourcesDisposable) {
cloneSourcesDisposable.dispose();
}
};
}

export function stop(): void {}
2 changes: 1 addition & 1 deletion plugins/workspace-plugin/src/workspace-folder-updater.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**********************************************************************
* Copyright (c) 2020 Red Hat, Inc.
* 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
Expand Down
31 changes: 16 additions & 15 deletions plugins/workspace-plugin/src/workspace-projects-manager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**********************************************************************
* Copyright (c) 2018-2020 Red Hat, Inc.
* Copyright (c) 2018-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 @@ -53,41 +53,37 @@ abstract class WorkspaceProjectsManager {
workspace = await che.workspace.getCurrentWorkspace();
}

const cloneCommandList = await this.selectProjectToCloneCommands(workspace);
const cloningPromise = this.executeCloneCommands(cloneCommandList);
const cloningPromise = this.executeCloneCommands(workspace);

theia.window.withProgress({ location: { viewId: 'explorer' } }, () => cloningPromise);
await cloningPromise;

this.ensureWorkspaceFolders(workspace);

await cloningPromise;
await this.startSyncWorkspaceProjects();
}

ensureWorkspaceFolders(workspace: cheApi.workspace.Workspace): void {
this.getProjects(workspace)
.map(project => this.getProjectPath(project))
.filter(projectPath => fs.existsSync(projectPath))
.forEach(projectPath => this.workspaceFolderUpdater.addWorkspaceFolder(projectPath));
}

private async executeCloneCommands(cloneCommandList: TheiaImportCommand[]): Promise<void> {
private async executeCloneCommands(workspace: cheApi.workspace.Workspace): Promise<void> {
const cloneCommandList = await this.selectProjectToCloneCommands(workspace);
if (cloneCommandList.length === 0) {
return;
}

theia.window.showInformationMessage('Che Workspace: Starting importing projects.');

const isMultiRoot = isMultiRootWorkspace(workspace);

const cloningPromises: PromiseLike<void>[] = [];
for (const cloneCommand of cloneCommandList) {
const cloningPromise = cloneCommand.execute();

cloningPromises.push(cloningPromise);

cloningPromise.then(() => this.workspaceFolderUpdater.addWorkspaceFolder(cloneCommand.getProjectPath()));
if (isMultiRoot) {
cloningPromise.then(() => this.workspaceFolderUpdater.addWorkspaceFolder(cloneCommand.getProjectPath()));
}
}

await Promise.all(cloningPromises);

theia.window.showInformationMessage('Che Workspace: Finished importing projects.');
onDidCloneSourcesEmitter.fire();
}
Expand Down Expand Up @@ -254,3 +250,8 @@ export class WorkspaceConfigProjectsManager extends WorkspaceProjectsManager {
);
}
}

function isMultiRootWorkspace(workspace: cheApi.workspace.Workspace): boolean {
const devfile = workspace.devfile;
return !!devfile && !!devfile.attributes && !!devfile.attributes.multiRoot && devfile.attributes.multiRoot === 'on';
}

0 comments on commit f08c3ea

Please sign in to comment.