Skip to content

fix(source-control): send Git forward-slash paths from a \wsl.localhost repo - #28862

Open
OrcaWin wants to merge 1 commit into
mainfrom
OrcaWin/sta-10494-wsl-pathspec
Open

OrcaWin wants to merge 1 commit into
mainfrom
OrcaWin/sta-10494-wsl-pathspec

Conversation

@OrcaWin

@OrcaWin OrcaWin commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator
Files Added Deleted Net
Test 4 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​70 $\color{#cf222e}{\Huge{\mathbf{−}}}$​29 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​41
Prod 4 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​17 $\color{#cf222e}{\Huge{\mathbf{−}}}$​20 $\color{#cf222e}{\Huge{\mathbf{−}}}$​3

ELI5

Git always writes folder paths with forward slashes (.claude/settings.json). Windows writes them with backslashes (.claude\settings.json). Orca checked file paths using Windows rules and handed the backslash version to Git. Git for Windows doesn't mind, but Git inside WSL treats a backslash as part of the file name, so it went looking for a file literally called .claude\settings.json. Now Orca always hands Git forward slashes.

What Changed

Before, in a repo opened from a \wsl.localhost\<distro>\... path whose project runtime is Windows (the default for a newly added project):

  • Staging or unstaging a file in a subfolder failed with fatal: pathspec ':(literal).claude\settings.json' did not match any files. Bulk stage failed the same way.
  • Discarding a subfolder file reported success and changed nothing.
  • Files at the repo root worked, and so did any repo whose project runtime was set to WSL.

After: all of these work, whatever the project's runtime setting says.

Mechanism. Two separate decisions disagreed:

  • Where Git runs comes from the path: any \wsl.localhost cwd runs Linux Git (resolveCommand).
  • The \ → / rewrite in literalPathspec keyed off options.wslDistro, which is set only when the project's runtime setting resolves to WSL.

This PR removes the second decision instead of syncing it with the first:

  • validateGitRelativeFilePath, the IPC boundary every Source Control call goes through, now returns the path as Git spells it: /-separated on every host. On Windows a \ can only be a separator, so the rewrite is always correct. On POSIX, sep is already /, so a literal \ in a filename is untouched.
  • literalPathspec no longer rewrites anything and drops its options parameter. A \ reaching it is a POSIX filename character. The runtime RPC boundary (normalizeRuntimeRelativePath) already sends / paths.

Side fixes from the same root cause:

  • git:checkIgnored in WSL repos sent backslash paths on stdin, so nested ignored files were never dimmed.
  • Drive-checkout suspect matching compares against Git's / paths, so it never matched subfolder files.

Why

Alternatives considered:

  • Rewrite only when Git will run in WSL, by deriving the distro from the cwd (fix: normalize pathspecs for WSL UNC worktrees #28478, credited as co-author). That works, but it threads worktreePath through every pathspec call and still ties correctness to routing. It also misses checkIgnored, which doesn't build pathspecs.
  • Make the project runtime setting follow the path. That's the larger "where does this run" question. It is being retired by WSL-via-orcad: WSL distros as hosts, and the WSL project mover, where Git runs in Linux with Linux paths. Not worth reworking here.

Normalizing once, at the boundary where the Windows spelling enters, is the smallest change that's correct for every route. Windows Git accepts / in :(literal) pathspecs; I checked with Git 2.55 for Windows.

Linked Issue

Fixes #28422
Fixes #22251

Supersedes #28478. Thanks @1aifanatic for the diagnosis and the wsl.localhost / wsl$ test cases; credited as co-author.

Visual Proof

Isolated dev Orca, CDP screenshots of a hidden window. Scratch repo inside WSL (Ubuntu-24.04), opened via its \wsl.localhost path, project runtime left at the default.

Before: clicking + on .claude/settings.json:

03-stage-failed.png

After: same click, the file is staged:

10-fixed-stage.png

Testing

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

Manual, on Windows 11 + WSL2 Ubuntu-24.04, in an isolated dev profile (ORCA_BACKGROUND_LAUNCH=1, CDP only):

  • Before the fix:
    • Single and bulk stage of subfolder files failed with the issue's exact error.
    • Discard was a silent no-op.
    • Setting the project runtime to WSL made staging work.
  • After the fix, WSL repo with the default runtime:
    • stage, unstage, bulk stage and bulk unstage all work;
    • discard of a tracked subfolder file works;
    • discard of an untracked file in a new folder works;
    • a nested ignored path is reported.
    • git status inside WSL confirms each result.
  • Native Windows repo on C:\: stage, unstage and discard of a subfolder file all work with / paths.
  • UI: clicking Stage in Source Control stages .claude/settings.json, with no error toast.

Automated:

  • filesystem-auth.test.ts: Windows path semantics through a path.win32 mock, covering \wsl.localhost, \wsl$ and C:\. A POSIX test checks that a backslash stays a filename character.
  • status-wsl-pathspecs.test.ts was rewritten for the new contract: the Git layer passes paths through, with or without wslDistro.
  • The handler tests now expect / paths instead of path.join.
  • tc:node and check:code-quality:changed pass.
  • On this Windows machine, the related suites have 21 failures that also fail identically on untouched origin/main (CRLF line endings, symlink permissions). No new failures.

Review

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

…st repo

A repo opened from \wsl.localhost always runs Linux Git, but Orca rewrote
`sub\file` to `sub/file` only when the project's runtime setting said WSL.
With the default (Windows) setting, staging a file in a subfolder failed and
discarding one reported success while changing nothing.

validateGitRelativeFilePath now returns the path as Git spells it ("/" on every
host). On Windows "\" can only be a separator, and Windows Git accepts "/", so
this holds whatever the project setting or routing. literalPathspec drops its
setting-dependent rewrite: a "\" reaching it is a POSIX filename character.

Also fixes nested ignored-path checks and drive-checkout suspect matching in
WSL repos, which received backslash paths the same way.

Fixes #28422
Fixes #22251

Co-authored-by: Naveen Chatlapalli <naveen.aifanatic@gmail.com>
@coderabbitai

coderabbitai Bot commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 74705dab-211e-4491-b4f9-bc9674d30461
📥 Commits

Reviewing files that changed from the base of the PR and between f8cbfef and 4fd5601.

📒 Files selected for processing: 8
  • src/main/git/source-control/discard-changes.ts
  • src/main/git/source-control/git-pathspec.ts
  • src/main/git/source-control/staging.ts
  • src/main/git/status-wsl-pathspecs.test.ts
  • src/main/ipc/filesystem-auth.test.ts
  • src/main/ipc/filesystem-branch-compare-diff.test.ts
  • src/main/ipc/filesystem-git-status-staging.test.ts
  • src/main/ipc/filesystem-path-containment.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

Validated Git-relative paths now use forward slashes on all hosts. literalPathspec no longer accepts runtime options or rewrites backslashes. Staging and discard operations call it without runtime options. Tests cover Git-style paths, WSL pathspecs, and backslashes that remain literal filename characters.

Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 4fd56

The reviewed path handling has no established merge-blocking issue. Normal checks can proceed.

Pre-merge checks: Passed 5
Passed Passed checks: 5 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: sending Git-compatible forward-slash paths from repositories opened through \wsl.localhost.
Description check Passed The description is complete and relevant. It covers the user impact, implementation, alternatives, linked issues, visual proof, manual and automated testing, cross-platform considerations, and known b…
Linked Issues check Passed The changes satisfy #28422 and #22251. validateGitRelativeFilePath now returns /-separated Git paths on Windows. stageFile, unstageFile, and bulk staging functions pass these paths through `li…
Out of Scope Changes check Passed The changes stay within the linked issue scope. Updates to discard, unstage, ignored-path handling, branch-diff path expectations, and pathspec tests apply the same Git path normalization contract to …
Docstring Coverage Passed Docstring coverage is 81.82% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 8 files.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant