mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-28 05:55:17 -07:00
Tighten bash shell option handling (#12532)
This commit is contained in:
@@ -186,7 +186,10 @@ describe('ShellExecutionService', () => {
|
||||
|
||||
expect(mockPtySpawn).toHaveBeenCalledWith(
|
||||
'bash',
|
||||
['-c', 'ls -l'],
|
||||
[
|
||||
'-c',
|
||||
'shopt -u promptvars nullglob extglob nocaseglob dotglob; ls -l',
|
||||
],
|
||||
expect.any(Object),
|
||||
);
|
||||
expect(result.exitCode).toBe(0);
|
||||
@@ -539,7 +542,10 @@ describe('ShellExecutionService', () => {
|
||||
|
||||
expect(mockPtySpawn).toHaveBeenCalledWith(
|
||||
'bash',
|
||||
['-c', 'ls "foo bar"'],
|
||||
[
|
||||
'-c',
|
||||
'shopt -u promptvars nullglob extglob nocaseglob dotglob; ls "foo bar"',
|
||||
],
|
||||
expect.any(Object),
|
||||
);
|
||||
});
|
||||
@@ -691,7 +697,10 @@ describe('ShellExecutionService child_process fallback', () => {
|
||||
|
||||
expect(mockCpSpawn).toHaveBeenCalledWith(
|
||||
'bash',
|
||||
['-c', 'ls -l'],
|
||||
[
|
||||
'-c',
|
||||
'shopt -u promptvars nullglob extglob nocaseglob dotglob; ls -l',
|
||||
],
|
||||
expect.objectContaining({ shell: false, detached: true }),
|
||||
);
|
||||
expect(result.exitCode).toBe(0);
|
||||
@@ -981,7 +990,10 @@ describe('ShellExecutionService child_process fallback', () => {
|
||||
|
||||
expect(mockCpSpawn).toHaveBeenCalledWith(
|
||||
'bash',
|
||||
['-c', 'ls "foo bar"'],
|
||||
[
|
||||
'-c',
|
||||
'shopt -u promptvars nullglob extglob nocaseglob dotglob; ls "foo bar"',
|
||||
],
|
||||
expect.objectContaining({
|
||||
shell: false,
|
||||
detached: true,
|
||||
|
||||
@@ -12,7 +12,7 @@ import { TextDecoder } from 'node:util';
|
||||
import os from 'node:os';
|
||||
import type { IPty } from '@lydell/node-pty';
|
||||
import { getCachedEncodingForBuffer } from '../utils/systemEncoding.js';
|
||||
import { getShellConfiguration } from '../utils/shell-utils.js';
|
||||
import { getShellConfiguration, type ShellType } from '../utils/shell-utils.js';
|
||||
import { isBinary } from '../utils/textUtils.js';
|
||||
import pkg from '@xterm/headless';
|
||||
import {
|
||||
@@ -24,6 +24,22 @@ const { Terminal } = pkg;
|
||||
const SIGKILL_TIMEOUT_MS = 200;
|
||||
const MAX_CHILD_PROCESS_BUFFER_SIZE = 16 * 1024 * 1024; // 16MB
|
||||
|
||||
const BASH_SHOPT_OPTIONS = 'promptvars nullglob extglob nocaseglob dotglob';
|
||||
const BASH_SHOPT_GUARD = `shopt -u ${BASH_SHOPT_OPTIONS};`;
|
||||
|
||||
function ensurePromptvarsDisabled(command: string, shell: ShellType): string {
|
||||
if (shell !== 'bash') {
|
||||
return command;
|
||||
}
|
||||
|
||||
const trimmed = command.trimStart();
|
||||
if (trimmed.startsWith(BASH_SHOPT_GUARD)) {
|
||||
return command;
|
||||
}
|
||||
|
||||
return `${BASH_SHOPT_GUARD} ${command}`;
|
||||
}
|
||||
|
||||
/** A structured result from a shell command execution. */
|
||||
export interface ShellExecutionResult {
|
||||
/** The raw, unprocessed output buffer. */
|
||||
@@ -190,8 +206,9 @@ export class ShellExecutionService {
|
||||
): ShellExecutionHandle {
|
||||
try {
|
||||
const isWindows = os.platform() === 'win32';
|
||||
const { executable, argsPrefix } = getShellConfiguration();
|
||||
const spawnArgs = [...argsPrefix, commandToExecute];
|
||||
const { executable, argsPrefix, shell } = getShellConfiguration();
|
||||
const guardedCommand = ensurePromptvarsDisabled(commandToExecute, shell);
|
||||
const spawnArgs = [...argsPrefix, guardedCommand];
|
||||
|
||||
const child = cpSpawn(executable, spawnArgs, {
|
||||
cwd,
|
||||
@@ -403,8 +420,9 @@ export class ShellExecutionService {
|
||||
try {
|
||||
const cols = shellExecutionConfig.terminalWidth ?? 80;
|
||||
const rows = shellExecutionConfig.terminalHeight ?? 30;
|
||||
const { executable, argsPrefix } = getShellConfiguration();
|
||||
const args = [...argsPrefix, commandToExecute];
|
||||
const { executable, argsPrefix, shell } = getShellConfiguration();
|
||||
const guardedCommand = ensurePromptvarsDisabled(commandToExecute, shell);
|
||||
const args = [...argsPrefix, guardedCommand];
|
||||
|
||||
const ptyProcess = ptyInfo.module.spawn(executable, args, {
|
||||
cwd,
|
||||
|
||||
Reference in New Issue
Block a user