environmentService.ts 6.7 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';
J
Joao 已提交
11
import * as fs from 'fs';
12
import URI from 'vs/base/common/uri';
J
Joao Moreno 已提交
13
import { generateUuid, isUUID } from 'vs/base/common/uuid';
14
import { memoize } from 'vs/base/common/decorators';
15 16
import pkg from 'vs/platform/node/package';
import product from 'vs/platform/node/product';
J
Joao Moreno 已提交
17

J
Joao Moreno 已提交
18 19 20
function getNixIPCHandle(userDataPath: string, type: string): string {
	return path.join(userDataPath, `${pkg.version}-${type}.sock`);
}
21

22 23 24
function getWin32IPCHandle(userDataPath: string, type: string): string {
	const scope = crypto.createHash('md5').update(userDataPath).digest('hex');
	return `\\\\.\\pipe\\${scope}-${pkg.version}-${type}-sock`;
J
Joao Moreno 已提交
25
}
26

J
Joao Moreno 已提交
27
function getIPCHandle(userDataPath: string, type: string): string {
28
	if (process.platform === 'win32') {
29
		return getWin32IPCHandle(userDataPath, type);
30
	} else {
J
Joao Moreno 已提交
31
		return getNixIPCHandle(userDataPath, type);
32 33 34
	}
}

35 36 37 38
export function getInstallSourcePath(userDataPath: string): string {
	return path.join(userDataPath, 'installSource');
}

J
Joao Moreno 已提交
39 40
export class EnvironmentService implements IEnvironmentService {

41
	_serviceBrand: any;
J
Joao Moreno 已提交
42

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

45 46
	@memoize
	get appRoot(): string { return path.dirname(URI.parse(require.toUrl('')).fsPath); }
J
Joao Moreno 已提交
47 48

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

50
	@memoize
51 52
	get userHome(): string { return os.homedir(); }

53
	@memoize
54
	get userDataPath(): string { return parseUserDataDir(this._args, process); }
J
Joao Moreno 已提交
55

56 57 58 59
	get appNameLong(): string { return product.nameLong; }

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

60 61
	@memoize
	get appSettingsHome(): string { return path.join(this.userDataPath, 'User'); }
62

63 64
	@memoize
	get appSettingsPath(): string { return path.join(this.appSettingsHome, 'settings.json'); }
65

66 67
	@memoize
	get appKeybindingsPath(): string { return path.join(this.appSettingsHome, 'keybindings.json'); }
68

69
	@memoize
70
	get isExtensionDevelopment(): boolean { return !!this._args.extensionDevelopmentPath; }
71

72 73 74 75 76 77
	@memoize
	get backupHome(): string { return path.join(this.userDataPath, 'Backups'); }

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

78 79 80
	@memoize
	get workspacesHome(): string { return path.join(this.userDataPath, 'Workspaces'); }

81
	@memoize
82
	get extensionsPath(): string { return parsePathArg(this._args['extensions-dir'], process) || process.env['VSCODE_EXTENSIONS'] || path.join(this.userHome, product.dataFolderName, 'extensions'); }
J
Joao Moreno 已提交
83

84 85 86 87 88
	@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; }
89

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

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

94
	@memoize
95 96 97 98
	get debugExtensionHost(): IExtensionHostDebugParams { return parseExtensionHostPort(this._args, this.isBuilt); }

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

100
	get isBuilt(): boolean { return !process.env['VSCODE_DEV']; }
J
Joao Moreno 已提交
101
	get verbose(): boolean { return this._args.verbose; }
102
	get wait(): boolean { return this._args.wait; }
J
Joao Moreno 已提交
103
	get logExtensionHostCommunication(): boolean { return this._args.logExtensionHostCommunication; }
104

105 106 107
	get performance(): boolean { return this._args.performance; }

	@memoize
J
Johannes Rieken 已提交
108 109
	get profileStartup(): { prefix: string, dir: string } | undefined {
		if (this._args['prof-startup']) {
110 111 112 113 114 115 116 117 118
			return {
				prefix: process.env.VSCODE_PROFILES_PREFIX,
				dir: os.homedir()
			};
		} else {
			return undefined;
		}
	}

119
	@memoize
J
Joao Moreno 已提交
120
	get mainIPCHandle(): string { return getIPCHandle(this.userDataPath, 'main'); }
121 122

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

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

J
Joao Moreno 已提交
128 129
	get disableUpdates(): boolean { return !!this._args['disable-updates']; }

J
Joao 已提交
130 131
	readonly machineUUID: string;

132 133
	readonly installSource: string;

J
Joao 已提交
134 135 136 137 138
	constructor(private _args: ParsedArgs, private _execPath: string) {
		const machineIdPath = path.join(this.userDataPath, 'machineid');

		try {
			this.machineUUID = fs.readFileSync(machineIdPath, 'utf8');
J
Joao Moreno 已提交
139 140 141 142

			if (!isUUID(this.machineUUID)) {
				throw new Error('Not a UUID');
			}
J
Joao 已提交
143 144 145 146
		} catch (err) {
			this.machineUUID = generateUuid();

			try {
J
Joao Moreno 已提交
147
				fs.writeFileSync(machineIdPath, this.machineUUID, 'utf8');
J
Joao 已提交
148
			} catch (err) {
J
Joao Moreno 已提交
149
				// noop
J
Joao 已提交
150 151
			}
		}
152 153 154 155 156 157

		try {
			this.installSource = fs.readFileSync(getInstallSourcePath(this.userDataPath), 'utf8').slice(0, 30);
		} catch (err) {
			this.installSource = '';
		}
J
Joao 已提交
158
	}
159 160
}

161 162 163 164 165 166 167 168 169 170 171 172 173
export function parseExtensionHostPort(args: ParsedArgs, isBuild: boolean): IExtensionHostDebugParams {
	return parseDebugPort(args.debugPluginHost, args.debugBrkPluginHost, 5870, isBuild, args.debugId);
}

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

export function parseDebugPort(debugArg: string, debugBrkArg: string, defaultBuildPort: number, isBuild: boolean, debugId?: string): IExtensionHostDebugParams {
	const portStr = debugBrkArg || debugArg;
	const port = Number(portStr) || (!isBuild ? defaultBuildPort : null);
	const brk = port ? Boolean(!!debugBrkArg) : false;
	return { port, break: brk, debugId };
174 175
}

J
João Moreno 已提交
176 177
function parsePathArg(arg: string, process: NodeJS.Process): string {
	if (!arg) {
M
Matt Bierner 已提交
178
		return undefined;
179
	}
J
João Moreno 已提交
180 181 182 183 184 185 186 187 188 189 190 191 192 193

	// 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));
194
}