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

Commit

Permalink
Add an ability to export devfile to file system
Browse files Browse the repository at this point in the history
Signed-off-by: Vladyslav Zhukovskyi <vzhukovs@redhat.com>
  • Loading branch information
vzhukovs committed Aug 26, 2020
1 parent cbe0f00 commit 4257550
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 4 deletions.
6 changes: 5 additions & 1 deletion extensions/eclipse-che-theia-workspace/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
"dependencies": {
"@eclipse-che/api": "latest",
"@theia/workspace": "next",
"@eclipse-che/theia-plugin-ext": "^0.0.1"
"@eclipse-che/theia-plugin-ext": "^0.0.1",
"js-yaml": "3.13.1"
},
"devDependencies": {
"@types/js-yaml": "3.11.2"
},
"scripts": {
"prepare": "yarn clean && yarn build",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ export namespace CheWorkspaceCommands {
category: WORKSPACE_CATEGORY,
label: 'Close Workspace'
};
export const SAVE_WORKSPACE_AS: Command = {
id: 'che.saveWorkspaceAs',
category: WORKSPACE_CATEGORY,
label: 'Save Workspace As...'
};
export const OPEN_WORKSPACE_ROOTS: Command & { dialogLabel: string } = {
id: 'workspace:openWorkspace',
category: FILE_CATEGORY,
Expand All @@ -51,6 +56,11 @@ export namespace CheWorkspaceCommands {
category: WORKSPACE_CATEGORY,
label: 'Close Workspace Roots'
};
export const SAVE_WORKSPACE_ROOTS_AS: Command = {
id: 'workspace:saveAs',
category: WORKSPACE_CATEGORY,
label: 'Save Workspace Roots As...'
};
}

@injectable()
Expand All @@ -69,6 +79,9 @@ export class CheWorkspaceContribution implements CommandContribution, MenuContri
commands.registerCommand(CheWorkspaceCommands.CLOSE_CURRENT_WORKSPACE, {
execute: () => this.workspaceController.closeCurrentWorkspace()
});
commands.registerCommand(CheWorkspaceCommands.SAVE_WORKSPACE_AS, {
execute: () => this.workspaceController.saveWorkspaceAs()
});

commands.unregisterCommand(WorkspaceCommands.OPEN_WORKSPACE);
commands.registerCommand(CheWorkspaceCommands.OPEN_WORKSPACE_ROOTS, {
Expand All @@ -83,6 +96,11 @@ export class CheWorkspaceContribution implements CommandContribution, MenuContri
isEnabled: () => this.workspaceService.opened,
execute: () => this.workspaceController.closeWorkspaceRoots()
});
commands.unregisterCommand(WorkspaceCommands.SAVE_WORKSPACE_AS);
commands.registerCommand(CheWorkspaceCommands.SAVE_WORKSPACE_ROOTS_AS, {
isEnabled: () => this.workspaceService.isMultiRootWorkspaceEnabled,
execute: () => this.workspaceController.saveWorkspaceRootsAs()
});
}

