Skip to content

Shell.resolve: a backslash roots a path on Windows - #24

Merged
odrobnik merged 4 commits into
mainfrom
fix/windows-rooted-paths
Oct 18, 2026
Merged

odrobnik merged 4 commits into
mainfrom
fix/windows-rooted-paths

Conversation

@odrobnik

@odrobnik odrobnik commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

On Windows, Shell.resolve(_:) recognized only / and drive letters (C:\x) as absolute. A path rooted by a backslash, either \dir (the current drive's root) or a \\server\share UNC path, was joined to the working directory as if it were relative.

This came up in SwiftPorts (Cocoanetics/SwiftPorts#125, Codex review): git push \\server\share\repo.git resolved its repository under the work tree.

Change

A backslash-rooted path is now handled like a drive-letter path. It is absolute and lives outside the unix-style virtual namespace, so it resolves to the unmapped sentinel under a path mapping, where Sandbox.authorize rejects it. Without a mapping:

  • a UNC path (\\server\share\x) comes back as given (normalizePath already kept UNC roots, Preserve UNC roots when normalizing Windows paths #23);
  • \x, the current drive's root, takes the drive of the shell's working directory, which can differ from the process's: a shell on Q:\work resolves \repo.git to Q:\repo.git. With no drive in the working directory, the path comes back as given.

/x is unchanged: it is the unix-style namespace and still comes back as given. On other platforms a backslash stays an ordinary character.

Tests

  • resolveBackslashRootedPathsAsAbsolute (Windows): UNC and drive-letter paths keep their root; \repo.git and \ take the drive of a Q:\work working directory; without a drive they come back as given; a UNC path is voided under a mapping.
  • resolveTakesABackslashAsAnOrdinaryCharacter (other platforms): \file.txt is still relative.

swift test passes on macOS (66 tests) and swiftlint lint is clean. The Windows test runs in CI.

🤖 Generated with Claude Code

`\dir` (the current drive's root) and `\\server\share` UNC paths were
joined to the working directory as if relative, so `git push
\\server\share\repo.git` (SwiftPorts) looked under the work tree. Like a
drive-letter path, a backslash-rooted one is now absolute, outside the
unix-style virtual namespace: as given without a mapping, voided under
one. On other platforms a backslash stays an ordinary character.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-18T11:44:55.626805Z 8217334 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@odrobnik

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b0097e752f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/ShellKit/Shell+Path.swift Outdated
odrobnik and others added 2 commits October 18, 2026 13:33
Codex review on #24: on Windows, `\repo.git` (and `/repo.git`) is the
root of the current drive, and a shell working on `D:\work` means
`D:\repo.git`, whatever drive the process is on. Without a mapping, a
path rooted at the current drive's root now takes the drive of the
shell's working directory; UNC paths and drive-letter paths keep their
own root, and a working directory without a drive leaves the path to
the process as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The previous commit also gave `/x` the shell's drive. `Environment()`
defaults the working directory to the process's, so on Windows every
`/x` would have come back spelled `D:/x`, against resolve's contract that
an absolute path without a mapping comes back as given (and
resolveAbsolutePathPassesThrough). `/x` is the unix-style namespace and
passes through unchanged again; only the backslash-rooted spelling,
which this PR adds, is taken onto the shell's drive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@odrobnik

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 3e9e3506e6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

`Environment()` starts in the process's directory, which on the Windows
runner is `D:\a\...`, so the "no drive to take" check took D:.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@odrobnik

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 821733468d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@odrobnik
odrobnik merged commit 15884fa into main Oct 18, 2026
6 checks passed
@odrobnik
odrobnik deleted the fix/windows-rooted-paths branch October 18, 2026 11:46
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