Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/test/automation/src/electron.ts
5241 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 { join } from 'path';
7
import * as fs from 'fs';
8
import { copyExtension } from './extensions';
9
import { URI } from 'vscode-uri';
10
import { measureAndLog } from './logger';
11
import type { LaunchOptions } from './code';
12
13
const root = join(__dirname, '..', '..', '..');
14
15
export interface IElectronConfiguration {
16
readonly electronPath: string;
17
readonly args: string[];
18
readonly env?: NodeJS.ProcessEnv;
19
}
20
21
export async function resolveElectronConfiguration(options: LaunchOptions): Promise<IElectronConfiguration> {
22
const { codePath, workspacePath, extensionsPath, userDataDir, remote, logger, logsPath, crashesPath, extraArgs } = options;
23
const env = { ...process.env };
24
25
const args: string[] = [
26
'--skip-release-notes',
27
'--skip-welcome',
28
'--disable-telemetry',
29
'--disable-experiments',
30
'--no-cached-data',
31
'--disable-updates',
32
'--disable-extension=vscode.vscode-api-tests',
33
`--crash-reporter-directory=${crashesPath}`,
34
'--disable-workspace-trust',
35
`--logsPath=${logsPath}`
36
];
37
38
// Only add workspace path if provided
39
if (workspacePath) {
40
args.unshift(workspacePath);
41
}
42
43
if (options.useInMemorySecretStorage) {
44
args.push('--use-inmemory-secretstorage');
45
}
46
if (userDataDir) {
47
args.push(`--user-data-dir=${userDataDir}`);
48
}
49
if (extensionsPath) {
50
args.push(`--extensions-dir=${extensionsPath}`);
51
}
52
if (options.verbose) {
53
args.push('--verbose');
54
}
55
if (options.extensionDevelopmentPath) {
56
args.push(`--extensionDevelopmentPath=${options.extensionDevelopmentPath}`);
57
}
58
59
if (remote) {
60
if (!workspacePath) {
61
throw new Error('Workspace path is required when running remote');
62
}
63
// Replace workspace path with URI
64
args[0] = `--${workspacePath.endsWith('.code-workspace') ? 'file' : 'folder'}-uri=vscode-remote://test+test/${URI.file(workspacePath).path}`;
65
66
if (codePath) {
67
if (!extensionsPath) {
68
throw new Error('Extensions path is required when running against a build at the moment.');
69
}
70
// running against a build: copy the test resolver extension
71
await measureAndLog(() => copyExtension(root, extensionsPath, 'vscode-test-resolver'), 'copyExtension(vscode-test-resolver)', logger);
72
}
73
args.push('--enable-proposed-api=vscode.vscode-test-resolver');
74
if (userDataDir) {
75
const remoteDataDir = `${userDataDir}-server`;
76
fs.mkdirSync(remoteDataDir, { recursive: true });
77
env['TESTRESOLVER_DATA_FOLDER'] = remoteDataDir;
78
}
79
env['TESTRESOLVER_LOGS_FOLDER'] = join(logsPath, 'server');
80
if (options.verbose) {
81
env['TESTRESOLVER_LOG_LEVEL'] = 'trace';
82
}
83
}
84
85
if (!codePath) {
86
args.unshift(root);
87
}
88
89
if (extraArgs) {
90
args.push(...extraArgs);
91
}
92
93
const electronPath = codePath ? getBuildElectronPath(codePath) : getDevElectronPath();
94
95
return {
96
env,
97
args,
98
electronPath
99
};
100
}
101
102
function findFilePath(root: string, path: string): string {
103
// First check if the path exists directly in the root
104
const directPath = join(root, path);
105
if (fs.existsSync(directPath)) {
106
return directPath;
107
}
108
109
// If not found directly, search through subdirectories
110
const entries = fs.readdirSync(root, { withFileTypes: true });
111
112
for (const entry of entries) {
113
if (entry.isDirectory()) {
114
const found = join(root, entry.name, path);
115
if (fs.existsSync(found)) {
116
return found;
117
}
118
}
119
}
120
121
throw new Error(`Could not find ${path} in any subdirectory`);
122
}
123
124
function parseVersion(version: string) {
125
const match = /^(\d+)\.(\d+)\.(\d+)/.exec(version);
126
if (!match) {
127
throw new Error(`Invalid version string: ${version}`);
128
}
129
const [, major, minor, patch] = match;
130
return { major: parseInt(major), minor: parseInt(minor), patch: parseInt(patch) };
131
}
132
133
export function getDevElectronPath(): string {
134
const buildPath = join(root, '.build');
135
const product = require(join(root, 'product.json'));
136
137
switch (process.platform) {
138
case 'darwin':
139
return join(buildPath, 'electron', `${product.nameLong}.app`, 'Contents', 'MacOS', `${product.nameShort}`);
140
case 'linux':
141
return join(buildPath, 'electron', `${product.applicationName}`);
142
case 'win32':
143
return join(buildPath, 'electron', `${product.nameShort}.exe`);
144
default:
145
throw new Error('Unsupported platform.');
146
}
147
}
148
149
export function getBuildElectronPath(root: string): string {
150
switch (process.platform) {
151
case 'darwin': {
152
const packageJson = require(join(root, 'Contents', 'Resources', 'app', 'package.json'));
153
const product = require(join(root, 'Contents', 'Resources', 'app', 'product.json'));
154
const { major, minor } = parseVersion(packageJson.version);
155
// For macOS builds using the legacy Electron binary name, versions up to and including
156
// 1.109.x ship the executable as "Electron". From later versions onward, the executable
157
// is renamed to match product.nameShort. This check preserves compatibility with older
158
// builds; update the cutoff here only if the binary naming scheme changes again.
159
if (major === 1 && minor <= 109) {
160
return join(root, 'Contents', 'MacOS', 'Electron');
161
} else {
162
return join(root, 'Contents', 'MacOS', product.nameShort);
163
}
164
}
165
case 'linux': {
166
const product = require(join(root, 'resources', 'app', 'product.json'));
167
return join(root, product.applicationName);
168
}
169
case 'win32': {
170
const productPath = findFilePath(root, join('resources', 'app', 'product.json'));
171
const product = require(productPath);
172
return join(root, `${product.nameShort}.exe`);
173
}
174
default:
175
throw new Error('Unsupported platform.');
176
}
177
}
178
179
export function getBuildVersion(root: string): string {
180
switch (process.platform) {
181
case 'darwin':
182
return require(join(root, 'Contents', 'Resources', 'app', 'package.json')).version;
183
case 'win32': {
184
const packagePath = findFilePath(root, join('resources', 'app', 'package.json'));
185
return require(packagePath).version;
186
}
187
default:
188
return require(join(root, 'resources', 'app', 'package.json')).version;
189
}
190
}
191
192