From 75bc7be9708a448d86d44b0f5f58dd57366331c4 Mon Sep 17 00:00:00 2001 From: Christopher Tso Date: Thu, 21 May 2026 04:52:05 +0200 Subject: [PATCH] fix(workspace): preserve git env for remote clones --- src/core/git.ts | 13 +++++++++---- src/core/managed-repos.ts | 5 +++-- tests/unit/core/git.test.ts | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 tests/unit/core/git.test.ts diff --git a/src/core/git.ts b/src/core/git.ts index 2d3bb30c..31549b0b 100644 --- a/src/core/git.ts +++ b/src/core/git.ts @@ -14,6 +14,14 @@ const CLONE_TIMEOUT_MS = (() => { return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_CLONE_TIMEOUT_MS; })(); +export function createGitEnv(): NodeJS.ProcessEnv { + return { + ...process.env, + GIT_TERMINAL_PROMPT: '0', + GIT_LFS_SKIP_SMUDGE: '1', + }; +} + function createGit(baseDir?: string) { return simpleGit(baseDir, { timeout: { block: CLONE_TIMEOUT_MS }, @@ -23,10 +31,7 @@ function createGit(baseDir?: string) { 'filter.lfs.clean=', 'filter.lfs.process=', ], - }).env({ - GIT_TERMINAL_PROMPT: '0', - GIT_LFS_SKIP_SMUDGE: '1', - }); + }).env(createGitEnv()); } /** diff --git a/src/core/managed-repos.ts b/src/core/managed-repos.ts index 83e2db05..b498fa7f 100644 --- a/src/core/managed-repos.ts +++ b/src/core/managed-repos.ts @@ -4,6 +4,7 @@ import { dirname, resolve } from 'node:path'; import simpleGit from 'simple-git'; import type { Repository, ManagedMode } from '../models/workspace-config.js'; import { getHomeDir } from '../constants.js'; +import { createGitEnv } from './git.js'; const CLONE_TIMEOUT_MS = 120_000; // 2 minutes for full clone @@ -80,7 +81,7 @@ export function buildCloneUrl(source: string, repo: string): string { */ async function cloneRepo(url: string, dest: string, branch?: string): Promise { await mkdir(dirname(dest), { recursive: true }); - const git = simpleGit({ timeout: { block: CLONE_TIMEOUT_MS } }); + const git = simpleGit({ timeout: { block: CLONE_TIMEOUT_MS } }).env(createGitEnv()); const cloneOptions = branch ? ['--branch', branch] : []; await git.clone(url, dest, cloneOptions); } @@ -90,7 +91,7 @@ async function cloneRepo(url: string, dest: string, branch?: string): Promise { - const git = simpleGit(repoPath, { timeout: { block: CLONE_TIMEOUT_MS } }); + const git = simpleGit(repoPath, { timeout: { block: CLONE_TIMEOUT_MS } }).env(createGitEnv()); // Check for uncommitted changes const status = await git.status(); diff --git a/tests/unit/core/git.test.ts b/tests/unit/core/git.test.ts new file mode 100644 index 00000000..2d3acb8d --- /dev/null +++ b/tests/unit/core/git.test.ts @@ -0,0 +1,34 @@ +import { afterEach, beforeEach, describe, expect, it } from 'bun:test'; +import { createGitEnv } from '../../../src/core/git.js'; + +describe('createGitEnv', () => { + const originalHome = process.env.HOME; + const originalPath = process.env.PATH; + const originalPrompt = process.env.GIT_TERMINAL_PROMPT; + const originalSkipSmudge = process.env.GIT_LFS_SKIP_SMUDGE; + + beforeEach(() => { + process.env.HOME = '/tmp/test-home'; + process.env.PATH = '/tmp/test-path'; + process.env.GIT_TERMINAL_PROMPT = '1'; + process.env.GIT_LFS_SKIP_SMUDGE = '0'; + }); + + afterEach(() => { + process.env.HOME = originalHome; + process.env.PATH = originalPath; + process.env.GIT_TERMINAL_PROMPT = originalPrompt; + process.env.GIT_LFS_SKIP_SMUDGE = originalSkipSmudge; + }); + + it('preserves inherited git environment while applying allagents overrides', () => { + const gitEnv = createGitEnv(); + + expect(gitEnv).toMatchObject({ + HOME: '/tmp/test-home', + PATH: '/tmp/test-path', + GIT_TERMINAL_PROMPT: '0', + GIT_LFS_SKIP_SMUDGE: '1', + }); + }); +});