environmentService.ts 8.4 KB
Newer Older
J
Joao Moreno 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

6
import { IEnvironmentService, ParsedArgs, IDebugParams, IExtensionHostDebugParams } from 'vs/platform/environment/common/environment';
7
import * as crypto from 'crypto';
J
Joao Moreno 已提交
8 9 10
import * as paths from 'vs/base/node/paths';
import * as os from 'os';
import * as path from 'path';
11
import URI from 'vs/base/common/uri';
12
import { memoize } from 'vs/base/common/decorators';
13 14
import pkg from 'vs/platform/node/package';
import product from 'vs/platform/node/product';
15
import { toLocalISOString } from 'vs/base/common/date';
16
import { isWindows, isLinux } from 'vs/base/common/platform';
J
Joao Moreno 已提交
17

J
Joao Moreno 已提交
18 19 20 21
// Read this before there's any chance it is overwritten
// Related to https://github.com/Microsoft/vscode/issues/30624
const xdgRuntimeDir = process.env['XDG_RUNTIME_DIR'];

J
Joao Moreno 已提交
22
function getNixIPCHandle(userDataPath: string, type: string): string {
J
Joao Moreno 已提交
23
	if (xdgRuntimeDir) {
J
Joao Moreno 已提交
24 25
		const scope = crypto.createHash('md5').update(userDataPath).digest('hex').substr(0, 8);
		return path.join(xdgRuntimeDir, `vscode-${scope}-${pkg.version}-${type}.sock`);
J
Joao Moreno 已提交
26 27
	}

J
Joao Moreno 已提交
28 29
	return path.join(userDataPath, `${pkg.version}-${type}.sock`);
}
30

31 32
function getWin32IPCHandle(userDataPath: string, type: string): string {
	const scope = crypto.createHash('md5').update(userDataPath).digest('hex');
33

34
	return `\\\\.\\pipe\\${scope}-${pkg.version}-${type}-sock`;
J
Joao Moreno 已提交
35
}
36

J
Joao Moreno 已提交
37
function getIPCHandle(userDataPath: string, type: string): string {
38
	if (isWindows) {
39
		return getWin32IPCHandle(userDataPath, type);
40
	}
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

	return getNixIPCHandle(userDataPath, type);
}

function getCLIPath(execPath: string, appRoot: string, isBuilt: boolean): string {

	// Windows
	if (isWindows) {
		if (isBuilt) {
			return path.join(path.dirname(execPath), 'bin', `${product.applicationName}.cmd`);
		}

		return path.join(appRoot, 'scripts', 'code-cli.bat');
	}

	// Linux
	if (isLinux) {
		if (isBuilt) {
			return path.join(path.dirname(execPath), 'bin', `${product.applicationName}`);
		}

		return path.join(appRoot, 'scripts', 'code-cli.sh');
	}

	// macOS
	if (isBuilt) {
		return path.join(appRoot, 'bin', 'code');
	}

	return path.join(appRoot, 'scripts', 'code-cli.sh');
71 72
}

J
Joao Moreno 已提交
73 74
export class EnvironmentService implements IEnvironmentService {

75
	_serviceBrand: any;
J
Joao Moreno 已提交
76

J
Joao Moreno 已提交
77 78
	get args(): ParsedArgs { return this._args; }

79 80
	@memoize
	get appRoot(): string { return path.dirname(URI.parse(require.toUrl('')).fsPath); }
J
Joao Moreno 已提交
81 82

	get execPath(): string { return this._execPath; }
83

84 85 86
	@memoize
	get cliPath(): string { return getCLIPath(this.execPath, this.appRoot, this.isBuilt); }

J
Joao Moreno 已提交
87 88
	readonly logsPath: string;

89
	@memoize
90 91
	get userHome(): string { return os.homedir(); }

92
	@memoize
J
Joao Moreno 已提交
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
	private get appPath(): string {
		if (process.env['VSCODE_DEV']) {
			return this.appRoot;
		} else if (process.platform === 'darwin') {
			return path.dirname(path.dirname(path.dirname(this.appRoot)));
		} else {
			return path.dirname(path.dirname(this.appRoot));
		}
	}

	@memoize
	get userDataPath(): string {
		if (product.portable) {
			return path.join(path.dirname(this.appPath), product.portable, 'user-data');
		}

		return parseUserDataDir(this._args, process);
	}
J
Joao Moreno 已提交
111

112 113 114 115
	get appNameLong(): string { return product.nameLong; }

	get appQuality(): string { return product.quality; }

116 117
	@memoize
	get appSettingsHome(): string { return path.join(this.userDataPath, 'User'); }
118

119 120
	@memoize
	get appSettingsPath(): string { return path.join(this.appSettingsHome, 'settings.json'); }
121

122 123 124
	@memoize
	get settingsSearchBuildId(): number { return product.settingsSearchBuildId; }

125 126 127
	@memoize
	get settingsSearchUrl(): string { return product.settingsSearchUrl; }

128 129
	@memoize
	get appKeybindingsPath(): string { return path.join(this.appSettingsHome, 'keybindings.json'); }
130

131
	@memoize
132
	get isExtensionDevelopment(): boolean { return !!this._args.extensionDevelopmentPath; }
133

134 135 136 137 138 139
	@memoize
	get backupHome(): string { return path.join(this.userDataPath, 'Backups'); }

