Skip to content

Commit cd144e1

Browse files
committed
feat(paths): add fromUnixPath to convert MSYS paths to native Windows format
1 parent 0475d45 commit cd144e1

File tree

2 files changed

+233
-99
lines changed

2 files changed

+233
-99
lines changed

src/paths/normalize.ts

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,62 @@ export function isRelative(pathLike: string | Buffer | URL): boolean {
358358
return !isAbsolute(filepath)
359359
}
360360

361+
/**
362+
* Convert Unix-style POSIX paths (MSYS/Git Bash format) back to native Windows paths.
363+
*
364+
* This is the inverse of {@link toUnixPath}. MSYS-style paths use `/c/` notation
365+
* for drive letters, which PowerShell and cmd.exe cannot resolve. This function
366+
* converts them back to native Windows format.
367+
*
368+
* Conversion rules:
369+
* - On Windows: Converts Unix drive notation to Windows drive letters
370+
* - `/c/path/to/file` becomes `C:/path/to/file`
371+
* - `/d/projects/app` becomes `D:/projects/app`
372+
* - Drive letters are always uppercase in the output
373+
* - On Unix: Returns the path unchanged (passes through normalization)
374+
*
375+
* This is particularly important for:
376+
* - GitHub Actions runners where `command -v` returns MSYS paths
377+
* - Tools like sfw that need to resolve real binary paths on Windows
378+
* - Scripts that receive paths from Git Bash but need to pass them to native Windows tools
379+
*
380+
* @param {string | Buffer | URL} pathLike - The MSYS/Unix-style path to convert
381+
* @returns {string} Native Windows path (e.g., `C:/path/to/file`) or normalized Unix path
382+
*
383+
* @example
384+
* ```typescript
385+
* // MSYS drive letter paths
386+
* fromUnixPath('/c/projects/app/file.txt') // 'C:/projects/app/file.txt'
387+
* fromUnixPath('/d/projects/foo/bar') // 'D:/projects/foo/bar'
388+
*
389+
* // Non-drive Unix paths (unchanged)
390+
* fromUnixPath('/tmp/build/output') // '/tmp/build/output'
391+
* fromUnixPath('/usr/local/bin') // '/usr/local/bin'
392+
*
393+
* // Already Windows paths (unchanged)
394+
* fromUnixPath('C:/Windows/System32') // 'C:/Windows/System32'
395+
*
396+
* // Edge cases
397+
* fromUnixPath('/c') // 'C:/'
398+
* fromUnixPath('') // '.'
399+
* ```
400+
*/
401+
/*@__NO_SIDE_EFFECTS__*/
402+
export function fromUnixPath(pathLike: string | Buffer | URL): string {
403+
const normalized = normalizePath(pathLike)
404+
405+
// On Windows, convert MSYS drive notation back to native: /c/path → C:/path
406+
if (WIN32) {
407+
return normalized.replace(
408+
/^\/([a-zA-Z])(\/|$)/,
409+
(_, letter, sep) => `${letter.toUpperCase()}:${sep || '/'}`,
410+
)
411+
}
412+
413+
// On Unix, just return the normalized path
414+
return normalized
415+
}
416+
361417
/**
362418
* Normalize a path by converting backslashes to forward slashes and collapsing segments.
363419
*
@@ -1114,21 +1170,23 @@ export function relativeResolve(from: string, to: string): string {
11141170
}
11151171

11161172
/**
1117-
* Convert Windows paths to Unix-style POSIX paths for Git Bash tools.
1173+
* Convert Windows paths to MSYS/Unix-style POSIX paths for Git Bash tools.
11181174
*
1119-
* Git for Windows tools (like tar, git, etc.) expect POSIX-style paths with
1120-
* forward slashes and Unix drive letter notation (/c/ instead of C:\).
1175+
* Git for Windows and MSYS2 tools (like tar, git, etc.) expect POSIX-style
1176+
* paths with forward slashes and Unix drive letter notation (/c/ instead of C:\).
11211177
* This function handles the conversion for cross-platform compatibility.
11221178
*
1179+
* This is the inverse of {@link fromUnixPath}.
1180+
*
11231181
* Conversion rules:
11241182
* - On Windows: Normalizes separators and converts drive letters
11251183
* - `C:\path\to\file` becomes `/c/path/to/file`
1126-
* - `D:/Users/name` becomes `/d/Users/name`
1184+
* - `D:/projects/app` becomes `/d/projects/app`
11271185
* - Drive letters are always lowercase in the output
11281186
* - On Unix: Returns the path unchanged (passes through normalization)
11291187
*
11301188
* This is particularly important for:
1131-
* - Git Bash tools that interpret `D:\` as a remote hostname
1189+
* - MSYS2/Git Bash tools that interpret `D:\` as a remote hostname
11321190
* - Cross-platform build scripts using tar, git archive, etc.
11331191
* - CI/CD environments where Git for Windows is used
11341192
*

0 commit comments

Comments
 (0)