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

Make Theia data folder name configurable #6650

Closed
wants to merge 8 commits 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
13 changes: 10 additions & 3 deletions packages/core/src/browser/preferences/preference-configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import { injectable, inject, named, interfaces } from 'inversify';
import URI from '../../common/uri';
import { ContributionProvider, bindContributionProvider } from '../../common/contribution-provider';
import { EnvVariablesServer } from '../../common/env-variables';

export const PreferenceConfiguration = Symbol('PreferenceConfiguration');
export interface PreferenceConfiguration {
Expand All @@ -34,9 +35,12 @@ export class PreferenceConfigurations {
@inject(ContributionProvider) @named(PreferenceConfiguration)
protected readonly provider: ContributionProvider<PreferenceConfiguration>;

@inject(EnvVariablesServer)
protected readonly envServer: EnvVariablesServer;

/* prefer Theia over VS Code by default */
getPaths(): string[] {
return ['.theia', '.vscode'];
async getPaths(): Promise<string[]> {
akosyakov marked this conversation as resolved.
Show resolved Hide resolved
return [await this.envServer.getDataFolderName(), '.vscode'];
}

getConfigName(): string {
Expand Down Expand Up @@ -71,7 +75,10 @@ export class PreferenceConfigurations {
return configUri.parent.path.base;
}

createUri(folder: URI, configPath: string = this.getPaths()[0], configName: string = this.getConfigName()): URI {
async createUri(folder: URI, configPath: string, configName: string = this.getConfigName()): Promise<URI> {
if (!configPath) {
Comment on lines +78 to +79
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This API change is odd.
Let's put aside, it was sync and now it is async, but earlier I could do

pc.createUri(myFolderUri)

Now I have to do

pc.createUri(myFolderUri, '') // Note the empty string

You ignored the default values. I guess we cannot avoid a breaking API change, then let's have a better API. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid passing of empty string we may default the argument to it. Just missed the usage. My PR changes many things...

configPath = (await this.getPaths())[0];
}
return folder.resolve(configPath).resolve(configName + '.json');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { interfaces } from 'inversify';
import { PreferenceProvider } from '../';
import { PreferenceScope } from '../preference-scope';
import { PreferenceProviderDataChanges, PreferenceProviderDataChange } from '../preference-provider';
import { EnvVariablesServer } from '../../../common/env-variables/env-variables-protocol';
import { MockEnvVariablesServerImpl } from '../../test/mock-env-variables-server';

export class MockPreferenceProvider extends PreferenceProvider {
readonly prefs: { [p: string]: any } = {};
Expand Down Expand Up @@ -50,6 +52,9 @@ export class MockPreferenceProvider extends PreferenceProvider {
export function bindMockPreferenceProviders(bind: interfaces.Bind, unbind: interfaces.Unbind): void {
unbind(PreferenceProvider);

// Needed for PreferenceConfigurations in PreferenceSchemaProvider
bind(EnvVariablesServer).to(MockEnvVariablesServerImpl).inSingletonScope();

bind(PreferenceProvider).toDynamicValue(ctx => new MockPreferenceProvider(PreferenceScope.User)).inSingletonScope().whenTargetNamed(PreferenceScope.User);
bind(PreferenceProvider).toDynamicValue(ctx => new MockPreferenceProvider(PreferenceScope.Workspace)).inSingletonScope().whenTargetNamed(PreferenceScope.Workspace);
bind(PreferenceProvider).toDynamicValue(ctx => new MockPreferenceProvider(PreferenceScope.Folder)).inSingletonScope().whenTargetNamed(PreferenceScope.Folder);
Expand Down
46 changes: 46 additions & 0 deletions packages/core/src/browser/test/mock-env-variables-server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/********************************************************************************
* Copyright (C) 2020 Red Hat, Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { injectable } from 'inversify';
import { EnvVariablesServer, EnvVariable } from '../../common/env-variables';

@injectable()
export class MockEnvVariablesServerImpl implements EnvVariablesServer {
async getDataFolderName(): Promise<string> {
return '.theia';
}

async getUserHomeFolder(): Promise<string> {
return 'file:///home/test';
}

async getUserDataFolder(): Promise<string> {
return 'file:///home/test/.theia';
}

getExecPath(): Promise<string> {
throw new Error('Method not implemented.');
}
getVariables(): Promise<EnvVariable[]> {
throw new Error('Method not implemented.');
}
getValue(key: string): Promise<EnvVariable | undefined> {
throw new Error('Method not implemented.');
}
getAppDataFolder(): Promise<string> {
throw new Error('Method not implemented.');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ export interface EnvVariablesServer {
getExecPath(): Promise<string>
getVariables(): Promise<EnvVariable[]>
getValue(key: string): Promise<EnvVariable | undefined>
getUserHomeFolder(): Promise<string>
getDataFolderName(): Promise<string>
getUserDataFolder(): Promise<string>
/** Windows specific. Returns system data folder of Theia. On other than Windows systems is the same as getUserDataFolder */
getAppDataFolder(): Promise<string>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need the app data folder? Is it required to comply with VS Code APIs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Windows VSCode uses AppData folder for some info.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is for VS Code compatibility, but we should understand it is better. I don't think it is something Windows or VS Code specific.

For instance, Electron distinguishes between the app folder (app.getPath('appData')) and the user folder (app.getPath('userData')), see https://github.com/electron/electron/blob/master/docs/api/app.md#appgetpathname. If I understand correctly former is used for place where program stores its files and second one where a program stores user files. If it is true, we should put it like that and list examples of files in comments.

@thegecko @mcgordonite Maybe you can shed some light on this question :) I think this PR is important for you, it is cleanly separates how to configure user folder for the concrete product.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is for VS Code compatibility

Can you please link the corresponding VS Code source? I couldn't find it with a text search for getAppDataFolder in the vscode repo.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

userData folder is simply the appData folder with the current application name at the end. It's not Windows specific.

e.g. on MacOS:

appData: ~/Library/Application Support
userData: ~/Library/Application Support/Mbed Studio (for example)

Copy link
Member

@akosyakov akosyakov Feb 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking that we use userData here bogusly. We probably should name it differently, user data it like where local storage (app state specific to user) is stored, not there settings or recent workspaces are stored.

Maybe we should call it appHome folder instead to avoid confusions with userData meaning from Electron? So there would be 4 folders:

  • userHome: ~
  • appHome = user home + home folder name: ~/.theia
  • appData: ~/Library/Application Support
  • userData = appData + productName: ~/Library/Application Support/Mbed Studio (for example)

Does it make sense?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mmorhun I'm a bit confused, I could not find a single client making use of getAppDataFolder. Did I overlook something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not find a single client making use of getAppDataFolder

That's why I have asked: why do we need it.

Copy link
Member

@akosyakov akosyakov Feb 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's keep a naming as it's and add js-docs:

  • userDataFolder controls a folder where user data like settings, recent workspaces and plugins are stored
  • appDataFolder controls a folder where app data are stored, like plugin logs and storages

btw PluginPathsServiceImpl.getLogsDirPath and PluginPathsServiceImpl.getWorkspaceStorageDirPath are bogus, they should use getAppDataFolder, not getUserDataFolder

Also getAppDataFolder implementation should be aligned with https://github.com/microsoft/vscode/blob/f3b191ab38fb9f1717ce5ce3396bb41204ffb399/src/paths.js#L18-L25, except bits of VSCODE_DATA, APP_DATA is Electron variable and USERPROFILE is windows variable, using homedir always is bogus

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've not seen it used, but you could imagine a company with multiple apps potentially sharing config data between them there?
I would be inclined to keep it and name it how an electron user would expect to see it.

}

export interface EnvVariable {
Expand Down
32 changes: 31 additions & 1 deletion packages/core/src/node/env-variables/env-variables-server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (C) 2018 Red Hat, Inc. and others.
* Copyright (C) 2018-2020 Red Hat, Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -14,9 +14,16 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import * as os from 'os';
import { injectable } from 'inversify';
import { EnvVariable, EnvVariablesServer } from '../../common/env-variables';
import { isWindows } from '../../common/os';
import { FileUri } from '../file-uri';

const THEIA_DATA_FOLDER = '.theia';
mmorhun marked this conversation as resolved.
Show resolved Hide resolved

const WINDOWS_APP_DATA_DIR = 'AppData';
const WINDOWS_ROAMING_DIR = 'Roaming';

@injectable()
export class EnvVariablesServerImpl implements EnvVariablesServer {
Expand Down Expand Up @@ -44,4 +51,27 @@ export class EnvVariablesServerImpl implements EnvVariablesServer {
}
return this.envs[key];
}

async getUserHomeFolder(): Promise<string> {
return FileUri.create(os.homedir()).toString();
}

async getDataFolderName(): Promise<string> {
return THEIA_DATA_FOLDER;
}

async getUserDataFolder(): Promise<string> {
return FileUri.create(await this.getUserHomeFolder()).resolve(await this.getDataFolderName()).toString();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two awaits do not depend on each other:

    async getUserDataFolder(): Promise<string> {
        const [home, data] = await Promise.all([
            this.getUserHomeFolder(),
            this.getDataFolderName()
        ]);
        return FileUri.create(home).resolve(data).toString();
    }

}

async getAppDataFolder(): Promise<string> {
const dataFolderUriBuilder = FileUri.create(await this.getUserHomeFolder());
if (isWindows) {
dataFolderUriBuilder.resolve(WINDOWS_APP_DATA_DIR);
dataFolderUriBuilder.resolve(WINDOWS_ROAMING_DIR);
mmorhun marked this conversation as resolved.
Show resolved Hide resolved
}
dataFolderUriBuilder.resolve(await this.getDataFolderName());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, please check and tell me if I have overlooked something.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, will fix

return dataFolderUriBuilder.toString();
}

}
3 changes: 3 additions & 0 deletions packages/core/src/node/file-uri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export namespace FileUri {
return fsPathFromVsCodeUri + '\\';
}
}
if (fsPathFromVsCodeUri.startsWith('/file:')) {
return fsPathFromVsCodeUri.substring('/file:'.length);
}
return fsPathFromVsCodeUri;
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/debug/src/browser/debug-configuration-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ export class DebugConfigurationManager {
if (configUri && configUri.path.base === 'launch.json') {
uri = configUri;
} else { // fallback
uri = new URI(model.workspaceFolderUri).resolve(`${this.preferenceConfigurations.getPaths()[0]}/launch.json`);
uri = new URI(model.workspaceFolderUri).resolve((await this.preferenceConfigurations.getPaths())[0] + '/launch.json');
}
const debugType = await this.selectDebugType();
const configurations = debugType ? await this.provideDebugConfigurations(debugType, model.workspaceFolderUri) : [];
Expand Down
7 changes: 4 additions & 3 deletions packages/java/src/node/java-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import * as os from 'os';
import * as path from 'path';
import * as glob from 'glob';
import { Socket } from 'net';
import { injectable, inject, named } from 'inversify';
import { Message, isRequestMessage } from 'vscode-ws-jsonrpc';
import { InitializeParams, InitializeRequest } from 'vscode-languageserver-protocol';
import { createSocketConnection } from 'vscode-ws-jsonrpc/lib/server';
import { DEBUG_MODE } from '@theia/core/lib/node';
import { DEBUG_MODE, FileUri } from '@theia/core/lib/node';
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
import { IConnection, BaseLanguageServerContribution, LanguageServerStartOptions } from '@theia/languages/lib/node';
import { JAVA_LANGUAGE_ID, JAVA_LANGUAGE_NAME, JavaStartParams } from '../common';
import { JavaCliContribution } from './java-cli-contribution';
Expand Down Expand Up @@ -52,6 +52,7 @@ export class JavaContribution extends BaseLanguageServerContribution {
protected readonly ready: Promise<void>;

constructor(
@inject(EnvVariablesServer) protected readonly envServer: EnvVariablesServer,
@inject(JavaCliContribution) protected readonly cli: JavaCliContribution,
@inject(ContributionProvider) @named(JavaExtensionContribution)
protected readonly contributions: ContributionProvider<JavaExtensionContribution>
Expand Down Expand Up @@ -103,7 +104,7 @@ export class JavaContribution extends BaseLanguageServerContribution {
this.activeDataFolders.add(dataFolderSuffix);
clientConnection.onClose(() => this.activeDataFolders.delete(dataFolderSuffix));

const workspacePath = path.resolve(os.homedir(), '.theia', 'jdt.ls', '_ws_' + dataFolderSuffix);
const workspacePath = path.resolve(FileUri.fsPath(await this.envServer.getUserDataFolder()), 'jdt.ls', '_ws_' + dataFolderSuffix);
const configuration = configurations.get(process.platform);
if (!configuration) {
throw new Error('Cannot find Java server configuration for ' + process.platform);
Expand Down
9 changes: 8 additions & 1 deletion packages/plugin-ext/src/common/plugin-api-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ import { ArgumentProcessor } from '../plugin/command-registry';
import { MaybePromise } from '@theia/core/lib/common/types';
import { QuickOpenItem, QuickOpenItemOptions } from '@theia/core/lib/common/quick-open-model';
import { QuickTitleButton } from '@theia/core/lib/common/quick-open-model';
import { EnvVariable } from '@theia/core/lib/common/env-variables';

export interface PreferenceData {
[scope: number]: any;
Expand All @@ -95,7 +96,7 @@ export interface Plugin {
export interface ConfigStorage {
hostLogPath: string;
hostStoragePath?: string;
hostGlobalStoragePath?: string;
hostGlobalStoragePath: string;
}

export interface EnvInit {
Expand Down Expand Up @@ -992,7 +993,13 @@ export interface DocumentsMain {

export interface EnvMain {
$getEnvVariable(envVarName: string): Promise<string | undefined>;
$getAllEnvVariables(): Promise<EnvVariable[]>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure why new APIs are necessary. Do you implement some VS Code API with them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably I changed formatting or so for this line. It was added long time ago.

Copy link
Member

@akosyakov akosyakov Feb 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean, there are no such APIs on master

export interface EnvMain {
$getEnvVariable(envVarName: string): Promise<string | undefined>;
$getClientOperatingSystem(): Promise<theia.OperatingSystem>;
}
and there is no formatting and whitespace changes

Copy link
Contributor Author

@mmorhun mmorhun Feb 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My mistake, sorry.

$getClientOperatingSystem(): Promise<theia.OperatingSystem>;
$getExecPath(): Promise<string>
$getUserHomeFolderPath(): Promise<string>
$getDataFolderName(): Promise<string>
$getUserDataFolderPath(): Promise<string>
$getAppDataPath(): Promise<string>
}

export interface PreferenceRegistryMain {
Expand Down
35 changes: 30 additions & 5 deletions packages/plugin-ext/src/hosted/browser/hosted-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ import { injectable, inject, interfaces, named, postConstruct } from 'inversify'
import { PluginWorker } from '../../main/browser/plugin-worker';
import { PluginMetadata, getPluginId, HostedPluginServer, DeployedPlugin } from '../../common/plugin-protocol';
import { HostedPluginWatcher } from './hosted-plugin-watcher';
import { MAIN_RPC_CONTEXT, PluginManagerExt } from '../../common/plugin-api-rpc';
import { MAIN_RPC_CONTEXT, PluginManagerExt, ConfigStorage } from '../../common/plugin-api-rpc';
import { setUpPluginApi } from '../../main/browser/main-context';
import { RPCProtocol, RPCProtocolImpl } from '../../common/rpc-protocol';
import {
Disposable, DisposableCollection,
ILogger, ContributionProvider, CommandRegistry, WillExecuteCommandEvent,
CancellationTokenSource, JsonRpcProxy, ProgressService
CancellationTokenSource, JsonRpcProxy, ProgressService, Path
} from '@theia/core';
import { PreferenceServiceImpl, PreferenceProviderProvider } from '@theia/core/lib/browser/preferences';
import { WorkspaceService } from '@theia/workspace/lib/browser';
Expand All @@ -47,6 +47,7 @@ import { Deferred } from '@theia/core/lib/common/promise-util';
import { DebugSessionManager } from '@theia/debug/lib/browser/debug-session-manager';
import { DebugConfigurationManager } from '@theia/debug/lib/browser/debug-configuration-manager';
import { WaitUntilEvent } from '@theia/core/lib/common/event';
import { FileSystem } from '@theia/filesystem/lib/common';
import { FileSearchService } from '@theia/file-search/lib/common/file-search-service';
import { Emitter, isCancelled } from '@theia/core';
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
Expand All @@ -56,6 +57,7 @@ import { WebviewEnvironment } from '../../main/browser/webview/webview-environme
import { WebviewWidget } from '../../main/browser/webview/webview';
import { WidgetManager } from '@theia/core/lib/browser/widget-manager';
import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service';
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';

export type PluginHost = 'frontend' | string;
export type DebugActivationEvent = 'onDebugResolve' | 'onDebugInitialConfigurations' | 'onDebugAdapterProtocolTracker';
Expand Down Expand Up @@ -109,6 +111,9 @@ export class HostedPluginSupport {
@inject(DebugConfigurationManager)
protected readonly debugConfigurationManager: DebugConfigurationManager;

@inject(FileSystem)
protected readonly fileSystem: FileSystem;

@inject(FileSearchService)
protected readonly fileSearchService: FileSearchService;

Expand Down Expand Up @@ -136,6 +141,9 @@ export class HostedPluginSupport {
@inject(TerminalService)
protected readonly terminalService: TerminalService;

@inject(EnvVariablesServer)
protected readonly envServer: EnvVariablesServer;

private theiaReadyPromise: Promise<any>;

protected readonly managers = new Map<string, PluginManagerExt>();
Expand Down Expand Up @@ -330,15 +338,20 @@ export class HostedPluginSupport {
let started = 0;
const startPluginsMeasurement = this.createMeasurement('startPlugins');

const [hostLogPath, hostStoragePath] = await Promise.all([
const [hostLogPath, hostStoragePath, hostGlobalStoragePath] = await Promise.all([
this.pluginPathsService.getHostLogPath(),
this.getStoragePath()
this.getStoragePath(),
this.getHostGlobalStoragePath()
]);
if (toDisconnect.disposed) {
return;
}
const thenable: Promise<void>[] = [];
const configStorage = { hostLogPath, hostStoragePath };
const configStorage: ConfigStorage = {
hostLogPath: hostLogPath!,
hostStoragePath: hostStoragePath,
hostGlobalStoragePath: hostGlobalStoragePath!
};
for (const [host, hostContributions] of contributionsByHost) {
const manager = await this.obtainManager(host, hostContributions, toDisconnect);
if (!manager) {
Expand Down Expand Up @@ -456,6 +469,18 @@ export class HostedPluginSupport {
return this.pluginPathsService.getHostStoragePath(this.workspaceService.workspace, roots);
}

protected async getHostGlobalStoragePath(): Promise<string> {
const userDataFolderPath: string = (await this.fileSystem.getFsPath(await this.envServer.getUserDataFolder()))!;
const globalStorageFolderPath = new Path(userDataFolderPath).join('globalStorage').toString();

// Make sure that folder by the path exists
if (! await this.fileSystem.exists(globalStorageFolderPath)) {
Copy link
Member

@akosyakov akosyakov Feb 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remote Theia APIs accept URIs, not paths

await this.fileSystem.createFolder(globalStorageFolderPath);
}

return globalStorageFolderPath;
}

async activateByEvent(activationEvent: string): Promise<void> {
if (this.activationEvents.has(activationEvent)) {
return;
Expand Down
27 changes: 26 additions & 1 deletion packages/plugin-ext/src/main/browser/env-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
********************************************************************************/

import { interfaces } from 'inversify';
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
import { EnvVariablesServer, EnvVariable } from '@theia/core/lib/common/env-variables';
import { RPCProtocol } from '../../common/rpc-protocol';
import { EnvMain } from '../../common/plugin-api-rpc';
import { QueryParameters } from '../../common/env';
import { isWindows, isOSX } from '@theia/core';
import { OperatingSystem } from '../../plugin/types-impl';

export class EnvMainImpl implements EnvMain {

private envVariableServer: EnvVariablesServer;

constructor(rpc: RPCProtocol, container: interfaces.Container) {
Expand All @@ -33,6 +34,10 @@ export class EnvMainImpl implements EnvMain {
return this.envVariableServer.getValue(envVarName).then(result => result ? result.value : undefined);
}

$getAllEnvVariables(): Promise<EnvVariable[]> {
return this.envVariableServer.getVariables();
}

async $getClientOperatingSystem(): Promise<OperatingSystem> {
if (isWindows) {
return OperatingSystem.Windows;
Expand All @@ -42,6 +47,26 @@ export class EnvMainImpl implements EnvMain {
}
return OperatingSystem.Linux;
}

$getExecPath(): Promise<string> {
return this.envVariableServer.getExecPath();
}

$getUserHomeFolderPath(): Promise<string> {
return this.envVariableServer.getUserHomeFolder();
}

$getDataFolderName(): Promise<string> {
return this.envVariableServer.getDataFolderName();
}

$getUserDataFolderPath(): Promise<string> {
return this.envVariableServer.getUserDataFolder();
}

$getAppDataPath(): Promise<string> {
return this.envVariableServer.getAppDataFolder();
}
}

/**
Expand Down
Loading