perf(git): cache git rev-parse results within sessions
Multiple gt commands call git rev-parse --show-toplevel, adding ~50ms each invocation. Results rarely change within a session, and multiple agents calling git concurrently contend on .git/index.lock. Add cached RepoRoot() and RepoRootFrom() functions to the git package and update all callers to use them. This ensures a single git subprocess call per process for the common case of checking the current directory's repo root. Files updated: - internal/git/git.go: Add RepoRoot() and RepoRootFrom() - internal/cmd/prime.go: Use cached git.RepoRoot() - internal/cmd/molecule_status.go: Use cached git.RepoRoot() - internal/cmd/sling_helpers.go: Use cached git.RepoRoot() - internal/cmd/rig_quick_add.go: Use git.RepoRootFrom() for path arg - internal/version/stale.go: Use cached git.RepoRoot() Closes: bd-2zd.5
This commit is contained in:
@@ -9,8 +9,49 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Cached repo root for the current process.
|
||||
// Since CLI commands are short-lived and the working directory doesn't change
|
||||
// during a single invocation, caching this avoids repeated git subprocess calls
|
||||
// that add ~50ms each and contend on .git/index.lock.
|
||||
var (
|
||||
cachedRepoRoot string
|
||||
cachedRepoRootOnce sync.Once
|
||||
cachedRepoRootErr error
|
||||
)
|
||||
|
||||
// RepoRoot returns the root directory of the git repository containing the
|
||||
// current working directory. The result is cached for the lifetime of the process.
|
||||
// This avoids repeated git rev-parse calls that are expensive (~50ms each) and
|
||||
// can cause lock contention when multiple agents are running.
|
||||
func RepoRoot() (string, error) {
|
||||
cachedRepoRootOnce.Do(func() {
|
||||
cmd := exec.Command("git", "rev-parse", "--show-toplevel")
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
cachedRepoRootErr = err
|
||||
return
|
||||
}
|
||||
cachedRepoRoot = strings.TrimSpace(string(out))
|
||||
})
|
||||
return cachedRepoRoot, cachedRepoRootErr
|
||||
}
|
||||
|
||||
// RepoRootFrom returns the root directory of the git repository containing the
|
||||
// specified path. Unlike RepoRoot(), this is not cached because it depends on
|
||||
// the input path. Use RepoRoot() when checking the current working directory.
|
||||
func RepoRootFrom(path string) (string, error) {
|
||||
cmd := exec.Command("git", "rev-parse", "--show-toplevel")
|
||||
cmd.Dir = path
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.TrimSpace(string(out)), nil
|
||||
}
|
||||
|
||||
// GitError contains raw output from a git command for agent observation.
|
||||
// ZFC: Callers observe the raw output and decide what to do.
|
||||
// The error interface methods provide human-readable messages, but agents
|
||||
|
||||
Reference in New Issue
Block a user