From bf93b2910d8fcee7e3a9f9768194f49191fb552f Mon Sep 17 00:00:00 2001 From: Vlad Arama <86936229+vladarama@users.noreply.github.com> Date: Fri, 17 Nov 2023 11:00:38 -0500 Subject: [PATCH] core: enable portable-mode (#12690) Signed-off-by: Vlad Arama --- .../electron-main-application.ts | 17 ++++++++++++++ .../env-variables/env-variables-server.ts | 22 ++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/core/src/electron-main/electron-main-application.ts b/packages/core/src/electron-main/electron-main-application.ts index 66d6ba1db7ff1..a6b6ce5a9d7e0 100644 --- a/packages/core/src/electron-main/electron-main-application.ts +++ b/packages/core/src/electron-main/electron-main-application.ts @@ -20,6 +20,7 @@ import * as path from 'path'; import { Argv } from 'yargs'; import { AddressInfo } from 'net'; import { promises as fs } from 'fs'; +import { existsSync, mkdirSync } from 'fs-extra'; import { fork, ForkOptions } from 'child_process'; import { DefaultTheme, FrontendApplicationConfig } from '@theia/application-package/lib/application-props'; import URI from '../common/uri'; @@ -171,6 +172,8 @@ export class ElectronMainApplication { @inject(TheiaElectronWindowFactory) protected readonly windowFactory: TheiaElectronWindowFactory; + protected isPortable = this.makePortable(); + protected readonly electronStore = new Storage<{ windowstate?: TheiaBrowserWindowOptions }>(); @@ -194,6 +197,20 @@ export class ElectronMainApplication { return this._config; } + protected makePortable(): boolean { + const dataFolderPath = path.join(app.getAppPath(), 'data'); + const appDataPath = path.join(dataFolderPath, 'app-data'); + if (existsSync(dataFolderPath)) { + if (!existsSync(appDataPath)) { + mkdirSync(appDataPath); + } + app.setPath('userData', appDataPath); + return true; + } else { + return false; + } + } + async start(config: FrontendApplicationConfig): Promise { this.useNativeWindowFrame = this.getTitleBarStyle(config) === 'native'; this._config = config; diff --git a/packages/core/src/node/env-variables/env-variables-server.ts b/packages/core/src/node/env-variables/env-variables-server.ts index 8b17d25c526b9..3d795a9063dde 100644 --- a/packages/core/src/node/env-variables/env-variables-server.ts +++ b/packages/core/src/node/env-variables/env-variables-server.ts @@ -18,6 +18,7 @@ import { join } from 'path'; import { homedir } from 'os'; import { injectable } from 'inversify'; import * as drivelist from 'drivelist'; +import { pathExists, mkdir } from 'fs-extra'; import { EnvVariable, EnvVariablesServer } from '../../common/env-variables'; import { isWindows } from '../../common/os'; import { FileUri } from '../file-uri'; @@ -28,6 +29,7 @@ export class EnvVariablesServerImpl implements EnvVariablesServer { protected readonly envs: { [key: string]: EnvVariable } = {}; protected readonly homeDirUri = FileUri.create(homedir()).toString(); protected readonly configDirUri: Promise; + protected readonly pathExistenceCache: { [key: string]: boolean } = {}; constructor() { this.configDirUri = this.createConfigDirUri(); @@ -43,7 +45,25 @@ export class EnvVariablesServerImpl implements EnvVariablesServer { } protected async createConfigDirUri(): Promise { - return FileUri.create(process.env.THEIA_CONFIG_DIR || join(homedir(), '.theia')).toString(); + let dataFolderPath: string = ''; + if (process.env.THEIA_APP_PROJECT_PATH) { + dataFolderPath = join(process.env.THEIA_APP_PROJECT_PATH, 'data'); + } + const userDataPath = join(dataFolderPath, 'user-data'); + const dataFolderExists = this.pathExistenceCache[dataFolderPath] ??= await pathExists(dataFolderPath); + if (dataFolderExists) { + const userDataExists = this.pathExistenceCache[userDataPath] ??= await pathExists(userDataPath); + if (userDataExists) { + process.env.THEIA_CONFIG_DIR = userDataPath; + } else { + await mkdir(userDataPath); + process.env.THEIA_CONFIG_DIR = userDataPath; + this.pathExistenceCache[userDataPath] = true; + } + } else { + process.env.THEIA_CONFIG_DIR = join(homedir(), '.theia'); + } + return FileUri.create(process.env.THEIA_CONFIG_DIR).toString(); } async getExecPath(): Promise {