Skip to content

perf(git): resolve the git binary once via a cached git_program() - #253

Merged
ScriptedAlchemy merged 1 commit into
masterfrom
perf/cached-git-program
Jul 3, 2026
Merged

perf(git): resolve the git binary once via a cached git_program()#253
ScriptedAlchemy merged 1 commit into
masterfrom
perf/cached-git-program

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

The daemon and CLI spawn git from ~13 sites, each a bare Command::new("git") that re-walks PATH per spawn (a git spawn is ~100–300ms on Windows). This resolves the binary once, process-wide.

Change

  • New src/git.rs: git_program() -> &'static OsStr, cached in a OnceLock. Resolution order: GIT env override → hand-rolled PATH lookup (Windows PATHEXT-aware) → literal "git" fallback (never worse than today). No new crate (which isn't a dep).
  • Routed the product CLI-fallback and one-shot spawn sites through it (branch.rs, worktree.rs, config.rs, graph/git.rs, mcp/tools/handlers/workflow.rs, tracedecay/lifecycle.rs).

Deliberately unchanged

The gix-first read paths (current_branch/local_branch_exists, git_worktree_root/git_common_dir) still use gix in-process and only fall back to git behind the git_may_resolve_repo preflight — only which program the fallback execs changed. No caching of git results (staleness risk).

Validation

fmt/clippy(-D warnings)/build clean; branch/worktree/git lib tests 51 (incl. 2 new git::tests covering stability + GIT override); core_cli 189, graph 176, agent_suite 427 green.

🤖 Generated with Claude Code

The daemon and CLI spawn `git` from several sites, each a bare
`Command::new("git")` that makes the OS re-walk PATH per spawn
(~100-300ms on Windows). Add `git::git_program()` which resolves the
git binary to an absolute path exactly once (OnceLock cache) and route
all product git-CLI spawn sites through it, so the long-running daemon
never re-walks PATH for git.

Resolution order: `GIT` env override -> which-style PATH lookup
(+ PATHEXT on Windows, hand-rolled, no new crate) -> literal "git"
fallback so behavior is never worse than today.

The gix-first read paths in branch.rs/worktree.rs are unchanged: they
still prefer in-process gix and only reach a git subprocess as a gated
fallback. Only that fallback and the one-shot spawn sites now exec the
cached path. Test-only spawn helpers are left untouched.

Converted sites: worktree.rs (git_command), branch.rs (x3),
config.rs (check-ignore), graph/git.rs (tokio churn), workflow.rs
(tokio diff), tracedecay/lifecycle.rs (git_output).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 8bc5791

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@ScriptedAlchemy
ScriptedAlchemy merged commit bc63387 into master Jul 3, 2026
29 of 30 checks passed
ScriptedAlchemy added a commit that referenced this pull request Jul 3, 2026
…255)

`broker_cancels_partial_refresh_without_poisoning_warm_client` asserts
that aborting a partial refresh does not poison the broker: a subsequent
refresh must spin up a clean client. On a loaded macOS CI runner the
recovery client's `python3` cold-start intermittently exceeds the 3s
initialize floor, surfacing a transient "initialize timed out" — a slow
start, not a poisoned broker — which failed the test on two consecutive
unrelated PRs (#253, #254).

Retry the recovery refresh a bounded number of times (5, 50ms apart),
tolerating only the transient initialize-timeout error and still failing
fast on any other error. The Ready/total_errors assertions are unchanged.

Co-authored-by: Claude <noreply@anthropic.com>
@ScriptedAlchemy
ScriptedAlchemy deleted the perf/cached-git-program branch July 4, 2026 01:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant