Skip to content

fix(worktree): resolve Git executable outside PATH#1776

Open
Priyanchew wants to merge 3 commits into
mainfrom
fix/worktree-git-executable-path
Open

fix(worktree): resolve Git executable outside PATH#1776
Priyanchew wants to merge 3 commits into
mainfrom
fix/worktree-git-executable-path

Conversation

@Priyanchew
Copy link
Copy Markdown
Collaborator

@Priyanchew Priyanchew commented May 10, 2026

Summary

  • Resolve Git via the shared platform layer before worktree operations.
  • Fall back to common Git install locations on Windows, macOS, and Linux when PATH is degraded.
  • Surface a clearer worktree setup error when Git is truly unavailable.

closes #1777

Test plan

  • pnpm --filter @aoagents/ao-core test -- src/__tests__/platform.test.ts
  • pnpm --filter @aoagents/ao-core typecheck && pnpm --filter @aoagents/ao-core build && pnpm --filter @aoagents/ao-plugin-workspace-worktree typecheck && pnpm --filter @aoagents/ao-plugin-workspace-worktree build
  • Reduced-PATH repro: getGitExecutable() resolves C:\Program Files\Git\cmd\git.exe and workspaceExists=true

Resolve Git through the platform layer so Windows worktree setup still works when AO is launched with a degraded PATH.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 10, 2026

Test Coverage Report

Metric Value
Lines covered 75/76
Lines not covered 1/76
Overall coverage 98.7%

Uncovered lines

  • packages/core/src/platform.ts: L130

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 10, 2026

Greptile Summary

This PR fixes worktree operations failing with a raw ENOENT in GUI-launched environments (e.g. Windows apps that launch Node without full PATH inheritance) by resolving the Git executable through a proper platform-aware lookup before spawning any git process.

  • getGitExecutable() added to platform.ts: walks PATH first using the now-cross-platform findOnPath, then probes a ranked list of well-known install locations per OS (Windows Program Files variants, macOS /usr/bin/Homebrew//usr/local, Linux /usr/bin//usr/local), and caches the result to avoid repeated filesystem probes. Falls back to bare \"git\" only when all candidates miss.
  • git() helper in the worktree plugin now catches ENOENT and re-throws with a human-readable message naming the executable that was tried, replacing the raw system error that previously surfaced.
  • Tests cover all four branches (PATH hit, Windows fallback, macOS Homebrew fallback, bare-git fallback) using per-test existsSync mocks via vi.doMock + vi.resetModules() + dynamic import() to avoid cross-test cache bleed.

Confidence Score: 5/5

Safe to merge — the change is additive, well-tested across all platform branches, and correctly follows the established caching and cross-platform patterns already in platform.ts.

All changed code paths are covered by explicit tests (PATH hit, Windows/macOS/Linux fallback candidates, bare-git fallback). The findOnPath generalisation preserves existing Windows shell-resolution behaviour because pathDelimiterForCurrentPlatform() still returns ';' on Windows. Caching mirrors the getShell() pattern exactly, and the ENOENT enrichment in git() is a strict improvement with no regression risk.

No files require special attention.

Important Files Changed

Filename Overview
packages/core/src/platform.ts Adds cross-platform getGitExecutable() with PATH-walk, platform-specific fallback candidates, and caching; findOnPath is properly generalised from Windows-only to cross-platform using platform-aware delimiters and separators.
packages/core/src/index.ts Exports getGitExecutable from the core package; _resetGitExecutableCache is correctly kept internal (not re-exported).
packages/plugins/workspace-worktree/src/index.ts Replaces bare "git" with getGitExecutable() in both git() and exists(); git() now wraps ENOENT with a user-readable message. exists() still silently returns false on all errors, which is the correct semantic for an existence check.
packages/core/src/tests/platform.test.ts Adds synchronous PATH-walk test and three async branch tests (Windows fallback, macOS Homebrew, Linux bare-git) using vi.doMock + vi.resetModules() + dynamic import() for per-test existsSync isolation; cache reset is properly handled via _resetGitExecutableCache() in beforeEach/afterEach.
packages/plugins/workspace-worktree/src/tests/index.test.ts Adds getGitExecutable to the @aoagents/ao-core mock so existing worktree tests continue to compile and pass after the new import.

Reviews (3): Last reviewed commit: "fix(worktree): satisfy platform test lin..." | Re-trigger Greptile

Comment thread packages/core/src/__tests__/platform.test.ts
Comment thread packages/core/src/platform.ts
Cache Git executable resolution and cover fallback branches so worktree setup avoids repeated filesystem probes while preserving cross-platform behavior.
Avoid import() type annotations in mocked platform tests while keeping fallback branch coverage intact.
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.

Windows worktree setup can fail with spawn git ENOENT

1 participant