fix(repocache): pass explicit env to remote-facing git subprocesses (#1029)

fix(repocache): pass explicit env to remote-facing git subprocesses
This commit is contained in:
marcel
2026-04-15 01:15:36 -04:00
committed by GitHub
parent 45dad23074
commit 287a9eb546
2 changed files with 49 additions and 2 deletions

View File

@@ -14,6 +14,14 @@ import (
"time"
)
// gitEnv returns an environment for git subprocesses that contact remotes.
// It passes the full daemon environment so credential helpers (e.g. gh) can
// locate their config, and disables TTY prompting so auth failures produce
// clear errors instead of blocking on a non-existent terminal.
func gitEnv() []string {
return append(os.Environ(), "GIT_TERMINAL_PROMPT=0")
}
// RepoInfo describes a repository to cache.
type RepoInfo struct {
URL string
@@ -157,6 +165,7 @@ const modernFetchRefspec = "+refs/heads/*:refs/remotes/origin/*"
func gitCloneBare(url, dest string) error {
cmd := exec.Command("git", "clone", "--bare", url, dest)
cmd.Env = gitEnv()
if out, err := cmd.CombinedOutput(); err != nil {
// Clean up partial clone.
os.RemoveAll(dest)
@@ -195,7 +204,9 @@ func gitFetch(barePath string) error {
// getRemoteDefaultBranch, but the modern-cache default-branch-change
// path (the only path that can't be recovered any other way) relies
// on this call.
_ = exec.Command("git", "-C", barePath, "remote", "set-head", "origin", "--auto").Run()
cmd := exec.Command("git", "-C", barePath, "remote", "set-head", "origin", "--auto")
cmd.Env = gitEnv()
_ = cmd.Run()
return nil
}
@@ -203,6 +214,7 @@ func gitFetch(barePath string) error {
// gitFetch, which migrates legacy caches first.
func runGitFetch(barePath string) error {
cmd := exec.Command("git", "-C", barePath, "fetch", "origin")
cmd.Env = gitEnv()
if out, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("git fetch: %s: %w", strings.TrimSpace(string(out)), err)
}
@@ -235,7 +247,9 @@ func ensureRemoteTrackingLayout(barePath string) error {
}
// Set refs/remotes/origin/HEAD so getRemoteDefaultBranch can read it.
// Non-fatal: if this fails we fall back to origin/main, origin/master.
_ = exec.Command("git", "-C", barePath, "remote", "set-head", "origin", "--auto").Run()
cmd := exec.Command("git", "-C", barePath, "remote", "set-head", "origin", "--auto")
cmd.Env = gitEnv()
_ = cmd.Run()
return nil
}

View File

@@ -13,6 +13,39 @@ func testLogger() *slog.Logger {
return slog.Default()
}
func TestGitEnv(t *testing.T) {
t.Parallel()
env := gitEnv()
// Must contain GIT_TERMINAL_PROMPT=0.
found := false
for _, entry := range env {
if entry == "GIT_TERMINAL_PROMPT=0" {
found = true
break
}
}
if !found {
t.Error("gitEnv() must include GIT_TERMINAL_PROMPT=0")
}
// Must contain HOME from the current environment.
home := os.Getenv("HOME")
if home == "" {
t.Skip("HOME not set in test environment")
}
foundHome := false
for _, entry := range env {
if entry == "HOME="+home {
foundHome = true
break
}
}
if !foundHome {
t.Error("gitEnv() must include HOME from os.Environ()")
}
}
func TestBareDirName(t *testing.T) {
t.Parallel()
tests := []struct {