Fix bug executing commands in windows whose flags contain spaces (#5317)

This commit is contained in:
Tommaso Sciortino 2025-07-31 17:27:07 -07:00 committed by GitHub
parent 6f7beb414c
commit a3a432e3cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 26 additions and 15 deletions

View File

@ -91,9 +91,9 @@ describe('ShellExecutionService', () => {
}); });
expect(mockSpawn).toHaveBeenCalledWith( expect(mockSpawn).toHaveBeenCalledWith(
'bash', 'ls -l',
['-c', 'ls -l'], [],
expect.any(Object), expect.objectContaining({ shell: 'bash' }),
); );
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.signal).toBeNull(); expect(result.signal).toBeNull();
@ -334,23 +334,31 @@ describe('ShellExecutionService', () => {
describe('Platform-Specific Behavior', () => { describe('Platform-Specific Behavior', () => {
it('should use cmd.exe on Windows', async () => { it('should use cmd.exe on Windows', async () => {
mockPlatform.mockReturnValue('win32'); mockPlatform.mockReturnValue('win32');
await simulateExecution('dir', (cp) => cp.emit('exit', 0, null)); await simulateExecution('dir "foo bar"', (cp) =>
cp.emit('exit', 0, null),
);
expect(mockSpawn).toHaveBeenCalledWith( expect(mockSpawn).toHaveBeenCalledWith(
'cmd.exe', 'dir "foo bar"',
['/c', 'dir'], [],
expect.objectContaining({ detached: false }), expect.objectContaining({
shell: true,
detached: false,
}),
); );
}); });
it('should use bash and detached process group on Linux', async () => { it('should use bash and detached process group on Linux', async () => {
mockPlatform.mockReturnValue('linux'); mockPlatform.mockReturnValue('linux');
await simulateExecution('ls', (cp) => cp.emit('exit', 0, null)); await simulateExecution('ls "foo bar"', (cp) => cp.emit('exit', 0, null));
expect(mockSpawn).toHaveBeenCalledWith( expect(mockSpawn).toHaveBeenCalledWith(
'bash', 'ls "foo bar"',
['-c', 'ls'], [],
expect.objectContaining({ detached: true }), expect.objectContaining({
shell: 'bash',
detached: true,
}),
); );
}); });
}); });

View File

@ -89,13 +89,16 @@ export class ShellExecutionService {
abortSignal: AbortSignal, abortSignal: AbortSignal,
): ShellExecutionHandle { ): ShellExecutionHandle {
const isWindows = os.platform() === 'win32'; const isWindows = os.platform() === 'win32';
const shell = isWindows ? 'cmd.exe' : 'bash';
const shellArgs = [isWindows ? '/c' : '-c', commandToExecute];
const child = spawn(shell, shellArgs, { const child = spawn(commandToExecute, [], {
cwd, cwd,
stdio: ['ignore', 'pipe', 'pipe'], stdio: ['ignore', 'pipe', 'pipe'],
detached: !isWindows, // Use process groups on non-Windows for robust killing // Use bash unless in Windows (since it doesn't support bash).
// For windows, just use the default.
shell: isWindows ? true : 'bash',
// Use process groups on non-Windows for robust killing.
// Windows process termination is handled by `taskkill /t`.
detached: !isWindows,
env: { env: {
...process.env, ...process.env,
GEMINI_CLI: '1', GEMINI_CLI: '1',