fix(core): safely append GIT_CONFIG overrides without breaking user config

This commit is contained in:
cocosheng-g
2026-03-02 17:33:18 -05:00
committed by Coco Sheng
parent 050fefe0c7
commit 0b332b41d7
2 changed files with 30 additions and 8 deletions

View File

@@ -1704,8 +1704,14 @@ describe('ShellExecutionService environment variables', () => {
await new Promise(process.nextTick);
});
it('should include headless git and gh environment variables in non-interactive mode', async () => {
it('should include headless git and gh environment variables in non-interactive mode and append git config safely', async () => {
vi.resetModules();
vi.stubEnv('GIT_CONFIG_COUNT', '2');
vi.stubEnv('GIT_CONFIG_KEY_0', 'core.editor');
vi.stubEnv('GIT_CONFIG_VALUE_0', 'vim');
vi.stubEnv('GIT_CONFIG_KEY_1', 'pull.rebase');
vi.stubEnv('GIT_CONFIG_VALUE_1', 'true');
const { ShellExecutionService } = await import(
'./shellExecutionService.js'
);
@@ -1729,13 +1735,23 @@ describe('ShellExecutionService environment variables', () => {
expect(cpEnv).toHaveProperty('GCM_INTERACTIVE', 'never');
expect(cpEnv).toHaveProperty('DISPLAY', '');
expect(cpEnv).toHaveProperty('DBUS_SESSION_BUS_ADDRESS', '');
expect(cpEnv).toHaveProperty('GIT_CONFIG_COUNT', '1');
expect(cpEnv).toHaveProperty('GIT_CONFIG_KEY_0', 'credential.helper');
expect(cpEnv).toHaveProperty('GIT_CONFIG_VALUE_0', '');
// Existing values should be preserved
expect(cpEnv).toHaveProperty('GIT_CONFIG_KEY_0', 'core.editor');
expect(cpEnv).toHaveProperty('GIT_CONFIG_VALUE_0', 'vim');
expect(cpEnv).toHaveProperty('GIT_CONFIG_KEY_1', 'pull.rebase');
expect(cpEnv).toHaveProperty('GIT_CONFIG_VALUE_1', 'true');
// The new credential.helper override should be appended at index 2
expect(cpEnv).toHaveProperty('GIT_CONFIG_COUNT', '3');
expect(cpEnv).toHaveProperty('GIT_CONFIG_KEY_2', 'credential.helper');
expect(cpEnv).toHaveProperty('GIT_CONFIG_VALUE_2', '');
// Ensure child_process exits
mockChildProcess.emit('exit', 0, null);
mockChildProcess.emit('close', 0, null);
await new Promise(process.nextTick);
vi.unstubAllEnvs();
});
});

View File

@@ -305,6 +305,12 @@ export class ShellExecutionService {
const guardedCommand = ensurePromptvarsDisabled(commandToExecute, shell);
const spawnArgs = [...argsPrefix, guardedCommand];
const sanitizedEnv = sanitizeEnvironment(process.env, sanitizationConfig);
const gitConfigCount = parseInt(
sanitizedEnv['GIT_CONFIG_COUNT'] || '0',
10,
);
const child = cpSpawn(executable, spawnArgs, {
cwd,
stdio: ['ignore', 'pipe', 'pipe'],
@@ -312,7 +318,7 @@ export class ShellExecutionService {
shell: false,
detached: !isWindows,
env: {
...sanitizeEnvironment(process.env, sanitizationConfig),
...sanitizedEnv,
[GEMINI_CLI_IDENTIFICATION_ENV_VAR]:
GEMINI_CLI_IDENTIFICATION_ENV_VAR_VALUE,
TERM: 'xterm-256color',
@@ -325,9 +331,9 @@ export class ShellExecutionService {
GCM_INTERACTIVE: 'never',
DISPLAY: '',
DBUS_SESSION_BUS_ADDRESS: '',
GIT_CONFIG_COUNT: '1',
GIT_CONFIG_KEY_0: 'credential.helper',
GIT_CONFIG_VALUE_0: '',
GIT_CONFIG_COUNT: (gitConfigCount + 1).toString(),
[`GIT_CONFIG_KEY_${gitConfigCount}`]: 'credential.helper',
[`GIT_CONFIG_VALUE_${gitConfigCount}`]: '',
PAGER: 'cat',
GIT_PAGER: 'cat',
},