registerMenus(menus: MenuModelRegistry): void {
Expand All @@ -95,6 +113,9 @@ export class CheWorkspaceContribution implements CommandContribution, MenuContri
menus.unregisterMenuAction({
commandId: WorkspaceCommands.CLOSE.id
}, CommonMenus.FILE_CLOSE);
menus.unregisterMenuAction({
commandId: WorkspaceCommands.SAVE_WORKSPACE_AS.id
}, CommonMenus.FILE_OPEN);

menus.registerMenuAction(CommonMenus.FILE_OPEN, {
commandId: CheWorkspaceCommands.OPEN_WORKSPACE.id,
Expand Down Expand Up @@ -124,5 +145,15 @@ export class CheWorkspaceContribution implements CommandContribution, MenuContri
commandId: CheWorkspaceCommands.CLOSE_WORKSPACE_ROOTS.id,
label: CheWorkspaceCommands.CLOSE_WORKSPACE_ROOTS.label
});
menus.registerMenuAction(CommonMenus.FILE_OPEN, {
commandId: CheWorkspaceCommands.SAVE_WORKSPACE_AS.id,
label: CheWorkspaceCommands.SAVE_WORKSPACE_AS.label,
order: 'a30'
});
menus.registerMenuAction(CommonMenus.FILE_OPEN, {
commandId: CheWorkspaceCommands.SAVE_WORKSPACE_ROOTS_AS.id,
label: CheWorkspaceCommands.SAVE_WORKSPACE_ROOTS_AS.label,
order: 'a31'
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,23 @@
import { inject, injectable } from 'inversify';
import { CheApiService } from '@eclipse-che/theia-plugin-ext/lib/common/che-protocol';
import { che } from '@eclipse-che/api';
import { AbstractDialog, ConfirmDialog } from '@theia/core/lib/browser';
import { AbstractDialog, ConfirmDialog, DefaultUriLabelProviderContribution } from '@theia/core/lib/browser';
import { Message } from '@theia/core/lib/browser/widgets';
import { Key } from '@theia/core/lib/browser/keyboard/keys';
import { CheWorkspaceCommands } from './che-workspace-contribution';
import { QuickOpenCheWorkspace } from './che-quick-open-workspace';
import { FileDialogService, OpenFileDialogProps } from '@theia/filesystem/lib/browser';
import { FileDialogService, FileDialogTreeFilters, OpenFileDialogProps } from '@theia/filesystem/lib/browser';
import {
WorkspaceService,
WorkspacePreferences
} from '@theia/workspace/lib/browser';
import URI from '@theia/core/lib/common/uri';
import { FileSystem } from '@theia/filesystem/lib/common';
import { FileSystem, FileStat } from '@theia/filesystem/lib/common';
import { THEIA_EXT, VSCODE_EXT } from '@theia/workspace/lib/common';
import { QuickOpenWorkspace } from '@theia/workspace/lib/browser/quick-open-workspace';

const YAML = require('js-yaml');

export class StopWorkspaceDialog extends AbstractDialog<boolean | undefined> {
protected confirmed: boolean | undefined = true;
protected readonly dontStopButton: HTMLButtonElement;
Expand Down Expand Up @@ -85,6 +87,16 @@ export class CheWorkspaceController {
@inject(FileDialogService) protected readonly fileDialogService: FileDialogService;
@inject(FileSystem) protected readonly fileSystem: FileSystem;
@inject(WorkspacePreferences) protected preferences: WorkspacePreferences;
@inject(DefaultUriLabelProviderContribution) protected uriLabelProvider: DefaultUriLabelProviderContribution;

DEFAULT_FILE_FILTER: FileDialogTreeFilters = {
'Theia Workspace (*.theia-workspace)': [THEIA_EXT],
'VS Code Workspace (*.code-workspace)': [VSCODE_EXT]
};

DEVFILE_FILE_FILTER: FileDialogTreeFilters = {
'Che Workspace (devfile)': ['devfile.yaml']
};

async openWorkspace(): Promise<void> {
await this.doOpenWorkspace(false);
Expand Down Expand Up @@ -181,4 +193,99 @@ export class CheWorkspaceController {
};
}
}

async saveWorkspaceRootsAs(): Promise<void> {
let exist: boolean = false;
let overwrite: boolean = false;
let selected: URI | undefined;
do {
selected = await this.fileDialogService.showSaveDialog({
title: CheWorkspaceCommands.SAVE_WORKSPACE_AS.label!,
filters: this.DEFAULT_FILE_FILTER
});
if (selected) {
const displayName = this.uriLabelProvider.getName(selected);
if (displayName && !displayName.endsWith(`.${THEIA_EXT}`) && !displayName.endsWith(`.${VSCODE_EXT}`)) {
selected = selected.parent.resolve(`${displayName}.${THEIA_EXT}`);
}
exist = await this.fileSystem.exists(selected.toString());
if (exist) {
overwrite = await this.confirmOverwrite(selected);
}
}
} while (selected && exist && !overwrite);

if (selected) {
await this.workspaceService.save(selected);
}
}

private async confirmOverwrite(uri: URI): Promise<boolean> {
const confirmed = await new ConfirmDialog({
title: 'Overwrite',
msg: `Do you really want to overwrite "${uri.toString()}"?`
}).open();
return !!confirmed;
}

async saveWorkspaceAs(): Promise<void> {
let exist: boolean = false;
let overwrite: boolean = false;
let selected: URI | undefined;
do {
selected = await this.fileDialogService.showSaveDialog({
title: CheWorkspaceCommands.SAVE_WORKSPACE_AS.label!,
filters: this.DEVFILE_FILE_FILTER,
inputValue: 'devfile.yaml'
});
if (selected) {
exist = await this.fileSystem.exists(selected.toString());
if (exist) {
overwrite = await this.confirmOverwrite(selected);
}
}
} while (selected && exist && !overwrite);

if (selected) {
const workspace = await this.cheApi.currentWorkspace();
if (!workspace.devfile) {
return;
}

const devfileContent = YAML.safeDump(workspace.devfile);
await this.writeDevfileFile(selected, devfileContent);
}
}

private async writeDevfileFile(uri: URI, devfile: string): Promise<void> {
const uriStr = uri.toString();
if (!await this.fileSystem.exists(uriStr)) {
await this.fileSystem.createFile(uriStr);
}

const devfileStat = await this.toFileStat(uriStr);
if (devfileStat) {
await this.fileSystem.setContent(devfileStat, devfile);
}
}

private async toFileStat(uri: URI | string | undefined): Promise<FileStat | undefined> {
if (!uri) {
return undefined;
}
let uriStr = uri.toString();
try {
if (uriStr.endsWith('/')) {
uriStr = uriStr.slice(0, -1);
}
const normalizedUriStr = new URI(uriStr).normalizePath().toString();
const fileStat = await this.fileSystem.getFileStat(normalizedUriStr);
if (!fileStat) {
return undefined;
}
return fileStat;
} catch (error) {
return undefined;
}
}
}
1 change: 1 addition & 0 deletions extensions/eclipse-che-theia-workspace/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"extends": "../../configs/base.tsconfig.json",
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"lib": [
"es6",
"dom"
Expand Down

0 comments on commit 4257550

Please sign in to comment.