fix(windows): git path resolution for modified files across Git Bash, MSYS2, and Cygwin#16422
Conversation
There was a problem hiding this comment.
Pull request overview
Restores reliable Windows modified-file tracking by normalizing Windows shell-style directory paths (Git Bash/MSYS2/Cygwin/WSL mounts) and making git resolution robust to Windows environment variable casing, with added regression tests to prevent future regressions.
Changes:
- Add
Filesystem.resolve()to convert shell-style Windows paths into real, normalized repo paths and use it in Server/Instance/TUI path handling. - Update
util.which()to honorPath/PathExtcasing (and fall back to process env) on Windows. - Add focused Windows regression tests for path resolution, config lookup, and
which()behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/opencode/src/util/which.ts | Make PATH/PATHEXT resolution tolerant of Windows casing variants. |
| packages/opencode/src/util/filesystem.ts | Introduce Filesystem.resolve() and expand Windows path normalization. |
| packages/opencode/src/server/server.ts | Normalize inbound directory (query/header) before workspace/instance resolution. |
| packages/opencode/src/project/instance.ts | Key instances by normalized directory paths to avoid duplicate instances on Windows. |
| packages/opencode/src/cli/cmd/tui/thread.ts | Normalize PWD/project paths to ensure correct repo resolution under Windows shells. |
| packages/opencode/test/util/which.test.ts | Add regression test for Path/PathExt casing fallback on Windows. |
| packages/opencode/test/util/filesystem.test.ts | Add Windows-only coverage for resolving Git Bash/MSYS2/Cygwin/WSL-style paths. |
| packages/opencode/test/config/config.test.ts | Add Windows-only config lookup tests using shell-style paths. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| fn: async () => { | ||
| const cfg = await Config.get() | ||
| expect(cfg.snapshot).toBe(true) | ||
| expect(Instance.directory).toBe(tmp.path) |
There was a problem hiding this comment.
Instance.directory is now set via Filesystem.resolve(), which may return a realpath-canonicalized string on Windows (drive-letter / directory casing can differ from tmp.path). This strict equality check can become flaky; consider comparing against Filesystem.normalizePath(tmp.path) (or Filesystem.resolve(tmp.path)) instead.
| expect(Instance.directory).toBe(tmp.path) | |
| expect(Instance.directory).toBe(Filesystem.normalizePath(tmp.path)) |
… MSYS2, and Cygwin (anomalyco#16422)
… MSYS2, and Cygwin (anomalyco#16422)
… MSYS2, and Cygwin (anomalyco#16422)
… MSYS2, and Cygwin (anomalyco#16422)
Uh oh!
There was an error while loading. Please reload this page.