Path: blob/main/src/vs/platform/environment/common/environmentService.ts
5240 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { toLocalISOString } from '../../../base/common/date.js';6import { memoize } from '../../../base/common/decorators.js';7import { FileAccess, Schemas } from '../../../base/common/network.js';8import { dirname, join, normalize, resolve } from '../../../base/common/path.js';9import { env } from '../../../base/common/process.js';10import { joinPath } from '../../../base/common/resources.js';11import { URI } from '../../../base/common/uri.js';12import { NativeParsedArgs } from './argv.js';13import { ExtensionKind, IExtensionHostDebugParams, INativeEnvironmentService } from './environment.js';14import { IProductService } from '../../product/common/productService.js';1516export const EXTENSION_IDENTIFIER_WITH_LOG_REGEX = /^([^.]+\..+)[:=](.+)$/;1718export interface INativeEnvironmentPaths {1920/**21* The user data directory to use for anything that should be22* persisted except for the content that is meant for the `homeDir`.23*24* Only one instance of VSCode can use the same `userDataDir`.25*/26userDataDir: string;2728/**29* The user home directory mainly used for persisting extensions30* and global configuration that should be shared across all31* versions.32*/33homeDir: string;3435/**36* OS tmp dir.37*/38tmpDir: string;39}4041export abstract class AbstractNativeEnvironmentService implements INativeEnvironmentService {4243declare readonly _serviceBrand: undefined;4445@memoize46get appRoot(): string { return dirname(FileAccess.asFileUri('').fsPath); }4748@memoize49get userHome(): URI { return URI.file(this.paths.homeDir); }5051@memoize52get userDataPath(): string { return this.paths.userDataDir; }5354@memoize55get appSettingsHome(): URI { return URI.file(join(this.userDataPath, 'User')); }5657@memoize58get tmpDir(): URI { return URI.file(this.paths.tmpDir); }5960@memoize61get cacheHome(): URI { return URI.file(this.userDataPath); }6263@memoize64get stateResource(): URI { return joinPath(this.appSettingsHome, 'globalStorage', 'storage.json'); }6566@memoize67get userRoamingDataHome(): URI { return this.appSettingsHome.with({ scheme: Schemas.vscodeUserData }); }6869@memoize70get userDataSyncHome(): URI { return joinPath(this.appSettingsHome, 'sync'); }7172get logsHome(): URI {73if (!this.args.logsPath) {74const key = toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '');75this.args.logsPath = join(this.userDataPath, 'logs', key);76}7778return URI.file(this.args.logsPath);79}8081@memoize82get sync(): 'on' | 'off' | undefined { return this.args.sync; }8384@memoize85get workspaceStorageHome(): URI { return joinPath(this.appSettingsHome, 'workspaceStorage'); }8687@memoize88get localHistoryHome(): URI { return joinPath(this.appSettingsHome, 'History'); }8990@memoize91get keyboardLayoutResource(): URI { return joinPath(this.userRoamingDataHome, 'keyboardLayout.json'); }9293@memoize94get argvResource(): URI {95const vscodePortable = env['VSCODE_PORTABLE'];96if (vscodePortable) {97return URI.file(join(vscodePortable, 'argv.json'));98}99100return joinPath(this.userHome, this.productService.dataFolderName, 'argv.json');101}102103@memoize104get isExtensionDevelopment(): boolean { return !!this.args.extensionDevelopmentPath; }105106@memoize107get untitledWorkspacesHome(): URI { return URI.file(join(this.userDataPath, 'Workspaces')); }108109@memoize110get builtinWorkbenchModesHome(): URI { return joinPath(URI.file(this.appRoot), 'resources', 'workbenchModes'); }111112@memoize113get builtinExtensionsPath(): string {114const cliBuiltinExtensionsDir = this.args['builtin-extensions-dir'];115if (cliBuiltinExtensionsDir) {116return resolve(cliBuiltinExtensionsDir);117}118119return normalize(join(FileAccess.asFileUri('').fsPath, '..', 'extensions'));120}121122@memoize123get extensionsDownloadLocation(): URI {124const cliExtensionsDownloadDir = this.args['extensions-download-dir'];125if (cliExtensionsDownloadDir) {126return URI.file(resolve(cliExtensionsDownloadDir));127}128129return URI.file(join(this.userDataPath, 'CachedExtensionVSIXs'));130}131132@memoize133get extensionsPath(): string {134const cliExtensionsDir = this.args['extensions-dir'];135if (cliExtensionsDir) {136return resolve(cliExtensionsDir);137}138139const vscodeExtensions = env['VSCODE_EXTENSIONS'];140if (vscodeExtensions) {141return vscodeExtensions;142}143144const vscodePortable = env['VSCODE_PORTABLE'];145if (vscodePortable) {146return join(vscodePortable, 'extensions');147}148149return joinPath(this.userHome, this.productService.dataFolderName, 'extensions').fsPath;150}151152@memoize153get extensionDevelopmentLocationURI(): URI[] | undefined {154const extensionDevelopmentPaths = this.args.extensionDevelopmentPath;155if (Array.isArray(extensionDevelopmentPaths)) {156return extensionDevelopmentPaths.map(extensionDevelopmentPath => {157if (/^[^:/?#]+?:\/\//.test(extensionDevelopmentPath)) {158return URI.parse(extensionDevelopmentPath);159}160161return URI.file(normalize(extensionDevelopmentPath));162});163}164165return undefined;166}167168@memoize169get extensionDevelopmentKind(): ExtensionKind[] | undefined {170return this.args.extensionDevelopmentKind?.map(kind => kind === 'ui' || kind === 'workspace' || kind === 'web' ? kind : 'workspace');171}172173@memoize174get extensionTestsLocationURI(): URI | undefined {175const extensionTestsPath = this.args.extensionTestsPath;176if (extensionTestsPath) {177if (/^[^:/?#]+?:\/\//.test(extensionTestsPath)) {178return URI.parse(extensionTestsPath);179}180181return URI.file(normalize(extensionTestsPath));182}183184return undefined;185}186187get disableExtensions(): boolean | string[] {188if (this.args['disable-extensions']) {189return true;190}191192const disableExtensions = this.args['disable-extension'];193if (disableExtensions) {194if (typeof disableExtensions === 'string') {195return [disableExtensions];196}197198if (Array.isArray(disableExtensions) && disableExtensions.length > 0) {199return disableExtensions;200}201}202203return false;204}205206@memoize207get debugExtensionHost(): IExtensionHostDebugParams { return parseExtensionHostDebugPort(this.args, this.isBuilt); }208get debugRenderer(): boolean { return !!this.args.debugRenderer; }209210get isBuilt(): boolean { return !env['VSCODE_DEV']; }211get verbose(): boolean { return !!this.args.verbose; }212213@memoize214get logLevel(): string | undefined { return this.args.log?.find(entry => !EXTENSION_IDENTIFIER_WITH_LOG_REGEX.test(entry)); }215@memoize216get extensionLogLevel(): [string, string][] | undefined {217const result: [string, string][] = [];218for (const entry of this.args.log || []) {219const matches = EXTENSION_IDENTIFIER_WITH_LOG_REGEX.exec(entry);220if (matches?.[1] && matches[2]) {221result.push([matches[1], matches[2]]);222}223}224return result.length ? result : undefined;225}226227@memoize228get serviceMachineIdResource(): URI { return joinPath(URI.file(this.userDataPath), 'machineid'); }229230get crashReporterId(): string | undefined { return this.args['crash-reporter-id']; }231get crashReporterDirectory(): string | undefined { return this.args['crash-reporter-directory']; }232233@memoize234get disableTelemetry(): boolean { return !!this.args['disable-telemetry']; }235236@memoize237get disableExperiments(): boolean { return !!this.args['disable-experiments']; }238239@memoize240get disableWorkspaceTrust(): boolean { return !!this.args['disable-workspace-trust']; }241242@memoize243get useInMemorySecretStorage(): boolean { return !!this.args['use-inmemory-secretstorage']; }244245@memoize246get policyFile(): URI | undefined {247if (this.args['__enable-file-policy']) {248const vscodePortable = env['VSCODE_PORTABLE'];249if (vscodePortable) {250return URI.file(join(vscodePortable, 'policy.json'));251}252253return joinPath(this.userHome, this.productService.dataFolderName, 'policy.json');254}255return undefined;256}257258@memoize259get agentSessionsWorkspace(): URI {260return joinPath(this.appSettingsHome, 'agent-sessions.code-workspace');261}262263get editSessionId(): string | undefined { return this.args['editSessionId']; }264265get exportPolicyData(): string | undefined {266return this.args['export-policy-data'];267}268269get continueOn(): string | undefined {270return this.args['continueOn'];271}272273set continueOn(value: string | undefined) {274this.args['continueOn'] = value;275}276277get args(): NativeParsedArgs { return this._args; }278279constructor(280private readonly _args: NativeParsedArgs,281private readonly paths: INativeEnvironmentPaths,282protected readonly productService: IProductService283) { }284}285286export function parseExtensionHostDebugPort(args: NativeParsedArgs, isBuilt: boolean): IExtensionHostDebugParams {287return parseDebugParams(args['inspect-extensions'], args['inspect-brk-extensions'], 5870, isBuilt, args.debugId, args.extensionEnvironment);288}289290export function parseDebugParams(debugArg: string | undefined, debugBrkArg: string | undefined, defaultBuildPort: number, isBuilt: boolean, debugId?: string, environmentString?: string): IExtensionHostDebugParams {291const portStr = debugBrkArg || debugArg;292const port = Number(portStr) || (!isBuilt ? defaultBuildPort : null);293const brk = port ? Boolean(!!debugBrkArg) : false;294let env: Record<string, string> | undefined;295if (environmentString) {296try {297env = JSON.parse(environmentString);298} catch {299// ignore300}301}302303return { port, break: brk, debugId, env };304}305306307