-
Notifications
You must be signed in to change notification settings - Fork 177
fix: translate WSL mount paths to Windows drive-letter paths #127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -69,7 +69,10 @@ | |||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // Ensure leading slash for POSIX-style absolute paths | ||||||||||||||||||||||||||||||||||||||||||||||
| return decodedPath.startsWith('/') ? decodedPath : `/${decodedPath}`; | ||||||||||||||||||||||||||||||||||||||||||||||
| const absolutePath = decodedPath.startsWith('/') ? decodedPath : `/${decodedPath}`; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
| // On non-Windows platforms, return the POSIX-style absolute path unchanged | |
| if (os.platform() !== 'win32') { | |
| return absolutePath; | |
| } |
Copilot
AI
Mar 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
translateWslMountPath() returns "D:" for an input like "/mnt/d" (no trailing slash). On Windows, "D:" is not an absolute path (path.isAbsolute('D:') is false), which can break downstream path resolution and cause fallbacks back to POSIX paths. Consider defaulting the "rest" portion to "/" when the mount path has no trailing segment so the result is "D:/".
| const rest = match[2] ?? ''; | |
| const rest = match[2] ?? '/'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When translating a WSL path that points to the root of a drive (e.g., /mnt/c), match[2] is undefined, and rest becomes ''. This results in returning C:, which is not a valid absolute path and can cause issues with path joining later. The path should be C:/. You can handle this more concisely.
| const rest = match[2] ?? ''; | |
| return `${drive}:${rest}`; | |
| return `${drive}:${match[2] || '/'}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
In Node.js on Windows, what does path.win32.isAbsolute('C:') return, and what is the correct absolute drive-root format?
💡 Result:
In Node.js on Windows, path.win32.isAbsolute('C:') returns false. The correct absolute drive-root format is 'C:\' or 'C:/' (drive letter followed by colon and path separator).
Citations:
- 1: nodejs/node@1c4007927d
- 2: https://github.com/nodejs/node/blob/main/lib/path.js
- 3: https://nodejs.org/api/path.html
🏁 Script executed:
# Find the pathDecoder.ts file and examine the function
find . -name "pathDecoder.ts" -type f | head -5Repository: matt1398/claude-devtools
Length of output: 99
🏁 Script executed:
# Get the full context of the function and surrounding code
cat -n src/main/utils/pathDecoder.ts | sed -n '95,115p'Repository: matt1398/claude-devtools
Length of output: 796
🏁 Script executed:
# Search for usage of translateWslMountPath in the codebase
rg "translateWslMountPath" -n -A 3 -B 1Repository: matt1398/claude-devtools
Length of output: 1353
🏁 Script executed:
# Look for tests related to this function
find . -name "*.test.ts" -o -name "*.spec.ts" | xargs grep -l "translateWslMountPath" 2>/dev/nullRepository: matt1398/claude-devtools
Length of output: 52
🏁 Script executed:
# Check path.isAbsolute usage in the codebase to understand downstream expectations
rg "isAbsolute|path\..*Absolute" --type ts --type tsx -n | grep -E "(src/main|src/renderer)" | head -20Repository: matt1398/claude-devtools
Length of output: 95
🏁 Script executed:
# Search for normalizeDriveLetter function definition
rg "normalizeDriveLetter" -n -B 2 -A 5 --type tsRepository: matt1398/claude-devtools
Length of output: 1182
🏁 Script executed:
# Search for tests more carefully with proper syntax
fd "\.(test|spec)\.ts$" -x grep -l "translateWslMountPath\|pathDecoder"Repository: matt1398/claude-devtools
Length of output: 146
🏁 Script executed:
# Look at the full context in metadataExtraction.ts to understand how the result is used
cat -n src/main/utils/metadataExtraction.ts | sed -n '60,70p'Repository: matt1398/claude-devtools
Length of output: 483
🏁 Script executed:
# Check if pathDecoder has any imports or exports related to normalization
cat -n src/main/utils/pathDecoder.ts | head -50Repository: matt1398/claude-devtools
Length of output: 2112
🏁 Script executed:
# Examine the pathDecoder test file to see existing test coverage
cat -n test/main/utils/pathDecoder.test.tsRepository: matt1398/claude-devtools
Length of output: 9427
🏁 Script executed:
# Check if normalizeDriveLetter handles the slash issue
rg "normalizeDriveLetter" -A 10 -B 5 src/main/utils/metadataExtraction.ts | head -30Repository: matt1398/claude-devtools
Length of output: 913
Normalize mount-root paths to X:/ format.
For input like /mnt/c, this currently returns C:, which is not an absolute path on Windows (path.win32.isAbsolute('C:') returns false). The function's contract explicitly documents the output format as X:/..., and downstream consumers assume absolute paths. Change line 108 from const rest = match[2] ?? ''; to const rest = match[2] ?? '/'; to produce C:/ instead.
Proposed fix
export function translateWslMountPath(posixPath: string): string {
if (process.platform !== 'win32') {
return posixPath;
}
const match = /^\/mnt\/([a-zA-Z])(\/.*)?$/.exec(posixPath);
if (match) {
const drive = match[1].toUpperCase();
- const rest = match[2] ?? '';
+ const rest = match[2] ?? '/';
return `${drive}:${rest}`;
}
return posixPath;
}Also add test coverage for the /mnt/c case to prevent regression.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function translateWslMountPath(posixPath: string): string { | |
| if (process.platform !== 'win32') { | |
| return posixPath; | |
| } | |
| const match = /^\/mnt\/([a-zA-Z])(\/.*)?$/.exec(posixPath); | |
| if (match) { | |
| const drive = match[1].toUpperCase(); | |
| const rest = match[2] ?? ''; | |
| return `${drive}:${rest}`; | |
| } | |
| export function translateWslMountPath(posixPath: string): string { | |
| if (process.platform !== 'win32') { | |
| return posixPath; | |
| } | |
| const match = /^\/mnt\/([a-zA-Z])(\/.*)?$/.exec(posixPath); | |
| if (match) { | |
| const drive = match[1].toUpperCase(); | |
| const rest = match[2] ?? '/'; | |
| return `${drive}:${rest}`; | |
| } | |
| return posixPath; | |
| } |
🧰 Tools
🪛 GitHub Check: validate
[warning] 105-105:
Unsafe Regular Expression
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/utils/pathDecoder.ts` around lines 101 - 110, The
translateWslMountPath function returns "C:" for input "/mnt/c", which is not an
absolute Windows path; update the logic in translateWslMountPath to default the
captured tail to '/' instead of '' (change the rest assignment from match[2] ??
'' to match[2] ?? '/') so the function returns "C:/" for mount-root inputs, and
add a unit test for the "/mnt/c" case to assert the output is "C:/" (or
otherwise absolute per path.win32.isAbsolute) to prevent regression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On Windows hosts this now rewrites every
cwdread from a session file, including files coming fromSshFileSystemProvider.ProjectPathResolver.resolveProjectPath()still callsextractCwd()forfsProvider.type === 'ssh', so a remote Linux project rooted at/mnt/d/repowill now be surfaced asD:/repoinProjectScannerand session exports even though the session is remote. That loses the real remote path and can point path-based UI/actions at an unrelated local drive when someone SSHes into a WSL/Unix machine that uses/mnt/<drive>mounts.Useful? React with 👍 / 👎.