|
1 | 1 | use std::{ |
2 | 2 | fs, io, |
3 | | - path::{Path, PathBuf}, |
| 3 | + path::{Component, Path, PathBuf}, |
4 | 4 | }; |
5 | 5 |
|
6 | 6 | /// File System abstraction used for `ResolverGeneric` |
@@ -91,33 +91,51 @@ impl FileSystem for FileSystemOs { |
91 | 91 | } |
92 | 92 |
|
93 | 93 | fn canonicalize(&self, path: &Path) -> io::Result<PathBuf> { |
94 | | - #[cfg(not(target_os = "wasi"))] |
| 94 | + #[cfg(target_os = "windows")] |
95 | 95 | { |
96 | 96 | dunce::canonicalize(path) |
97 | 97 | } |
98 | | - #[cfg(target_os = "wasi")] |
| 98 | + #[cfg(not(target_os = "windows"))] |
99 | 99 | { |
100 | | - let meta = fs::symlink_metadata(path)?; |
101 | | - if meta.file_type().is_symlink() { |
102 | | - let link = fs::read_link(path)?; |
103 | | - let mut path_buf = path.to_path_buf(); |
| 100 | + let mut path_buf = path.to_path_buf(); |
| 101 | + loop { |
| 102 | + let link = fs::read_link(&path_buf)?; |
104 | 103 | path_buf.pop(); |
105 | | - for segment in link.iter() { |
106 | | - match segment.to_str() { |
107 | | - Some("..") => { |
| 104 | + for component in link.components() { |
| 105 | + match component { |
| 106 | + Component::ParentDir => { |
108 | 107 | path_buf.pop(); |
109 | 108 | } |
110 | | - Some(".") | None => {} |
111 | | - Some(seg) => { |
112 | | - // Need to trim the extra \0 introduces by rust std rust-lang/rust#123727 |
113 | | - path_buf.push(seg.trim_end_matches('\0')); |
| 109 | + Component::Normal(seg) => { |
| 110 | + #[cfg(target_family = "wasm")] |
| 111 | + // Need to trim the extra \0 introduces by https://github.com/nodejs/uvwasi/issues/262 |
| 112 | + { |
| 113 | + path_buf.push(seg.to_string_lossy().trim_end_matches('\0')); |
| 114 | + } |
| 115 | + #[cfg(not(target_family = "wasm"))] |
| 116 | + { |
| 117 | + path_buf.push(seg); |
| 118 | + } |
114 | 119 | } |
| 120 | + Component::RootDir => { |
| 121 | + #[cfg(target_os = "windows")] |
| 122 | + { |
| 123 | + path_buf.push("\\"); |
| 124 | + } |
| 125 | + #[cfg(not(target_os = "windows"))] |
| 126 | + { |
| 127 | + #[allow(clippy::path_buf_push_overwrite)] |
| 128 | + path_buf.push("/"); |
| 129 | + } |
| 130 | + } |
| 131 | + Component::CurDir | Component::Prefix(_) => {} |
115 | 132 | } |
116 | 133 | } |
117 | | - Ok(path_buf) |
118 | | - } else { |
119 | | - Ok(path.to_path_buf()) |
| 134 | + if !fs::symlink_metadata(&path_buf)?.is_symlink() { |
| 135 | + break; |
| 136 | + } |
120 | 137 | } |
| 138 | + Ok(path_buf) |
121 | 139 | } |
122 | 140 | } |
123 | 141 | } |
|
0 commit comments