Skip to content

Commit c7ba3d3

Browse files
authored
Avoid git subprocesses during sync project resolution (#590)
## Summary - Prefer the cheap filesystem `.git` walk for sync-time project extraction so normal repos and linked worktrees do not shell out to `git` per session. - Preserve the kit `gitrepo.MainRoot` fallback for rare live-repo layouts when the local walk cannot resolve a root. - Add regression coverage for both sides: plain repos must not invoke `git`, and the git fallback remains available when local resolution misses. ## Investigation - Reproduced with isolated data dirs only (`AGENTSVIEW_DATA_DIR=/tmp/...`, also set `AGENTSVIEW_HOME=/tmp/...`); production DB was not touched. - Same source session set: about 35.7k discovered sessions. - `v0.31.1` cold sync: 1m12.7s. - `v0.32.0` cold sync: 4m31.4s. - Revised PR build cold sync: 1m14.2s. - 0.32.0 CPU profile showed ~190s cumulative under `go.kenn.io/kit/git/repo.MainRoot` / `os/exec` from `ExtractProjectFromCwdWithBranch`; revised PR profile returns to SQLite/file-read dominated work. ## Test Plan - [x] `go test ./internal/parser ./internal/sync ./cmd/agentsview` - [x] Isolated revised PR cold sync with `AGENTSVIEW_DATA_DIR=/tmp/agentsview-prof-pr-fallback`: 1m14.2s
1 parent 2e11aa7 commit c7ba3d3

2 files changed

Lines changed: 130 additions & 12 deletions

File tree

internal/parser/project.go

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -435,14 +435,7 @@ func findGitRepoRoot(ctx context.Context, cwd string) string {
435435
cwdMissing = true
436436
dir = filepath.Dir(dir)
437437
}
438-
439-
if !cwdMissing {
440-
opCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
441-
defer cancel()
442-
if root, err := gitrepo.MainRoot(opCtx, dir); err == nil {
443-
return root
444-
}
445-
}
438+
startDir := dir
446439

447440
// When the original path is gone, walk up to the first
448441
// existing ancestor and check its children for worktree
@@ -466,31 +459,60 @@ func findGitRepoRoot(ctx context.Context, cwd string) string {
466459
}
467460
}
468461

462+
root, conservative := findGitRepoRootLocal(dir)
463+
if root != "" && !conservative {
464+
return root
465+
}
466+
if !cwdMissing {
467+
if gitRoot := gitMainRoot(ctx, startDir); gitRoot != "" {
468+
return gitRoot
469+
}
470+
}
471+
return root
472+
}
473+
474+
func findGitRepoRootLocal(dir string) (root string, conservative bool) {
469475
for {
470476
gitPath := filepath.Join(dir, ".git")
471477
info, err := osStat(gitPath)
472478
if err == nil {
473479
if info.IsDir() {
474-
return dir
480+
return dir, false
475481
}
476482
if info.Mode().IsRegular() {
477483
if root := repoRootFromGitFile(dir, gitPath); root != "" {
478-
return root
484+
if root == dir {
485+
return root, true
486+
}
487+
return root, false
479488
}
480489
// Keep conservative fallback for gitfile repos
481490
// when metadata cannot be parsed.
482-
return dir
491+
return dir, true
483492
}
484493
}
485494

486495
parent := filepath.Dir(dir)
487496
if parent == dir {
488-
return ""
497+
return "", false
489498
}
490499
dir = parent
491500
}
492501
}
493502

503+
func gitMainRoot(ctx context.Context, dir string) string {
504+
if ctx == nil || dir == "" {
505+
return ""
506+
}
507+
opCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
508+
defer cancel()
509+
root, err := gitrepo.MainRoot(opCtx, dir)
510+
if err != nil {
511+
return ""
512+
}
513+
return root
514+
}
515+
494516
// repoRootFromSiblings checks child directories of dir for
495517
// linked-worktree .git files and uses them to discover the
496518
// true repo root. Submodule .git files are skipped, and all

internal/parser/project_git_test.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,98 @@ func TestExtractProjectFromCwdWithBranchContext_GitWorktreeMainRoot(t *testing.T
106106
"kit-backed worktree resolution should use the main repo name")
107107
}
108108

