Skip to content

fix(git): prefer PATH git before fallback#2665

Open
janburzinski wants to merge 8 commits into
mainfrom
jan/eng-1658-honor-path-git-before-usrbingit-on-macos
Open

fix(git): prefer PATH git before fallback#2665
janburzinski wants to merge 8 commits into
mainfrom
jan/eng-1658-honor-path-git-before-usrbingit-on-macos

Conversation

@janburzinski

Copy link
Copy Markdown
Collaborator

Description

  • prefer the first executable git found on PATH before falling back on hardcoded git locations
  • keep explicit GIT_PATH as highest-priority override

Screenshot/Recording (if applicable)

(context: i updated my git path before this haha)
https://streamable.com/m4ee7h

Checklist
  • I kept this PR small and focused
  • I ran a self-review before opening this PR
  • I ran the relevant local checks or explained why not
  • I updated docs when behavior or setup changed
  • I added or updated tests when behavior changed, or explained why not
  • I only added comments where the logic is not obvious
  • I used Conventional Commits for commit
    messages and, when possible, the PR title

@greptile-apps

greptile-apps Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR upgrades the git binary resolution strategy so the first executable git found on PATH is preferred over hardcoded fallback paths, while GIT_PATH remains the top-priority override. A new host-dependency probe for git is wired into the runtime lifecycle, replacing the static GIT_EXECUTABLE constant with a dynamic getGitExecutable() that can be updated after the probe completes.

  • exec.ts gains findExecutableOnPath (with Windows PATHEXT support), getGitExecutable/setGitExecutableOverride for per-connection dynamic resolution, and exports resolveGitBin for testing.
  • HostDependencyManager.probe() now awaits buildAndStoreHostDependency for core-category deps (synchronous path), ensuring onStatusUpdated fires before the probe returns so the git override is set before any GitRuntime is constructed.
  • SSH execution contexts now carry a connectionId, allowing getGitExecutable(connectionId) to select the correct remote git binary per connection.

Confidence Score: 5/5

Safe to merge — the git binary is resolved at startup as before and the new dynamic override only takes effect after an explicit probe, so there is no regression window.

The probe-then-override ordering is correct: buildAndStoreHostDependency is now awaited for core deps, ensuring setGitExecutableOverride is called before any GitRuntime is constructed. All existing callers that used the static GIT_EXECUTABLE now call getGitExecutable(), which falls back to the same startup-resolved value until the probe fires. The Windows PATHEXT path, per-connection remote overrides, and the invalid-GIT_PATH fallthrough are all covered by new tests.

No files require special attention; the one style note on DynamicGitExec.file in runtime-manager.ts is non-blocking.

Important Files Changed

Filename Overview
apps/emdash-desktop/src/main/core/utils/exec.ts Core of the change: adds PATH-based git discovery with Windows PATHEXT support, dynamic per-connection overrides, and a GIT_EXECUTABLE startup fallback.
apps/emdash-desktop/src/main/core/runtime/runtime-manager.ts Introduces DynamicGitExec (BoundExec wrapping dynamic git resolution) and probeGitDependency called before runtime creation; DynamicGitExec.file is hardcoded as 'git' while the actual binary is resolved dynamically.
apps/emdash-desktop/src/main/core/dependencies/dependency-managers.ts Adds syncGitExecutable subscriber on onStatusUpdated to propagate the probed git path into getGitExecutable; clears remote overrides on clearDependencyManager.
packages/core/src/host-dependencies/runtime/host-dependency-manager.ts Extends probe() to await buildAndStoreHostDependency for core-category deps (synchronous event emission) and adds probePinnedSource for pinned installs not on PATH.
apps/emdash-desktop/src/main/core/execution-context/ssh-execution-context.ts Threads connectionId through SshExecutionContext and uses getGitExecutable(connectionId) to select the correct remote git binary per connection.
packages/core/src/host-dependencies/core-dependencies.ts New file: defines GIT_DEPENDENCY_DESCRIPTOR and CORE_DEPENDENCIES array for git as a core (non-agent) dependency.
apps/emdash-desktop/src/main/core/utils/exec.test.ts New test file covering GIT_PATH priority, PATH preference, invalid GIT_PATH fallthrough, Windows PATHEXT, local override, and per-connection remote overrides.
apps/emdash-desktop/src/main/core/runtime/legacy/ssh-git.ts Threads connectionId into LegacySshGitRuntime so all internally created SshExecutionContexts carry the correct connection identity for git resolution.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant App as App startup
    participant RM as RuntimeManager.acquire()
    participant PGD as probeGitDependency()
    participant DM as HostDependencyManager
    participant SE as syncGitExecutable()
    participant GE as getGitExecutable()

    App->>RM: acquire(machine)
    RM->>PGD: await probeGitDependency(machine)
    PGD->>DM: getDependencyManager(connectionId)
    DM-->>PGD: manager
    PGD->>DM: await manager.probe('git')
    DM->>DM: findExecutableOnPath('git') + version probe
    DM->>DM: buildAndStoreHostDependency (awaited for core deps)
    DM->>SE: onStatusUpdated.emit(event)
    SE->>SE: resolveActiveInstallation()
    SE->>GE: setGitExecutableOverride(path, connectionId)
    DM-->>PGD: DependencyState
    PGD-->>RM: (done)
    RM->>RM: new LocalMachineRuntime() / SshMachineRuntime()
    Note over RM,GE: GitRuntime now calls getGitExecutable() which returns the probed PATH git
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant App as App startup
    participant RM as RuntimeManager.acquire()
    participant PGD as probeGitDependency()
    participant DM as HostDependencyManager
    participant SE as syncGitExecutable()
    participant GE as getGitExecutable()

    App->>RM: acquire(machine)
    RM->>PGD: await probeGitDependency(machine)
    PGD->>DM: getDependencyManager(connectionId)
    DM-->>PGD: manager
    PGD->>DM: await manager.probe('git')
    DM->>DM: findExecutableOnPath('git') + version probe
    DM->>DM: buildAndStoreHostDependency (awaited for core deps)
    DM->>SE: onStatusUpdated.emit(event)
    SE->>SE: resolveActiveInstallation()
    SE->>GE: setGitExecutableOverride(path, connectionId)
    DM-->>PGD: DependencyState
    PGD-->>RM: (done)
    RM->>RM: new LocalMachineRuntime() / SshMachineRuntime()
    Note over RM,GE: GitRuntime now calls getGitExecutable() which returns the probed PATH git
Loading

Reviews (4): Last reviewed commit: "fix(deps): clear ssh git override" | Re-trigger Greptile

Comment thread apps/emdash-desktop/src/main/core/utils/exec.ts Outdated
Comment thread apps/emdash-desktop/src/main/core/utils/exec.test.ts
@janburzinski

Copy link
Copy Markdown
Collaborator Author

@greptileai

@Davidknp Davidknp marked this pull request as draft June 24, 2026 21:44
@Davidknp Davidknp self-assigned this Jun 24, 2026
@janburzinski

Copy link
Copy Markdown
Collaborator Author

@greptileai

@janburzinski janburzinski marked this pull request as ready for review June 25, 2026 12:55
@janburzinski

Copy link
Copy Markdown
Collaborator Author

@Davidknp would love for your feedback :)

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.

2 participants