Skip to content

Commit 50afe68

Browse files
committed
fix: improve flexibility of runVSCodeCommand
1 parent 021f593 commit 50afe68

File tree

3 files changed

+54
-31
lines changed

3 files changed

+54
-31
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
### 2.4.0 | 2024-05-24
44

55
- Allow installing unreleased builds using an `-unreleased` suffix, such as `insiders-unreleased`.
6+
- Allow passing different data directories in `runVSCodeCommand`, using it for extension development.
67

78
### 2.3.10 | 2024-05-13
89

lib/runTest.ts

+2-22
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import * as cp from 'child_process';
7-
import * as path from 'path';
8-
import { DownloadOptions, defaultCachePath, downloadAndUnzipVSCode } from './download';
9-
import { killTree } from './util';
7+
import { DownloadOptions, downloadAndUnzipVSCode } from './download';
8+
import { getProfileArguments, killTree } from './util';
109

1110
export interface TestOptions extends Partial<DownloadOptions> {
1211
/**
@@ -108,25 +107,6 @@ export async function runTests(options: TestOptions): Promise<number> {
108107

109108
return innerRunTests(options.vscodeExecutablePath, args, options.extensionTestsEnv);
110109
}
111-
112-
/** Adds the extensions and user data dir to the arguments for the VS Code CLI */
113-
export function getProfileArguments(args: readonly string[]) {
114-
const out: string[] = [];
115-
if (!hasArg('extensions-dir', args)) {
116-
out.push(`--extensions-dir=${path.join(defaultCachePath, 'extensions')}`);
117-
}
118-
119-
if (!hasArg('user-data-dir', args)) {
120-
out.push(`--user-data-dir=${path.join(defaultCachePath, 'user-data')}`);
121-
}
122-
123-
return out;
124-
}
125-
126-
function hasArg(argName: string, argList: readonly string[]) {
127-
return argList.some((a) => a === `--${argName}` || a.startsWith(`--${argName}=`));
128-
}
129-
130110
const SIGINT = 'SIGINT';
131111

132112
async function innerRunTests(

lib/util.ts

+51-9
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import * as https from 'https';
1111
import * as createHttpsProxyAgent from 'https-proxy-agent';
1212
import * as path from 'path';
1313
import { URL } from 'url';
14-
import { DownloadOptions, DownloadPlatform, downloadAndUnzipVSCode } from './download';
14+
import { DownloadOptions, DownloadPlatform, defaultCachePath, downloadAndUnzipVSCode } from './download';
1515
import * as request from './request';
16-
import { TestOptions, getProfileArguments } from './runTest';
16+
import { TestOptions } from './runTest';
1717

1818
export let systemDefaultPlatform: DownloadPlatform;
1919

@@ -219,7 +219,39 @@ export function resolveCliArgsFromVSCodeExecutablePath(
219219
return args;
220220
}
221221

222-
export type RunVSCodeCommandOptions = Partial<DownloadOptions> & { spawn?: SpawnOptions };
222+
export interface RunVSCodeCommandOptions extends Partial<DownloadOptions> {
223+
/**
224+
* Additional options to pass to `child_process.spawn`
225+
*/
226+
spawn?: SpawnOptions;
227+
228+
/**
229+
* Whether VS Code should be launched using default settings and extensions
230+
* installed on this machine. If `false`, then separate directories will be
231+
* used inside the `.vscode-test` folder within the project.
232+
*
233+
* Defaults to `false`.
234+
*/
235+
reuseMachineInstall?: boolean;
236+
}
237+
238+
/** Adds the extensions and user data dir to the arguments for the VS Code CLI */
239+
export function getProfileArguments(args: readonly string[]) {
240+
const out: string[] = [];
241+
if (!hasArg('extensions-dir', args)) {
242+
out.push(`--extensions-dir=${path.join(defaultCachePath, 'extensions')}`);
243+
}
244+
245+
if (!hasArg('user-data-dir', args)) {
246+
out.push(`--user-data-dir=${path.join(defaultCachePath, 'user-data')}`);
247+
}
248+
249+
return out;
250+
}
251+
252+
export function hasArg(argName: string, argList: readonly string[]) {
253+
return argList.some((a) => a === `--${argName}` || a.startsWith(`--${argName}=`));
254+
}
223255

224256
export class VSCodeCommandError extends Error {
225257
constructor(
@@ -233,20 +265,30 @@ export class VSCodeCommandError extends Error {
233265
}
234266

235267
/**
236-
* Runs a VS Code command, and returns its output
268+
* Runs a VS Code command, and returns its output.
269+
*
237270
* @throws a {@link VSCodeCommandError} if the command fails
238271
*/
239-
export async function runVSCodeCommand(args: string[], options: RunVSCodeCommandOptions = {}) {
240-
const vscodeExecutablePath = await downloadAndUnzipVSCode(options);
241-
const [cli, ...baseArgs] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath);
272+
export async function runVSCodeCommand(_args: readonly string[], options: RunVSCodeCommandOptions = {}) {
273+
const args = _args.slice();
242274

243-
const shell = process.platform === 'win32';
275+
let executable = await downloadAndUnzipVSCode(options);
276+
let shell = false;
277+
if (!options.reuseMachineInstall) {
278+
args.push(...getProfileArguments(args));
279+
}
280+
281+
// Unless the user is manually running tests or extension development, then resolve to the CLI script
282+
if (!hasArg('extensionTestsPath', args) && !hasArg('extensionDevelopmentPath', args)) {
283+
executable = resolveCliPathFromVSCodeExecutablePath(executable, options?.platform ?? systemDefaultPlatform);
284+
shell = process.platform === 'win32'; // CVE-2024-27980
285+
}
244286

245287
return new Promise<{ stdout: string; stderr: string }>((resolve, reject) => {
246288
let stdout = '';
247289
let stderr = '';
248290

249-
const child = spawn(shell ? `"${cli}"` : cli, [...baseArgs, ...args], {
291+
const child = spawn(shell ? `"${executable}"` : executable, args, {
250292
stdio: 'pipe',
251293
shell,
252294
windowsHide: true,

0 commit comments

Comments
 (0)