Skip to content

Commit 068bef9

Browse files
committed
clean up
1 parent e7cfc08 commit 068bef9

File tree

4 files changed

+77
-88
lines changed

4 files changed

+77
-88
lines changed

src/file_system.rs

Lines changed: 9 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -155,52 +155,17 @@ impl FileSystemOs {
155155
/// See [std::fs::read_link]
156156
#[inline]
157157
pub fn read_link(path: &Path) -> io::Result<PathBuf> {
158-
let target = fs::read_link(path)?;
159-
cfg_if! {
160-
if #[cfg(windows)] {
161-
Ok(match Self::try_strip_windows_prefix(&target) {
162-
Some(path) => path,
163-
// We won't follow the link if we cannot represent its target properly.
164-
None => target,
165-
})
166-
} else {
167-
Ok(target.to_path_buf())
168-
}
169-
}
170-
}
171-
172-
/// When applicable, converts a [DOS device path](https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#dos-device-paths)
173-
/// to a normal path (usually, "Traditional DOS paths" or "UNC path") that can be consumed by the `import`/`require` syntax of Node.js.
174-
/// Returns `None` if the path cannot be represented as a normal path.
175-
pub fn try_strip_windows_prefix<P: AsRef<Path>>(path: P) -> Option<PathBuf> {
176-
// See https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
177-
let path_bytes = path.as_ref().as_os_str().as_encoded_bytes();
178-
179-
let path = if let Some(p) =
180-
path_bytes.strip_prefix(br"\\?\UNC\").or(path_bytes.strip_prefix(br"\\.\UNC\"))
181-
{
182-
// UNC paths
183-
unsafe {
184-
PathBuf::from(std::ffi::OsStr::from_encoded_bytes_unchecked(&[br"\\", p].concat()))
158+
let path = fs::read_link(path)?;
159+
if cfg!(target_os = "windows") {
160+
match crate::windows::try_strip_windows_prefix(path) {
161+
Ok(p) => Ok(p),
162+
// We won't follow the link if we cannot represent its target properly.
163+
Err(crate::ResolveError::PathNotSupported(p)) => Ok(p),
164+
_ => unreachable!(),
185165
}
186-
} else if let Some(p) =
187-
path_bytes.strip_prefix(br"\\?\").or(path_bytes.strip_prefix(br"\\.\"))
188-
{
189-
// Assuming traditional DOS path "\\?\C:\"
190-
if p[1] != b':' {
191-
// E.g.,
192-
// \\?\Volume{b75e2c83-0000-0000-0000-602f00000000}
193-
// \\?\BootPartition\
194-
// It seems nodejs does not support DOS device paths with Volume GUIDs.
195-
// This can happen if the path points to a Mounted Volume without a drive letter.
196-
return None;
197-
}
198-
unsafe { PathBuf::from(std::ffi::OsStr::from_encoded_bytes_unchecked(p)) }
199166
} else {
200-
path.as_ref().to_path_buf()
201-
};
202-
203-
Some(path)
167+
Ok(path)
168+
}
204169
}
205170
}
206171

@@ -267,37 +232,3 @@ fn metadata() {
267232
);
268233
let _ = meta;
269234
}
270-
271-
#[test]
272-
fn test_strip_windows_prefix() {
273-
assert_eq!(
274-
FileSystemOs::try_strip_windows_prefix(PathBuf::from(
275-
r"\\?\C:\Users\user\Documents\file.txt"
276-
)),
277-
Some(PathBuf::from(r"C:\Users\user\Documents\file.txt"))
278-
);
279-
280-
assert_eq!(
281-
FileSystemOs::try_strip_windows_prefix(PathBuf::from(
282-
r"\\.\C:\Users\user\Documents\file.txt"
283-
)),
284-
Some(PathBuf::from(r"C:\Users\user\Documents\file.txt"))
285-
);
286-
287-
assert_eq!(
288-
FileSystemOs::try_strip_windows_prefix(PathBuf::from(r"\\?\UNC\server\share\file.txt")),
289-
Some(PathBuf::from(r"\\server\share\file.txt"))
290-
);
291-
292-
assert_eq!(
293-
FileSystemOs::try_strip_windows_prefix(PathBuf::from(
294-
r"\\?\Volume{c8ec34d8-3ba6-45c3-9b9d-3e4148e12d00}\file.txt"
295-
)),
296-
None
297-
);
298-
299-
assert_eq!(
300-
FileSystemOs::try_strip_windows_prefix(PathBuf::from(r"\\?\BootPartition\file.txt")),
301-
None
302-
);
303-
}

src/fs_cache.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,11 @@ impl<Fs: FileSystem> Cache for FsCache<Fs> {
7777

7878
fn canonicalize(&self, path: &Self::Cp) -> Result<PathBuf, ResolveError> {
7979
let cached_path = self.canonicalize_impl(path)?;
80-
let path = cached_path.to_path_buf();
81-
cfg_if! {
82-
if #[cfg(windows)] {
83-
match crate::FileSystemOs::try_strip_windows_prefix(&path) {
84-
Some(path) => Ok(path),
85-
None => Err(ResolveError::PathNotSupported(path)),
86-
}
87-
} else {
88-
Ok(path)
89-
}
80+
let mut path = cached_path.to_path_buf();
81+
if cfg!(target_os = "windows") {
82+
path = crate::windows::try_strip_windows_prefix(path)?;
9083
}
84+
Ok(path)
9185
}
9286

9387
fn is_file(&self, path: &Self::Cp, ctx: &mut Ctx) -> bool {

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ mod specifier;
6565
mod tsconfig;
6666
#[cfg(feature = "fs_cache")]
6767
mod tsconfig_serde;
68+
mod windows;
6869

6970
#[cfg(test)]
7071
mod tests;

src/windows.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use std::path::PathBuf;
2+
3+
use crate::ResolveError;
4+
5+
/// When applicable, converts a [DOS device path](https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#dos-device-paths)
6+
/// to a normal path (usually, "Traditional DOS paths" or "UNC path") that can be consumed by the `import`/`require` syntax of Node.js.
7+
/// Returns `None` if the path cannot be represented as a normal path.
8+
// #[cfg(target_os = "windows")]
9+
pub fn try_strip_windows_prefix(path: PathBuf) -> Result<PathBuf, ResolveError> {
10+
// See https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
11+
let path_bytes = path.as_os_str().as_encoded_bytes();
12+
13+
let path = if let Some(p) =
14+
path_bytes.strip_prefix(br"\\?\UNC\").or(path_bytes.strip_prefix(br"\\.\UNC\"))
15+
{
16+
// UNC paths
17+
unsafe {
18+
PathBuf::from(std::ffi::OsStr::from_encoded_bytes_unchecked(&[br"\\", p].concat()))
19+
}
20+
} else if let Some(p) = path_bytes.strip_prefix(br"\\?\").or(path_bytes.strip_prefix(br"\\.\"))
21+
{
22+
// Assuming traditional DOS path "\\?\C:\"
23+
if p[1] != b':' {
24+
// E.g.,
25+
// \\?\Volume{b75e2c83-0000-0000-0000-602f00000000}
26+
// \\?\BootPartition\
27+
// It seems nodejs does not support DOS device paths with Volume GUIDs.
28+
// This can happen if the path points to a Mounted Volume without a drive letter.
29+
return Err(ResolveError::PathNotSupported(path));
30+
}
31+
unsafe { PathBuf::from(std::ffi::OsStr::from_encoded_bytes_unchecked(p)) }
32+
} else {
33+
path
34+
};
35+
36+
Ok(path)
37+
}
38+
39+
// #[cfg(target_os = "windows")]
40+
#[test]
41+
fn test_try_strip_windows_prefix() {
42+
let pass = [
43+
(r"\\?\C:\Users\user\Documents\file1.txt", r"C:\Users\user\Documents\file1.txt"),
44+
(r"\\.\C:\Users\user\Documents\file2.txt", r"C:\Users\user\Documents\file2.txt"),
45+
(r"\\?\UNC\server\share\file3.txt", r"\\server\share\file3.txt"),
46+
];
47+
48+
for (path, expected) in pass {
49+
assert_eq!(try_strip_windows_prefix(PathBuf::from(path)), Ok(PathBuf::from(expected)));
50+
}
51+
52+
let fail = [
53+
r"\\?\Volume{c8ec34d8-3ba6-45c3-9b9d-3e4148e12d00}\file4.txt",
54+
r"\\?\BootPartition\file4.txt",
55+
];
56+
57+
for path in fail {
58+
assert_eq!(
59+
try_strip_windows_prefix(PathBuf::from(path)),
60+
Err(crate::ResolveError::PathNotSupported(PathBuf::from(path)))
61+
);
62+
}
63+
}

0 commit comments

Comments
 (0)