-
Notifications
You must be signed in to change notification settings - Fork 992
Expand file tree
/
Copy pathwin-shell.ts
More file actions
65 lines (60 loc) · 2.15 KB
/
win-shell.ts
File metadata and controls
65 lines (60 loc) · 2.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
/**
* Windows shell quoting utilities for child_process.spawn().
*
* When spawn() is called with `shell: true` on Windows, the command and
* arguments are concatenated and passed to cmd.exe. Paths containing spaces
* must be wrapped in double-quotes to prevent cmd.exe from splitting them
* into separate tokens.
*
* This module is intentionally dependency-free so it can be unit-tested
* without mocking Electron.
*/
import path from 'path';
/**
* Quote a path/value for safe use with Windows cmd.exe (shell: true in spawn).
*
* When Node.js spawn is called with `shell: true` on Windows, cmd.exe
* interprets spaces as argument separators. Wrapping the value in double
* quotes prevents this. On non-Windows platforms the value is returned
* unchanged so this function can be called unconditionally.
*/
export function quoteForCmd(value: string): string {
if (process.platform !== 'win32') return value;
if (!value.includes(' ')) return value;
if (value.startsWith('"') && value.endsWith('"')) return value;
return `"${value}"`;
}
/**
* Determine whether a spawn call needs `shell: true` on Windows.
*
* Full (absolute) paths can be executed directly by the OS via
* CreateProcessW, which handles spaces correctly without a shell.
* Simple command names (e.g. 'uv', 'node') need shell for PATH/PATHEXT
* resolution on Windows.
*/
export function needsWinShell(bin: string): boolean {
if (process.platform !== 'win32') return false;
return !path.win32.isAbsolute(bin);
}
/**
* Prepare command and args for spawn(), handling Windows paths with spaces.
*
* Returns the shell option, the (possibly quoted) command, and the
* (possibly quoted) args array ready for child_process.spawn().
*/
export function prepareWinSpawn(
command: string,
args: string[],
forceShell?: boolean,
): { shell: boolean; command: string; args: string[] } {
const isWin = process.platform === 'win32';
const useShell = forceShell ?? (isWin && !path.win32.isAbsolute(command));
if (!useShell || !isWin) {
return { shell: useShell, command, args };
}
return {
shell: true,
command: quoteForCmd(command),
args: args.map(a => quoteForCmd(a)),
};
}