Skip to content

Commit 09a000c

Browse files
committed
Refactor 'spawn to a string+code' into a standalone util
1 parent e631cb9 commit 09a000c

File tree

2 files changed

+40
-28
lines changed

2 files changed

+40
-28
lines changed

src/interceptors/terminal/fresh-terminal-interceptor.ts

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { findExecutableById } from '@httptoolkit/osx-find-executable';
1010
import { Interceptor } from '..';
1111
import { HtkConfig } from '../../config';
1212
import { reportError, addBreadcrumb } from '../../error-tracking';
13+
import { spawnToResult } from '../../util';
14+
1315
import { getTerminalEnvVars } from './terminal-env-overrides';
1416
import { editShellStartupScripts, resetShellStartupScripts } from './terminal-scripts';
1517

@@ -27,28 +29,6 @@ interface SpawnArgs {
2729
skipStartupScripts?: true;
2830
}
2931

30-
// Spawn a command, and resolve with all stdout & stderr output as strings when it terminates
31-
const spawnAndCollectOutput = (command: string, args: string[] = []): Promise<{ stdout: string, stderr: string }> => {
32-
return new Promise((resolve, reject) => {
33-
const childProc = spawn(command, args, { stdio: 'pipe' });
34-
const { stdout, stderr } = childProc;
35-
36-
const stdoutData: Buffer[] = [];
37-
stdout.on('data', (d) => stdoutData.push(d));
38-
const stderrData: Buffer[] = [];
39-
stderr.on('data', (d) => stderrData.push(d));
40-
41-
childProc.once('error', reject);
42-
childProc.once('close', () => {
43-
// Note that we do _not_ check the error code
44-
resolve({
45-
stdout: Buffer.concat(stdoutData).toString(),
46-
stderr: Buffer.concat(stderrData).toString()
47-
});
48-
});
49-
});
50-
};
51-
5232
const getTerminalCommand = _.memoize(async (): Promise<SpawnArgs | null> => {
5333
let result: Promise<SpawnArgs | null>;
5434

@@ -138,7 +118,7 @@ const getXTerminalCommand = async (command = 'x-terminal-emulator'): Promise<Spa
138118
try {
139119
// Run the command with -h to get some output we can use to infer the terminal itself.
140120
// --version would be nice, but the debian wrapper ignores it. --help isn't supported by xterm.
141-
const { stdout } = await spawnAndCollectOutput(command, ['-h']);
121+
const { stdout } = await spawnToResult(command, ['-h']);
142122
const helpOutput = stdout.toLowerCase().replace(/[^\w\d]+/g, ' ');
143123

144124
if (helpOutput.includes('gnome terminal') && await commandExists('gnome-terminal')) {
@@ -164,7 +144,7 @@ const getXTerminalCommand = async (command = 'x-terminal-emulator'): Promise<Spa
164144
const getKonsoleTerminalCommand = async (command = 'konsole'): Promise<SpawnArgs> => {
165145
let extraArgs: string[] = [];
166146

167-
const { stdout } = await spawnAndCollectOutput(command, ['--help']);
147+
const { stdout } = await spawnToResult(command, ['--help']);
168148

169149
// Forces Konsole to run in the foreground, with no separate process
170150
// Seems to be well supported for a long time, but check just in case
@@ -178,7 +158,7 @@ const getKonsoleTerminalCommand = async (command = 'konsole'): Promise<SpawnArgs
178158
const getGnomeTerminalCommand = async (command = 'gnome-terminal'): Promise<SpawnArgs> => {
179159
let extraArgs: string[] = [];
180160

181-
const { stdout } = await spawnAndCollectOutput(command, ['--help-all']);
161+
const { stdout } = await spawnToResult(command, ['--help-all']);
182162

183163
// Officially supported option, but only supported in v3.28+
184164
if (stdout.includes('--wait')) {
@@ -200,7 +180,7 @@ const getGnomeTerminalCommand = async (command = 'gnome-terminal'): Promise<Spaw
200180
const getXfceTerminalCommand = async (command = 'xfce4-terminal'): Promise<SpawnArgs> => {
201181
let extraArgs: string[] = [];
202182

203-
const { stdout } = await spawnAndCollectOutput(command, ['--help']);
183+
const { stdout } = await spawnToResult(command, ['--help']);
204184

205185
// Disables the XFCE terminal server for this terminal, so it runs in the foreground.
206186
// Seems to be well supported for a long time, but check just in case

src/util.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { spawn } from 'child_process';
1+
import { spawn, SpawnOptions } from 'child_process';
22

33
export function delay(durationMs: number): Promise<void> {
44
return new Promise((resolve) => setTimeout(resolve, durationMs));
@@ -32,4 +32,36 @@ export async function windowsKill(processMatcher: string) {
3232
], {
3333
stdio: 'inherit'
3434
});
35-
}
35+
}
36+
37+
// Spawn a command, and resolve with all output as strings when it terminates
38+
export function spawnToResult(command: string, args: string[] = [], inheritOutput = false): Promise<{
39+
exitCode?: number,
40+
stdout: string,
41+
stderr: string
42+
}> {
43+
return new Promise((resolve, reject) => {
44+
const childProc = spawn(command, args, { stdio: 'pipe' });
45+
const { stdout, stderr } = childProc;
46+
47+
const stdoutData: Buffer[] = [];
48+
stdout.on('data', (d) => stdoutData.push(d));
49+
const stderrData: Buffer[] = [];
50+
stderr.on('data', (d) => stderrData.push(d));
51+
52+
if (inheritOutput) {
53+
stdout.pipe(process.stdout);
54+
stderr.pipe(process.stderr);
55+
}
56+
57+
childProc.once('error', reject);
58+
childProc.once('close', (code?: number) => {
59+
// Note that we do _not_ check the error code, we just return it
60+
resolve({
61+
exitCode: code,
62+
stdout: Buffer.concat(stdoutData).toString(),
63+
stderr: Buffer.concat(stderrData).toString()
64+
});
65+
});
66+
});
67+
};

0 commit comments

Comments
 (0)