109+
func TestExtractProjectFromCwdPlainRepoDoesNotInvokeGit(t *testing.T) {
110+
if runtime.GOOS == "windows" {
111+
t.Skip("test uses a POSIX shell git shim")
112+
}
113+
114+
root := t.TempDir()
115+
binDir := filepath.Join(root, "bin")
116+
mustMkdirAll(t, binDir)
117+
marker := filepath.Join(root, "git-invoked")
118+
fakeGit := filepath.Join(binDir, "git")
119+
mustWriteFile(t, fakeGit, "#!/bin/sh\n: > "+shellQuote(marker)+"\nexit 1\n")
120+
require.NoError(t, os.Chmod(fakeGit, 0o755), "chmod fake git")
121+
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
122+
123+
repo := filepath.Join(root, "plain-repo")
124+
subdir := filepath.Join(repo, "internal", "parser")
125+
mustMkdirAll(t, filepath.Join(repo, ".git"))
126+
mustMkdirAll(t, subdir)
127+
128+
assert.Equal(t, "plain_repo", ExtractProjectFromCwd(subdir))
129+
assert.NoFileExists(t, marker, "plain .git directory should resolve without invoking git")
130+
}
131+
132+
func TestExtractProjectFromCwdFallsBackToGitWhenLocalWalkMisses(t *testing.T) {
133+
if runtime.GOOS == "windows" {
134+
t.Skip("test uses a POSIX shell git shim")
135+
}
136+
137+
root := t.TempDir()
138+
binDir := filepath.Join(root, "bin")
139+
mustMkdirAll(t, binDir)
140+
gitLog := filepath.Join(root, "git-log")
141+
repo := filepath.Join(root, "virtual-repo")
142+
cwd := filepath.Join(repo, "internal", "parser")
143+
mustMkdirAll(t, cwd)
144+
145+
fakeGit := filepath.Join(binDir, "git")
146+
mustWriteFile(t, fakeGit, "#!/bin/sh\n"+
147+
"echo \"$*\" >> "+shellQuote(gitLog)+"\n"+
148+
"case \"$*\" in\n"+
149+
" 'rev-parse --git-dir') echo .git ;;\n"+
150+
" 'rev-parse --git-common-dir') echo .git ;;\n"+
151+
" 'rev-parse --show-toplevel') echo "+shellQuote(repo)+" ;;\n"+
152+
" *) exit 1 ;;\n"+
153+
"esac\n")
154+
require.NoError(t, os.Chmod(fakeGit, 0o755), "chmod fake git")
155+
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
156+
157+
assert.Equal(t, "virtual_repo",
158+
ExtractProjectFromCwdWithBranchContext(context.Background(), cwd, ""))
159+
assert.FileExists(t, gitLog, "git fallback should be used when local walk misses")
160+
}
161+
162+
func TestExtractProjectFromCwdTriesGitBeforeConservativeGitFileFallback(
163+
t *testing.T,
164+
) {
165+
if runtime.GOOS == "windows" {
166+
t.Skip("test uses a POSIX shell git shim")
167+
}
168+
169+
root := t.TempDir()
170+
binDir := filepath.Join(root, "bin")
171+
mustMkdirAll(t, binDir)
172+
gitLog := filepath.Join(root, "git-log")
173+
mainRepo := filepath.Join(root, "main-repo")
174+
worktree := filepath.Join(root, "feature-worktree")
175+
cwd := filepath.Join(worktree, "internal", "parser")
176+
commonDir := filepath.Join(mainRepo, ".git")
177+
externalGitDir := filepath.Join(root, "bare-common", "worktrees", "feature")
178+
mustMkdirAll(t, commonDir)
179+
mustMkdirAll(t, externalGitDir)
180+
mustMkdirAll(t, cwd)
181+
mustWriteFile(t, filepath.Join(worktree, ".git"),
182+
"gitdir: "+externalGitDir+"\n")
183+
184+
fakeGit := filepath.Join(binDir, "git")
185+
mustWriteFile(t, fakeGit, "#!/bin/sh\n"+
186+
"echo \"$*\" >> "+shellQuote(gitLog)+"\n"+
187+
"case \"$*\" in\n"+
188+
" 'rev-parse --git-dir') echo "+shellQuote(externalGitDir)+" ;;\n"+
189+
" 'rev-parse --git-common-dir') echo "+shellQuote(commonDir)+" ;;\n"+
190+
" *) exit 1 ;;\n"+
191+
"esac\n")
192+
require.NoError(t, os.Chmod(fakeGit, 0o755), "chmod fake git")
193+
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
194+
195+
assert.Equal(t, "main_repo",
196+
ExtractProjectFromCwdWithBranchContext(context.Background(), cwd, ""))
197+
assert.FileExists(t, gitLog,
198+
"git fallback should run before accepting conservative gitfile root")
199+
}
200+
109201
func TestExtractProjectFromCwd_DeletedNestedWorktree(t *testing.T) {
110202
// Simulates a nested worktree layout where the session's
111203
// worktree has been deleted but a sibling worktree still
@@ -591,6 +683,10 @@ func mustWriteFile(t *testing.T, path, content string) {
591683
"WriteFile(%q)", path)
592684
}
593685

686+
func shellQuote(s string) string {
687+
return "'" + strings.ReplaceAll(s, "'", "'\\''") + "'"
688+
}
689+
594690
func skipIfNoGit(t *testing.T) {
595691
t.Helper()
596692
if _, err := exec.LookPath("git"); err != nil {

0 commit comments

Comments
 (0)