From 0fe8fa0e5451030fe26b5cccc870b26437be8f3c Mon Sep 17 00:00:00 2001 From: Roman Nikitenko Date: Wed, 19 Jun 2019 12:57:20 +0300 Subject: [PATCH] Export configurations of Che tasks to config file Signed-off-by: Roman Nikitenko --- .../src/che-task-backend-module.ts | 12 ++- .../src/export/export-configs-manager.ts | 47 +++------ .../src/export/launch-configs-exporter.ts | 89 ++++++++++++----- .../src/export/task-configs-exporter.ts | 95 +++++++++++++++---- .../src/extract/che-task-configs-extractor.ts | 34 +++++++ .../config-file-launch-configs-extractor.ts | 29 ++++++ .../config-file-task-configs-extractor.ts | 29 ++++++ .../vscode-launch-configs-extractor.ts | 48 ++++++++++ .../extract/vscode-task-configs-extractor.ts | 48 ++++++++++ .../task-plugin/src/task/che-task-provider.ts | 40 +------- plugins/task-plugin/src/task/converter.ts | 59 ++++++++++++ 11 files changed, 413 insertions(+), 117 deletions(-) create mode 100644 plugins/task-plugin/src/extract/che-task-configs-extractor.ts create mode 100644 plugins/task-plugin/src/extract/config-file-launch-configs-extractor.ts create mode 100644 plugins/task-plugin/src/extract/config-file-task-configs-extractor.ts create mode 100644 plugins/task-plugin/src/extract/vscode-launch-configs-extractor.ts create mode 100644 plugins/task-plugin/src/extract/vscode-task-configs-extractor.ts create mode 100644 plugins/task-plugin/src/task/converter.ts diff --git a/plugins/task-plugin/src/che-task-backend-module.ts b/plugins/task-plugin/src/che-task-backend-module.ts index 50c517325..c6ea5c373 100644 --- a/plugins/task-plugin/src/che-task-backend-module.ts +++ b/plugins/task-plugin/src/che-task-backend-module.ts @@ -24,7 +24,12 @@ import { PreviewUrlOpenService } from './preview/preview-url-open-service'; import { CheWorkspaceClient } from './che-workspace-client'; import { LaunchConfigurationsExporter } from './export/launch-configs-exporter'; import { TaskConfigurationsExporter } from './export/task-configs-exporter'; -import { ConfigurationsExporter, ExportConfigurationsManager } from './export/export-configs-manager'; +import { ExportConfigurationsManager, ConfigurationsExporter } from './export/export-configs-manager'; +import { CheTaskConfigsExtractor } from './extract/che-task-configs-extractor'; +import { ConfigFileLaunchConfigsExtractor } from './extract/config-file-launch-configs-extractor'; +import { ConfigFileTasksExtractor } from './extract/config-file-task-configs-extractor'; +import { VsCodeLaunchConfigsExtractor } from './extract/vscode-launch-configs-extractor'; +import { VsCodeTaskConfigsExtractor } from './extract/vscode-task-configs-extractor'; const container = new Container(); container.bind(CheTaskProvider).toSelf().inSingletonScope(); @@ -42,6 +47,11 @@ container.bind(PreviewUrlOpenService).toSelf().inSingletonScope(); container.bind(ConfigurationsExporter).to(TaskConfigurationsExporter).inSingletonScope(); container.bind(ConfigurationsExporter).to(LaunchConfigurationsExporter).inSingletonScope(); container.bind(ExportConfigurationsManager).toSelf().inSingletonScope(); +container.bind(CheTaskConfigsExtractor).toSelf().inSingletonScope(); +container.bind(ConfigFileTasksExtractor).toSelf().inSingletonScope(); +container.bind(ConfigFileLaunchConfigsExtractor).toSelf().inSingletonScope(); +container.bind(VsCodeLaunchConfigsExtractor).toSelf().inSingletonScope(); +container.bind(VsCodeTaskConfigsExtractor).toSelf().inSingletonScope(); container.bind(PreviewUrlsWidget).toSelf().inTransientScope(); container.bind(PreviewUrlsWidgetFactory).toDynamicValue(ctx => ({ diff --git a/plugins/task-plugin/src/export/export-configs-manager.ts b/plugins/task-plugin/src/export/export-configs-manager.ts index f9efaf2bb..f6c195ad0 100644 --- a/plugins/task-plugin/src/export/export-configs-manager.ts +++ b/plugins/task-plugin/src/export/export-configs-manager.ts @@ -18,15 +18,21 @@ export const ConfigurationsExporter = Symbol('ConfigurationsExporter'); /** Exports content with configurations in the config file */ export interface ConfigurationsExporter { - /** Type of the exporter corresponds to type of command which brings content with configs */ - readonly type: string; - /** - * Exports given content with configurations in the config file of given workspace folder - * @param configsContent content with configurations for export + * Exports configurations in the config file of given workspace folder * @param workspaceFolder workspace folder for exporting configs in the config file + * @param commands commands with configurations for export */ - export(configsContent: string, workspaceFolder: theia.WorkspaceFolder): void; + export(workspaceFolder: theia.WorkspaceFolder, commands: cheApi.workspace.Command[]): void; +} +/** Contains configurations as array of object and as raw content and is used at getting configurations from config file for example */ +export interface Configurations { + + /** Raw content with configurations from config file */ + content: string; + + /** Configurations as array of objects */ + configs: T[]; } /** Reads the commands from the current Che workspace and exports task and launch configurations in the config files. */ @@ -47,36 +53,13 @@ export class ExportConfigurationsManager { const cheCommands = await this.cheWorkspaceClient.getCommands(); for (const exporter of this.exporters) { - const configsContent = this.extractConfigsContent(exporter.type, cheCommands); - if (!configsContent) { - continue; - } - - this.exportContent(configsContent, exporter, workspaceFolders); + this.doExport(workspaceFolders, cheCommands, exporter); } } - private exportContent(configsContent: string, exporter: ConfigurationsExporter, workspaceFolders: theia.WorkspaceFolder[]) { + private doExport(workspaceFolders: theia.WorkspaceFolder[], cheCommands: cheApi.workspace.Command[], exporter: ConfigurationsExporter) { for (const workspaceFolder of workspaceFolders) { - exporter.export(configsContent, workspaceFolder); + exporter.export(workspaceFolder, cheCommands); } } - - private extractConfigsContent(type: string, commands: cheApi.workspace.Command[]): string { - const configCommands = commands.filter(command => command.type === type); - if (configCommands.length === 0) { - return ''; - } - - if (configCommands.length > 1) { - console.warn(`Found duplicate entry for type ${type}`); - } - - const configCommand = configCommands[0]; - if (!configCommand || !configCommand.attributes || !configCommand.attributes.actionReferenceContent) { - return ''; - } - - return configCommand.attributes.actionReferenceContent; - } } diff --git a/plugins/task-plugin/src/export/launch-configs-exporter.ts b/plugins/task-plugin/src/export/launch-configs-exporter.ts index caac93e81..2b40486c9 100644 --- a/plugins/task-plugin/src/export/launch-configs-exporter.ts +++ b/plugins/task-plugin/src/export/launch-configs-exporter.ts @@ -8,57 +8,96 @@ * SPDX-License-Identifier: EPL-2.0 **********************************************************************/ -import { injectable } from 'inversify'; +import { injectable, inject } from 'inversify'; import * as theia from '@theia/plugin'; +import { che as cheApi } from '@eclipse-che/api'; import { resolve } from 'path'; -import { readFileSync, writeFileSync, format, modify, parse } from '../utils'; +import { writeFileSync, modify } from '../utils'; import { ConfigurationsExporter } from './export-configs-manager'; +import { ConfigFileLaunchConfigsExtractor } from '../extract/config-file-launch-configs-extractor'; +import { VsCodeLaunchConfigsExtractor } from '../extract/vscode-launch-configs-extractor'; const CONFIG_DIR = '.theia'; const LAUNCH_CONFIG_FILE = 'launch.json'; const formattingOptions = { tabSize: 4, insertSpaces: true, eol: '' }; -export const VSCODE_LAUNCH_TYPE = 'vscode-launch'; - /** Exports content with launch configurations in the config file. */ @injectable() export class LaunchConfigurationsExporter implements ConfigurationsExporter { - readonly type: string = VSCODE_LAUNCH_TYPE; - export(configsContent: string, workspaceFolder: theia.WorkspaceFolder): void { + @inject(ConfigFileLaunchConfigsExtractor) + protected readonly configFileLaunchConfigsExtractor: ConfigFileLaunchConfigsExtractor; + + @inject(VsCodeLaunchConfigsExtractor) + protected readonly vsCodeLaunchConfigsExtractor: VsCodeLaunchConfigsExtractor; + + export(workspaceFolder: theia.WorkspaceFolder, commands: cheApi.workspace.Command[]): void { const launchConfigFileUri = this.getConfigFileUri(workspaceFolder.uri.path); - const existingContent = readFileSync(launchConfigFileUri); - if (configsContent === existingContent) { - return; - } + const configFileConfigs = this.configFileLaunchConfigsExtractor.extract(launchConfigFileUri); + const vsCodeConfigs = this.vsCodeLaunchConfigsExtractor.extract(commands); - const configsJson = parse(configsContent); - if (!configsJson || !configsJson.configurations) { + const configFileContent = configFileConfigs.content; + if (configFileContent) { + this.saveConfigs(launchConfigFileUri, configFileContent, this.merge(vsCodeConfigs.configs, configFileConfigs.configs)); return; } - const existingJson = parse(existingContent); - if (!existingJson || !existingJson.configurations) { - writeFileSync(launchConfigFileUri, format(configsContent, formattingOptions)); - return; + const vsCodeConfigsContent = vsCodeConfigs.content; + if (vsCodeConfigsContent) { + this.saveConfigs(launchConfigFileUri, vsCodeConfigsContent, vsCodeConfigs.configs); } - - const mergedConfigs = this.merge(existingJson.configurations, configsJson.configurations); - const result = modify(configsContent, ['configurations'], mergedConfigs, formattingOptions); - writeFileSync(launchConfigFileUri, result); } - private merge(existingConfigs: theia.DebugConfiguration[], newConfigs: theia.DebugConfiguration[]): theia.DebugConfiguration[] { - const result: theia.DebugConfiguration[] = Object.assign([], newConfigs); - for (const existing of existingConfigs) { - if (!newConfigs.some(config => config.name === existing.name)) { - result.push(existing); + private merge(configurations1: theia.DebugConfiguration[], configurations2: theia.DebugConfiguration[]): theia.DebugConfiguration[] { + const result: theia.DebugConfiguration[] = Object.assign([], configurations1); + + for (const config2 of configurations2) { + const conflict = configurations1.find(config1 => config1.name === config2.name); + if (!conflict) { + result.push(config2); + continue; + } + + if (this.areEqual(config2, conflict)) { + continue; } + + const newName = this.getUniqueName(config2.name, [...configurations1, ...configurations2]); + result.push({ ...config2, name: newName }); } + return result; } + private areEqual(config1: theia.DebugConfiguration, config2: theia.DebugConfiguration): boolean { + const { type: type1, name: name1, request: request1, ...properties1 } = config1; + const { type: type2, name: name2, request: request2, ...properties2 } = config2; + + if (type1 !== type2 || name1 !== name2 || request1 !== request2) { + return false; + } + + return JSON.stringify(properties1) === JSON.stringify(properties2); + } + + private getUniqueName(name: string, configs: theia.DebugConfiguration[]): string { + let counter = 1; + let newName = ''; + + do { + newName = `${name}_${counter}`; + counter++; + } while (configs.some(config => config.name === newName)); + + return newName; + } + private getConfigFileUri(rootDir: string): string { return resolve(rootDir.toString(), CONFIG_DIR, LAUNCH_CONFIG_FILE); } + + private saveConfigs(launchConfigFileUri: string, content: string, configurations: theia.DebugConfiguration[]) { + const result = modify(content, ['configurations'], configurations, formattingOptions); + writeFileSync(launchConfigFileUri, result); + } } diff --git a/plugins/task-plugin/src/export/task-configs-exporter.ts b/plugins/task-plugin/src/export/task-configs-exporter.ts index 55891d187..c903bf3b3 100644 --- a/plugins/task-plugin/src/export/task-configs-exporter.ts +++ b/plugins/task-plugin/src/export/task-configs-exporter.ts @@ -8,12 +8,16 @@ * SPDX-License-Identifier: EPL-2.0 **********************************************************************/ -import { injectable } from 'inversify'; +import { injectable, inject } from 'inversify'; import * as theia from '@theia/plugin'; +import { che as cheApi } from '@eclipse-che/api'; import { TaskConfiguration } from '@eclipse-che/plugin'; import { resolve } from 'path'; -import { readFileSync, writeFileSync, format, modify, parse } from '../utils'; +import { writeFileSync, modify } from '../utils'; +import { CheTaskConfigsExtractor } from '../extract/che-task-configs-extractor'; +import { VsCodeTaskConfigsExtractor } from '../extract/vscode-task-configs-extractor'; import { ConfigurationsExporter } from './export-configs-manager'; +import { ConfigFileTasksExtractor } from '../extract/config-file-task-configs-extractor'; const CONFIG_DIR = '.theia'; const TASK_CONFIG_FILE = 'tasks.json'; @@ -24,42 +28,91 @@ export const VSCODE_TASK_TYPE = 'vscode-task'; /** Exports configurations of tasks in the config file. */ @injectable() export class TaskConfigurationsExporter implements ConfigurationsExporter { - readonly type: string = VSCODE_TASK_TYPE; - export(tasksContent: string, workspaceFolder: theia.WorkspaceFolder): void { + @inject(ConfigFileTasksExtractor) + protected readonly configFileTasksExtractor: ConfigFileTasksExtractor; + + @inject(CheTaskConfigsExtractor) + protected readonly cheTaskConfigsExtractor: CheTaskConfigsExtractor; + + @inject(VsCodeTaskConfigsExtractor) + protected readonly vsCodeTaskConfigsExtractor: VsCodeTaskConfigsExtractor; + + export(workspaceFolder: theia.WorkspaceFolder, commands: cheApi.workspace.Command[]): void { const tasksConfigFileUri = this.getConfigFileUri(workspaceFolder.uri.path); - const existingContent = readFileSync(tasksConfigFileUri); - if (tasksContent === existingContent) { - return; - } + const configFileTasks = this.configFileTasksExtractor.extract(tasksConfigFileUri); + + const cheTasks = this.cheTaskConfigsExtractor.extract(commands); + const vsCodeTasks = this.vsCodeTaskConfigsExtractor.extract(commands); + const newConfigs = this.merge(vsCodeTasks.configs, cheTasks); - const tasksJson = parse(tasksContent); - if (!tasksJson || !tasksJson.tasks) { + const configFileContent = configFileTasks.content; + if (configFileContent) { + this.saveConfigs(tasksConfigFileUri, configFileContent, this.merge(newConfigs, configFileTasks.configs)); return; } - const existingJson = parse(existingContent); - if (!existingJson || !existingJson.tasks) { - writeFileSync(tasksConfigFileUri, format(tasksContent, formattingOptions)); + const vsCodeTasksContent = vsCodeTasks.content; + if (vsCodeTasksContent) { + this.saveConfigs(tasksConfigFileUri, vsCodeTasksContent, newConfigs); return; } - const mergedConfigs = this.merge(existingJson.tasks, tasksJson.tasks); - const result = modify(tasksContent, ['tasks'], mergedConfigs, formattingOptions); - writeFileSync(tasksConfigFileUri, result); + if (cheTasks) { + this.saveConfigs(tasksConfigFileUri, '', cheTasks); + } } - private merge(existingConfigs: TaskConfiguration[], newConfigs: TaskConfiguration[]): TaskConfiguration[] { - const result: TaskConfiguration[] = Object.assign([], newConfigs); - for (const existing of existingConfigs) { - if (!newConfigs.some(config => config.label === existing.label)) { - result.push(existing); + private merge(configurations1: TaskConfiguration[], configurations2: TaskConfiguration[]): TaskConfiguration[] { + const result: TaskConfiguration[] = Object.assign([], configurations1); + + for (const config2 of configurations2) { + const conflict = configurations1.find(config1 => config1.label === config2.label); + if (!conflict) { + result.push(config2); + continue; + } + + if (this.areEqual(config2, conflict)) { + continue; } + + const newLabel = this.getUniqueLabel(config2.label, [...configurations1, ...configurations2]); + result.push({ ...config2, label: newLabel }); } + return result; } + private areEqual(config1: TaskConfiguration, config2: TaskConfiguration): boolean { + const { type: type1, label: label1, ...properties1 } = config1; + const { type: type2, label: label2, ...properties2 } = config2; + + if (type1 !== type2 || label1 !== label2) { + return false; + } + + return JSON.stringify(properties1) === JSON.stringify(properties2); + } + + private getUniqueLabel(label: string, configs: TaskConfiguration[]): string { + let counter = 1; + let newLabel = ''; + + do { + newLabel = `${label}_${counter}`; + counter++; + } while (configs.some(config => config.label === newLabel)); + + return newLabel; + } + private getConfigFileUri(rootDir: string): string { return resolve(rootDir.toString(), CONFIG_DIR, TASK_CONFIG_FILE); } + + private saveConfigs(tasksConfigFileUri: string, content: string, configurations: TaskConfiguration[]) { + const result = modify(content, ['tasks'], configurations, formattingOptions); + writeFileSync(tasksConfigFileUri, result); + } } diff --git a/plugins/task-plugin/src/extract/che-task-configs-extractor.ts b/plugins/task-plugin/src/extract/che-task-configs-extractor.ts new file mode 100644 index 000000000..1ab2c9706 --- /dev/null +++ b/plugins/task-plugin/src/extract/che-task-configs-extractor.ts @@ -0,0 +1,34 @@ +/********************************************************************* + * Copyright (c) 2019 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 } from 'inversify'; +import { che as cheApi } from '@eclipse-che/api'; +import { TaskConfiguration } from '@eclipse-che/plugin'; +import { toTaskConfiguration } from '../task/converter'; +import { VSCODE_TASK_TYPE } from './vscode-task-configs-extractor'; +import { VSCODE_LAUNCH_TYPE } from './vscode-launch-configs-extractor'; + +/** Extracts CHE configurations of tasks. */ +@injectable() +export class CheTaskConfigsExtractor { + + extract(commands: cheApi.workspace.Command[]): TaskConfiguration[] { + // TODO filter should be changed according to task type after resolving https://github.com/eclipse/che/issues/12710 + const filteredCommands = commands.filter(command => + command.type !== VSCODE_TASK_TYPE && + command.type !== VSCODE_LAUNCH_TYPE); + + if (filteredCommands.length === 0) { + return []; + } + + return filteredCommands.map(command => toTaskConfiguration(command)); + } +} diff --git a/plugins/task-plugin/src/extract/config-file-launch-configs-extractor.ts b/plugins/task-plugin/src/extract/config-file-launch-configs-extractor.ts new file mode 100644 index 000000000..fcedd3206 --- /dev/null +++ b/plugins/task-plugin/src/extract/config-file-launch-configs-extractor.ts @@ -0,0 +1,29 @@ +/********************************************************************* + * Copyright (c) 2019 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 } from 'inversify'; +import * as theia from '@theia/plugin'; +import { parse, readFileSync } from '../utils'; +import { Configurations } from '../export/export-configs-manager'; + +/** Extracts launch configurations from config file by given uri. */ +@injectable() +export class ConfigFileLaunchConfigsExtractor { + + extract(launchConfigFileUri: string): Configurations { + const configsContent = readFileSync(launchConfigFileUri); + const configsJson = parse(configsContent); + if (!configsJson || !configsJson.configurations) { + return { content: '', configs: [] }; + } + + return { content: configsContent, configs: configsJson.configurations }; + } +} diff --git a/plugins/task-plugin/src/extract/config-file-task-configs-extractor.ts b/plugins/task-plugin/src/extract/config-file-task-configs-extractor.ts new file mode 100644 index 000000000..a8b54e528 --- /dev/null +++ b/plugins/task-plugin/src/extract/config-file-task-configs-extractor.ts @@ -0,0 +1,29 @@ +/********************************************************************* + * Copyright (c) 2019 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 } from 'inversify'; +import { parse, readFileSync } from '../utils'; +import { Configurations } from '../export/export-configs-manager'; +import { TaskConfiguration } from '@eclipse-che/plugin'; + +/** Extracts configurations of tasks from config file by given uri. */ +@injectable() +export class ConfigFileTasksExtractor { + + extract(tasksConfigFileUri: string): Configurations { + const tasksContent = readFileSync(tasksConfigFileUri); + const tasksJson = parse(tasksContent); + if (!tasksJson || !tasksJson.tasks) { + return { content: '', configs: [] }; + } + + return { content: tasksContent, configs: tasksJson.tasks }; + } +} diff --git a/plugins/task-plugin/src/extract/vscode-launch-configs-extractor.ts b/plugins/task-plugin/src/extract/vscode-launch-configs-extractor.ts new file mode 100644 index 000000000..a97824897 --- /dev/null +++ b/plugins/task-plugin/src/extract/vscode-launch-configs-extractor.ts @@ -0,0 +1,48 @@ +/********************************************************************* + * Copyright (c) 2019 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 } from 'inversify'; +import * as theia from '@theia/plugin'; +import { che as cheApi } from '@eclipse-che/api'; +import { parse } from '../utils'; +import { Configurations } from '../export/export-configs-manager'; + +export const VSCODE_LAUNCH_TYPE = 'vscode-launch'; + +/** Extracts vscode launch configurations. */ +@injectable() +export class VsCodeLaunchConfigsExtractor { + + extract(commands: cheApi.workspace.Command[]): Configurations { + const emptyContent: Configurations = { content: '', configs: [] }; + + const configCommands = commands.filter(command => command.type === VSCODE_LAUNCH_TYPE); + if (configCommands.length === 0) { + return emptyContent; + } + + if (configCommands.length > 1) { + console.warn(`Found duplicate entry with configurations for type ${VSCODE_LAUNCH_TYPE}`); + } + + const configCommand = configCommands[0]; + if (!configCommand || !configCommand.attributes || !configCommand.attributes.actionReferenceContent) { + return emptyContent; + } + + const launchConfigsContent = configCommand.attributes.actionReferenceContent; + const configsJson = parse(launchConfigsContent); + if (!configsJson || !configsJson.configurations) { + return emptyContent; + } + + return { content: launchConfigsContent, configs: configsJson.configurations }; + } +} diff --git a/plugins/task-plugin/src/extract/vscode-task-configs-extractor.ts b/plugins/task-plugin/src/extract/vscode-task-configs-extractor.ts new file mode 100644 index 000000000..fef1d5875 --- /dev/null +++ b/plugins/task-plugin/src/extract/vscode-task-configs-extractor.ts @@ -0,0 +1,48 @@ +/********************************************************************* + * Copyright (c) 2019 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 } from 'inversify'; +import { che as cheApi } from '@eclipse-che/api'; +import { parse } from '../utils'; +import { Configurations } from '../export/export-configs-manager'; +import { TaskConfiguration } from '@eclipse-che/plugin'; + +export const VSCODE_TASK_TYPE = 'vscode-task'; + +/** Extracts vscode configurations of tasks. */ +@injectable() +export class VsCodeTaskConfigsExtractor { + + extract(commands: cheApi.workspace.Command[]): Configurations { + const emptyContent = { content: '', configs: [] } as Configurations; + + const configCommands = commands.filter(command => command.type === VSCODE_TASK_TYPE); + if (configCommands.length === 0) { + return emptyContent; + } + + if (configCommands.length > 1) { + console.warn(`Found duplicate entry with configurations for type ${VSCODE_TASK_TYPE}`); + } + + const configCommand = configCommands[0]; + if (!configCommand || !configCommand.attributes || !configCommand.attributes.actionReferenceContent) { + return emptyContent; + } + + const tasksContent = configCommand.attributes.actionReferenceContent; + const tasksJson = parse(tasksContent); + if (!tasksJson || !tasksJson.tasks) { + return emptyContent; + } + + return { content: tasksContent, configs: tasksJson.tasks }; + } +} diff --git a/plugins/task-plugin/src/task/che-task-provider.ts b/plugins/task-plugin/src/task/che-task-provider.ts index 4276af215..c81d1c4b2 100644 --- a/plugins/task-plugin/src/task/che-task-provider.ts +++ b/plugins/task-plugin/src/task/che-task-provider.ts @@ -10,13 +10,10 @@ import { injectable, inject } from 'inversify'; import * as che from '@eclipse-che/plugin'; -import { che as cheApi } from '@eclipse-che/api'; import { Task } from '@theia/plugin'; -import { CHE_TASK_TYPE, MACHINE_NAME_ATTRIBUTE, PREVIEW_URL_ATTRIBUTE, WORKING_DIR_ATTRIBUTE, CheTaskDefinition, Target } from './task-protocol'; +import { CHE_TASK_TYPE, CheTaskDefinition, Target } from './task-protocol'; import { MachinesPicker } from '../machine/machines-picker'; import { CheWorkspaceClient } from '../che-workspace-client'; -import { VSCODE_LAUNCH_TYPE } from '../export/launch-configs-exporter'; -import { VSCODE_TASK_TYPE } from '../export/task-configs-exporter'; /** Reads the commands from the current Che workspace and provides it as Task Configurations. */ @injectable() @@ -28,11 +25,7 @@ export class CheTaskProvider { protected readonly cheWorkspaceClient!: CheWorkspaceClient; async provideTasks(): Promise { - const commands = await this.cheWorkspaceClient.getCommands(); - const filteredCommands = commands.filter(command => - command.type !== VSCODE_TASK_TYPE && - command.type !== VSCODE_LAUNCH_TYPE); - return filteredCommands.map(command => this.toTask(command)); + return []; } async resolveTask(task: Task): Promise { @@ -75,33 +68,4 @@ export class CheTaskProvider { execution: task.execution }; } - - private toTask(command: cheApi.workspace.Command): Task { - return { - definition: { - type: CHE_TASK_TYPE, - command: command.commandLine, - target: { - workingDir: this.getCommandAttribute(command, WORKING_DIR_ATTRIBUTE), - machineName: this.getCommandAttribute(command, MACHINE_NAME_ATTRIBUTE) - }, - previewUrl: this.getCommandAttribute(command, PREVIEW_URL_ATTRIBUTE) - }, - name: `${command.name}`, - source: CHE_TASK_TYPE, - }; - } - - private getCommandAttribute(command: cheApi.workspace.Command, attrName: string): string | undefined { - if (!command.attributes) { - return undefined; - } - - for (const attr in command.attributes) { - if (attr === attrName) { - return command.attributes[attr]; - } - } - return undefined; - } } diff --git a/plugins/task-plugin/src/task/converter.ts b/plugins/task-plugin/src/task/converter.ts new file mode 100644 index 000000000..3b6960e22 --- /dev/null +++ b/plugins/task-plugin/src/task/converter.ts @@ -0,0 +1,59 @@ +/********************************************************************* + * Copyright (c) 2019 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 { che as cheApi } from '@eclipse-che/api'; +import { Task } from '@theia/plugin'; +import { TaskConfiguration } from '@eclipse-che/plugin'; +import { CHE_TASK_TYPE, MACHINE_NAME_ATTRIBUTE, PREVIEW_URL_ATTRIBUTE, WORKING_DIR_ATTRIBUTE } from './task-protocol'; + +/** Converts the Che command to Theia Task Configuration */ +export function toTaskConfiguration(command: cheApi.workspace.Command): TaskConfiguration { + const taskConfig: TaskConfiguration = { + type: CHE_TASK_TYPE, + label: command.name, + command: command.commandLine, + target: { + workingDir: this.getCommandAttribute(command, WORKING_DIR_ATTRIBUTE), + machineName: this.getCommandAttribute(command, MACHINE_NAME_ATTRIBUTE) + }, + previewUrl: this.getCommandAttribute(command, PREVIEW_URL_ATTRIBUTE) + }; + return taskConfig; +} + +/** Converts the Che command to Task API object */ +export function toTask(command: cheApi.workspace.Command): Task { + return { + definition: { + type: CHE_TASK_TYPE, + command: command.commandLine, + target: { + workingDir: this.getCommandAttribute(command, WORKING_DIR_ATTRIBUTE), + machineName: this.getCommandAttribute(command, MACHINE_NAME_ATTRIBUTE) + }, + previewUrl: this.getCommandAttribute(command, PREVIEW_URL_ATTRIBUTE) + }, + name: `${command.name}`, + source: CHE_TASK_TYPE, + }; +} + +export function getCommandAttribute(command: cheApi.workspace.Command, attrName: string): string | undefined { + if (!command.attributes) { + return undefined; + } + + for (const attr in command.attributes) { + if (attr === attrName) { + return command.attributes[attr]; + } + } + return undefined; +}