Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/environment/common/environmentService.ts
5240 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { toLocalISOString } from '../../../base/common/date.js';
7
import { memoize } from '../../../base/common/decorators.js';
8
import { FileAccess, Schemas } from '../../../base/common/network.js';
9
import { dirname, join, normalize, resolve } from '../../../base/common/path.js';
10
import { env } from '../../../base/common/process.js';
11
import { joinPath } from '../../../base/common/resources.js';
12
import { URI } from '../../../base/common/uri.js';
13
import { NativeParsedArgs } from './argv.js';
14
import { ExtensionKind, IExtensionHostDebugParams, INativeEnvironmentService } from './environment.js';
15
import { IProductService } from '../../product/common/productService.js';
16
17
export const EXTENSION_IDENTIFIER_WITH_LOG_REGEX = /^([^.]+\..+)[:=](.+)$/;
18
19
export interface INativeEnvironmentPaths {
20
21
/**
22
* The user data directory to use for anything that should be
23
* persisted except for the content that is meant for the `homeDir`.
24
*
25
* Only one instance of VSCode can use the same `userDataDir`.
26
*/
27
userDataDir: string;
28
29
/**
30
* The user home directory mainly used for persisting extensions
31
* and global configuration that should be shared across all
32
* versions.
33
*/
34
homeDir: string;
35
36
/**
37
* OS tmp dir.
38
*/
39
tmpDir: string;
40
}
41
42
export abstract class AbstractNativeEnvironmentService implements INativeEnvironmentService {
43
44
declare readonly _serviceBrand: undefined;
45
46
@memoize
47
get appRoot(): string { return dirname(FileAccess.asFileUri('').fsPath); }
48
49
@memoize
50
get userHome(): URI { return URI.file(this.paths.homeDir); }
51
52
@memoize
53
get userDataPath(): string { return this.paths.userDataDir; }
54
55
@memoize
56
get appSettingsHome(): URI { return URI.file(join(this.userDataPath, 'User')); }
57
58
@memoize
59
get tmpDir(): URI { return URI.file(this.paths.tmpDir); }
60
61
@memoize
62
get cacheHome(): URI { return URI.file(this.userDataPath); }
63
64
@memoize
65
get stateResource(): URI { return joinPath(this.appSettingsHome, 'globalStorage', 'storage.json'); }
66
67
@memoize
68
get userRoamingDataHome(): URI { return this.appSettingsHome.with({ scheme: Schemas.vscodeUserData }); }
69
70
@memoize
71
get userDataSyncHome(): URI { return joinPath(this.appSettingsHome, 'sync'); }
72
73
get logsHome(): URI {
74
if (!this.args.logsPath) {
75
const key = toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '');
76
this.args.logsPath = join(this.userDataPath, 'logs', key);
77
}
78
79
return URI.file(this.args.logsPath);
80
}
81
82
@memoize
83
get sync(): 'on' | 'off' | undefined { return this.args.sync; }
84
85
@memoize
86
get workspaceStorageHome(): URI { return joinPath(this.appSettingsHome, 'workspaceStorage'); }
87
88
@memoize
89
get localHistoryHome(): URI { return joinPath(this.appSettingsHome, 'History'); }
90
91
@memoize
92
get keyboardLayoutResource(): URI { return joinPath(this.userRoamingDataHome, 'keyboardLayout.json'); }
93
94
@memoize
95
get argvResource(): URI {
96
const vscodePortable = env['VSCODE_PORTABLE'];
97
if (vscodePortable) {
98
return URI.file(join(vscodePortable, 'argv.json'));
99
}
100
101
return joinPath(this.userHome, this.productService.dataFolderName, 'argv.json');
102
}
103
104
@memoize
105
get isExtensionDevelopment(): boolean { return !!this.args.extensionDevelopmentPath; }
106
107
@memoize
108
get untitledWorkspacesHome(): URI { return URI.file(join(this.userDataPath, 'Workspaces')); }
109
110
@memoize
111
get builtinWorkbenchModesHome(): URI { return joinPath(URI.file(this.appRoot), 'resources', 'workbenchModes'); }
112
113
@memoize
114
get builtinExtensionsPath(): string {
115
const cliBuiltinExtensionsDir = this.args['builtin-extensions-dir'];
116
if (cliBuiltinExtensionsDir) {
117
return resolve(cliBuiltinExtensionsDir);
118
}
119
120
return normalize(join(FileAccess.asFileUri('').fsPath, '..', 'extensions'));
121
}
122
123
@memoize
124
get extensionsDownloadLocation(): URI {
125
const cliExtensionsDownloadDir = this.args['extensions-download-dir'];
126
if (cliExtensionsDownloadDir) {
127
return URI.file(resolve(cliExtensionsDownloadDir));
128
}
129
130
return URI.file(join(this.userDataPath, 'CachedExtensionVSIXs'));
131
}
132
133
@memoize
134
get extensionsPath(): string {
135
const cliExtensionsDir = this.args['extensions-dir'];
136
if (cliExtensionsDir) {
137
return resolve(cliExtensionsDir);
138
}
139
140
const vscodeExtensions = env['VSCODE_EXTENSIONS'];
141
if (vscodeExtensions) {
142
return vscodeExtensions;
143
}
144
145
const vscodePortable = env['VSCODE_PORTABLE'];
146
if (vscodePortable) {
147
return join(vscodePortable, 'extensions');
148
}
149
150
return joinPath(this.userHome, this.productService.dataFolderName, 'extensions').fsPath;
151
}
152
153
@memoize
154
get extensionDevelopmentLocationURI(): URI[] | undefined {
155
const extensionDevelopmentPaths = this.args.extensionDevelopmentPath;
156
if (Array.isArray(extensionDevelopmentPaths)) {
157
return extensionDevelopmentPaths.map(extensionDevelopmentPath => {
158
if (/^[^:/?#]+?:\/\//.test(extensionDevelopmentPath)) {
159
return URI.parse(extensionDevelopmentPath);
160
}
161
162
return URI.file(normalize(extensionDevelopmentPath));
163
});
164
}
165
166
return undefined;
167
}
168
169
@memoize
170
get extensionDevelopmentKind(): ExtensionKind[] | undefined {
171
return this.args.extensionDevelopmentKind?.map(kind => kind === 'ui' || kind === 'workspace' || kind === 'web' ? kind : 'workspace');
172
}
173
174
@memoize
175
get extensionTestsLocationURI(): URI | undefined {
176
const extensionTestsPath = this.args.extensionTestsPath;
177
if (extensionTestsPath) {
178
if (/^[^:/?#]+?:\/\//.test(extensionTestsPath)) {
179
return URI.parse(extensionTestsPath);
180
}
181
182
return URI.file(normalize(extensionTestsPath));
183
}
184
185
return undefined;
186
}
187
188
get disableExtensions(): boolean | string[] {
189
if (this.args['disable-extensions']) {
190
return true;
191
}
192
193
const disableExtensions = this.args['disable-extension'];
194
if (disableExtensions) {
195
if (typeof disableExtensions === 'string') {
196
return [disableExtensions];
197
}
198
199
if (Array.isArray(disableExtensions) && disableExtensions.length > 0) {
200
return disableExtensions;
201
}
202
}
203
204
return false;
205
}
206
207
@memoize
208
get debugExtensionHost(): IExtensionHostDebugParams { return parseExtensionHostDebugPort(this.args, this.isBuilt); }
209
get debugRenderer(): boolean { return !!this.args.debugRenderer; }
210
211
get isBuilt(): boolean { return !env['VSCODE_DEV']; }
212
get verbose(): boolean { return !!this.args.verbose; }
213
214
@memoize
215
get logLevel(): string | undefined { return this.args.log?.find(entry => !EXTENSION_IDENTIFIER_WITH_LOG_REGEX.test(entry)); }
216
@memoize
217
get extensionLogLevel(): [string, string][] | undefined {
218
const result: [string, string][] = [];
219
for (const entry of this.args.log || []) {
220
const matches = EXTENSION_IDENTIFIER_WITH_LOG_REGEX.exec(entry);
221
if (matches?.[1] && matches[2]) {
222
result.push([matches[1], matches[2]]);
223
}
224
}
225
return result.length ? result : undefined;
226
}
227
228
@memoize
229
get serviceMachineIdResource(): URI { return joinPath(URI.file(this.userDataPath), 'machineid'); }
230
231
get crashReporterId(): string | undefined { return this.args['crash-reporter-id']; }
232
get crashReporterDirectory(): string | undefined { return this.args['crash-reporter-directory']; }
233
234
@memoize
235
get disableTelemetry(): boolean { return !!this.args['disable-telemetry']; }
236
237
@memoize
238
get disableExperiments(): boolean { return !!this.args['disable-experiments']; }
239
240
@memoize
241
get disableWorkspaceTrust(): boolean { return !!this.args['disable-workspace-trust']; }
242
243
@memoize
244
get useInMemorySecretStorage(): boolean { return !!this.args['use-inmemory-secretstorage']; }
245
246
@memoize
247
get policyFile(): URI | undefined {
248
if (this.args['__enable-file-policy']) {
249
const vscodePortable = env['VSCODE_PORTABLE'];
250
if (vscodePortable) {
251
return URI.file(join(vscodePortable, 'policy.json'));
252
}
253
254
return joinPath(this.userHome, this.productService.dataFolderName, 'policy.json');
255
}
256
return undefined;
257
}
258
259
@memoize
260
get agentSessionsWorkspace(): URI {
261
return joinPath(this.appSettingsHome, 'agent-sessions.code-workspace');
262
}
263
264
get editSessionId(): string | undefined { return this.args['editSessionId']; }
265
266
get exportPolicyData(): string | undefined {
267
return this.args['export-policy-data'];
268
}
269
270
get continueOn(): string | undefined {
271
return this.args['continueOn'];
272
}
273
274
set continueOn(value: string | undefined) {
275
this.args['continueOn'] = value;
276
}
277
278
get args(): NativeParsedArgs { return this._args; }
279
280
constructor(
281
private readonly _args: NativeParsedArgs,
282
private readonly paths: INativeEnvironmentPaths,
283
protected readonly productService: IProductService
284
) { }
285
}
286
287
export function parseExtensionHostDebugPort(args: NativeParsedArgs, isBuilt: boolean): IExtensionHostDebugParams {
288
return parseDebugParams(args['inspect-extensions'], args['inspect-brk-extensions'], 5870, isBuilt, args.debugId, args.extensionEnvironment);
289
}
290
291
export function parseDebugParams(debugArg: string | undefined, debugBrkArg: string | undefined, defaultBuildPort: number, isBuilt: boolean, debugId?: string, environmentString?: string): IExtensionHostDebugParams {
292
const portStr = debugBrkArg || debugArg;
293
const port = Number(portStr) || (!isBuilt ? defaultBuildPort : null);
294
const brk = port ? Boolean(!!debugBrkArg) : false;
295
let env: Record<string, string> | undefined;
296
if (environmentString) {
297
try {
298
env = JSON.parse(environmentString);
299
} catch {
300
// ignore
301
}
302
}
303
304
return { port, break: brk, debugId, env };
305
}
306
307