Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/environment/common/environmentService.ts
3296 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 builtinExtensionsPath(): string {
112
const cliBuiltinExtensionsDir = this.args['builtin-extensions-dir'];
113
if (cliBuiltinExtensionsDir) {
114
return resolve(cliBuiltinExtensionsDir);
115
}
116
117
return normalize(join(FileAccess.asFileUri('').fsPath, '..', 'extensions'));
118
}
119
120
get extensionsDownloadLocation(): URI {
121
const cliExtensionsDownloadDir = this.args['extensions-download-dir'];
122
if (cliExtensionsDownloadDir) {
123
return URI.file(resolve(cliExtensionsDownloadDir));
124
}
125
126
return URI.file(join(this.userDataPath, 'CachedExtensionVSIXs'));
127
}
128
129
@memoize
130
get extensionsPath(): string {
131
const cliExtensionsDir = this.args['extensions-dir'];
132
if (cliExtensionsDir) {
133
return resolve(cliExtensionsDir);
134
}
135
136
const vscodeExtensions = env['VSCODE_EXTENSIONS'];
137
if (vscodeExtensions) {
138
return vscodeExtensions;
139
}
140
141
const vscodePortable = env['VSCODE_PORTABLE'];
142
if (vscodePortable) {
143
return join(vscodePortable, 'extensions');
144
}
145
146
return joinPath(this.userHome, this.productService.dataFolderName, 'extensions').fsPath;
147
}
148
149
@memoize
150
get extensionDevelopmentLocationURI(): URI[] | undefined {
151
const extensionDevelopmentPaths = this.args.extensionDevelopmentPath;
152
if (Array.isArray(extensionDevelopmentPaths)) {
153
return extensionDevelopmentPaths.map(extensionDevelopmentPath => {
154
if (/^[^:/?#]+?:\/\//.test(extensionDevelopmentPath)) {
155
return URI.parse(extensionDevelopmentPath);
156
}
157
158
return URI.file(normalize(extensionDevelopmentPath));
159
});
160
}
161
162
return undefined;
163
}
164
165
@memoize
166
get extensionDevelopmentKind(): ExtensionKind[] | undefined {
167
return this.args.extensionDevelopmentKind?.map(kind => kind === 'ui' || kind === 'workspace' || kind === 'web' ? kind : 'workspace');
168
}
169
170
@memoize
171
get extensionTestsLocationURI(): URI | undefined {
172
const extensionTestsPath = this.args.extensionTestsPath;
173
if (extensionTestsPath) {
174
if (/^[^:/?#]+?:\/\//.test(extensionTestsPath)) {
175
return URI.parse(extensionTestsPath);
176
}
177
178
return URI.file(normalize(extensionTestsPath));
179
}
180
181
return undefined;
182
}
183
184
get disableExtensions(): boolean | string[] {
185
if (this.args['disable-extensions']) {
186
return true;
187
}
188
189
const disableExtensions = this.args['disable-extension'];
190
if (disableExtensions) {
191
if (typeof disableExtensions === 'string') {
192
return [disableExtensions];
193
}
194
195
if (Array.isArray(disableExtensions) && disableExtensions.length > 0) {
196
return disableExtensions;
197
}
198
}
199
200
return false;
201
}
202
203
@memoize
204
get debugExtensionHost(): IExtensionHostDebugParams { return parseExtensionHostDebugPort(this.args, this.isBuilt); }
205
get debugRenderer(): boolean { return !!this.args.debugRenderer; }
206
207
get isBuilt(): boolean { return !env['VSCODE_DEV']; }
208
get verbose(): boolean { return !!this.args.verbose; }
209
210
@memoize
211
get logLevel(): string | undefined { return this.args.log?.find(entry => !EXTENSION_IDENTIFIER_WITH_LOG_REGEX.test(entry)); }
212
@memoize
213
get extensionLogLevel(): [string, string][] | undefined {
214
const result: [string, string][] = [];
215
for (const entry of this.args.log || []) {
216
const matches = EXTENSION_IDENTIFIER_WITH_LOG_REGEX.exec(entry);
217
if (matches && matches[1] && matches[2]) {
218
result.push([matches[1], matches[2]]);
219
}
220
}
221
return result.length ? result : undefined;
222
}
223
224
@memoize
225
get serviceMachineIdResource(): URI { return joinPath(URI.file(this.userDataPath), 'machineid'); }
226
227
get crashReporterId(): string | undefined { return this.args['crash-reporter-id']; }
228
get crashReporterDirectory(): string | undefined { return this.args['crash-reporter-directory']; }
229
230
@memoize
231
get disableTelemetry(): boolean { return !!this.args['disable-telemetry']; }
232
233
@memoize
234
get disableExperiments(): boolean { return !!this.args['disable-experiments']; }
235
236
@memoize
237
get disableWorkspaceTrust(): boolean { return !!this.args['disable-workspace-trust']; }
238
239
@memoize
240
get useInMemorySecretStorage(): boolean { return !!this.args['use-inmemory-secretstorage']; }
241
242
@memoize
243
get policyFile(): URI | undefined {
244
if (this.args['__enable-file-policy']) {
245
const vscodePortable = env['VSCODE_PORTABLE'];
246
if (vscodePortable) {
247
return URI.file(join(vscodePortable, 'policy.json'));
248
}
249
250
return joinPath(this.userHome, this.productService.dataFolderName, 'policy.json');
251
}
252
return undefined;
253
}
254
255
get editSessionId(): string | undefined { return this.args['editSessionId']; }
256
257
get continueOn(): string | undefined {
258
return this.args['continueOn'];
259
}
260
261
set continueOn(value: string | undefined) {
262
this.args['continueOn'] = value;
263
}
264
265
get args(): NativeParsedArgs { return this._args; }
266
267
get isSimulation(): boolean {
268
return env['SIMULATION'] === '1';
269
}
270
271
constructor(
272
private readonly _args: NativeParsedArgs,
273
private readonly paths: INativeEnvironmentPaths,
274
protected readonly productService: IProductService
275
) { }
276
}
277
278
export function parseExtensionHostDebugPort(args: NativeParsedArgs, isBuilt: boolean): IExtensionHostDebugParams {
279
return parseDebugParams(args['inspect-extensions'], args['inspect-brk-extensions'], 5870, isBuilt, args.debugId, args.extensionEnvironment);
280
}
281
282
export function parseDebugParams(debugArg: string | undefined, debugBrkArg: string | undefined, defaultBuildPort: number, isBuilt: boolean, debugId?: string, environmentString?: string): IExtensionHostDebugParams {
283
const portStr = debugBrkArg || debugArg;
284
const port = Number(portStr) || (!isBuilt ? defaultBuildPort : null);
285
const brk = port ? Boolean(!!debugBrkArg) : false;
286
let env: Record<string, string> | undefined;
287
if (environmentString) {
288
try {
289
env = JSON.parse(environmentString);
290
} catch {
291
// ignore
292
}
293
}
294
295
return { port, break: brk, debugId, env };
296
}
297
298