	@memoize
	get backupWorkspacesPath(): string { return path.join(this.backupHome, 'workspaces.json'); }

140 141 142
	@memoize
	get workspacesHome(): string { return path.join(this.userDataPath, 'Workspaces'); }

143 144 145
	@memoize
	get installSourcePath(): string { return path.join(this.userDataPath, 'installSource'); }

146
	@memoize
J
Joao Moreno 已提交
147 148 149 150 151 152 153 154 155 156 157 158 159
	get extensionsPath(): string {
		const fromArgs = parsePathArg(this._args['extensions-dir'], process);

		if (fromArgs) {
			return fromArgs;
		} else if (process.env['VSCODE_EXTENSIONS']) {
			return process.env['VSCODE_EXTENSIONS'];
		} else if (product.portable) {
			return path.join(path.dirname(this.appPath), product.portable, 'extensions');
		} else {
			return path.join(this.userHome, product.dataFolderName, 'extensions');
		}
	}
J
Joao Moreno 已提交
160

161 162 163 164 165
	@memoize
	get extensionDevelopmentPath(): string { return this._args.extensionDevelopmentPath ? path.normalize(this._args.extensionDevelopmentPath) : this._args.extensionDevelopmentPath; }

	@memoize
	get extensionTestsPath(): string { return this._args.extensionTestsPath ? path.normalize(this._args.extensionTestsPath) : this._args.extensionTestsPath; }
166

J
Johannes Rieken 已提交
167
	get disableExtensions(): boolean { return this._args['disable-extensions']; }
B
Benjamin Pasero 已提交
168

169
	get skipGettingStarted(): boolean { return this._args['skip-getting-started']; }
170

171 172
	get skipReleaseNotes(): boolean { return this._args['skip-release-notes']; }

173 174
	get skipAddToRecentlyOpened(): boolean { return this._args['skip-add-to-recently-opened']; }

175
	@memoize
176 177 178 179
	get debugExtensionHost(): IExtensionHostDebugParams { return parseExtensionHostPort(this._args, this.isBuilt); }

	@memoize
	get debugSearch(): IDebugParams { return parseSearchPort(this._args, this.isBuilt); }
180

181
	get isBuilt(): boolean { return !process.env['VSCODE_DEV']; }
J
Joao Moreno 已提交
182
	get verbose(): boolean { return this._args.verbose; }
183

184
	get wait(): boolean { return this._args.wait; }
J
Joao Moreno 已提交
185
	get logExtensionHostCommunication(): boolean { return this._args.logExtensionHostCommunication; }
186

187
	get performance(): boolean { return this._args.performance; }
B
Benjamin Pasero 已提交
188
	get status(): boolean { return this._args.status; }
189

190
	@memoize
J
Joao Moreno 已提交
191
	get mainIPCHandle(): string { return getIPCHandle(this.userDataPath, 'main'); }
192 193

	@memoize
J
Joao Moreno 已提交
194
	get sharedIPCHandle(): string { return getIPCHandle(this.userDataPath, 'shared'); }
195

196
	@memoize
197
	get nodeCachedDataDir(): string { return this.isBuilt ? path.join(this.userDataPath, 'CachedData', product.commit || new Array(41).join('0')) : undefined; }
198

J
Joao Moreno 已提交
199
	get disableUpdates(): boolean { return !!this._args['disable-updates']; }
200
	get disableCrashReporter(): boolean { return !!this._args['disable-crash-reporter']; }
J
Joao Moreno 已提交
201

J
Joao Moreno 已提交
202
	get driverHandle(): string { return this._args['driver']; }
203
	get driverVerbose(): boolean { return this._args['driver-verbose']; }
J
Joao Moreno 已提交
204

J
Joao 已提交
205
	constructor(private _args: ParsedArgs, private _execPath: string) {
J
Joao Moreno 已提交
206
		if (!process.env['VSCODE_LOGS']) {
207
			const key = toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '');
J
Joao Moreno 已提交
208 209 210 211
			process.env['VSCODE_LOGS'] = path.join(this.userDataPath, 'logs', key);
		}

		this.logsPath = process.env['VSCODE_LOGS'];
J
Joao 已提交
212
	}
213 214
}

215
export function parseExtensionHostPort(args: ParsedArgs, isBuild: boolean): IExtensionHostDebugParams {
216
	return parseDebugPort(args.debugPluginHost, args.debugBrkPluginHost, 5870, isBuild, args.debugId);
217 218 219
}

export function parseSearchPort(args: ParsedArgs, isBuild: boolean): IDebugParams {
220
	return parseDebugPort(args.debugSearch, args.debugBrkSearch, 5876, isBuild);
221 222
}

223
export function parseDebugPort(debugArg: string, debugBrkArg: string, defaultBuildPort: number, isBuild: boolean, debugId?: string): IExtensionHostDebugParams {
224
	const portStr = debugBrkArg || debugArg;
225
	const port = Number(portStr) || (!isBuild ? defaultBuildPort : null);
226 227
	const brk = port ? Boolean(!!debugBrkArg) : false;
	return { port, break: brk, debugId };
228 229
}

J
João Moreno 已提交
230 231
function parsePathArg(arg: string, process: NodeJS.Process): string {
	if (!arg) {
M
Matt Bierner 已提交
232
		return undefined;
233
	}
J
João Moreno 已提交
234 235 236 237 238 239 240 241 242 243 244 245 246 247

	// Determine if the arg is relative or absolute, if relative use the original CWD
	// (VSCODE_CWD), not the potentially overridden one (process.cwd()).
	const resolved = path.resolve(arg);

	if (path.normalize(arg) === resolved) {
		return resolved;
	} else {
		return path.resolve(process.env['VSCODE_CWD'] || process.cwd(), arg);
	}
}

export function parseUserDataDir(args: ParsedArgs, process: NodeJS.Process): string {
	return parsePathArg(args['user-data-dir'], process) || path.resolve(paths.getDefaultUserDataPath(process.platform));
248
}