|
7 | 7 |
|
8 | 8 | use deno_error::JsError; |
9 | 9 | use std::borrow::Cow; |
10 | | -use std::ffi::OsString; |
11 | 10 | use std::path::Component; |
12 | 11 | use std::path::Path; |
13 | 12 | use std::path::PathBuf; |
@@ -146,32 +145,39 @@ fn url_to_file_path_wasm(url: &Url) -> Result<PathBuf, ()> { |
146 | 145 | /// <https://github.com/rust-lang/cargo/blob/af307a38c20a753ec60f0ad18be5abed3db3c9ac/src/cargo/util/paths.rs#L60-L85> |
147 | 146 | #[inline] |
148 | 147 | pub fn normalize_path(path: Cow<Path>) -> Cow<Path> { |
149 | | - enum ShouldNormalize { |
150 | | - Yes, |
151 | | - No, |
152 | | - EnsureNoTrailingSlash, |
153 | | - } |
| 148 | + fn should_normalize(path: &Path) -> bool { |
| 149 | + if path_has_trailing_separator(&path) { |
| 150 | + return true; |
| 151 | + } |
154 | 152 |
|
155 | | - fn should_normalize(path: &Path) -> ShouldNormalize { |
156 | | - let mut had_normal = false; |
157 | 153 | for component in path.components() { |
158 | 154 | match component { |
159 | 155 | Component::CurDir | Component::ParentDir => { |
160 | | - return ShouldNormalize::Yes; |
| 156 | + return true; |
161 | 157 | } |
162 | | - Component::Prefix(..) | Component::RootDir => { |
| 158 | + Component::Prefix(..) | Component::RootDir | Component::Normal(_) => { |
163 | 159 | // ok |
164 | 160 | } |
165 | | - Component::Normal(_) => had_normal = true, |
166 | 161 | } |
167 | 162 | } |
168 | 163 |
|
169 | | - if path_has_cur_dir_separator(path) { |
170 | | - ShouldNormalize::Yes |
171 | | - } else if had_normal { |
172 | | - ShouldNormalize::EnsureNoTrailingSlash |
| 164 | + path_has_cur_dir_separator(path) |
| 165 | + } |
| 166 | + |
| 167 | + fn path_has_trailing_separator(path: &Path) -> bool { |
| 168 | + #[cfg(unix)] |
| 169 | + let raw = std::os::unix::ffi::OsStrExt::as_bytes(path.as_os_str()); |
| 170 | + #[cfg(windows)] |
| 171 | + let raw = path.as_os_str().as_encoded_bytes(); |
| 172 | + #[cfg(target_arch = "wasm32")] |
| 173 | + let raw = path.to_string_lossy(); |
| 174 | + #[cfg(target_arch = "wasm32")] |
| 175 | + let raw = raw.as_bytes(); |
| 176 | + |
| 177 | + if sys_traits::impls::is_windows() { |
| 178 | + raw.contains(&('/' as u8)) || raw.ends_with(b"\\") |
173 | 179 | } else { |
174 | | - ShouldNormalize::No |
| 180 | + raw.ends_with(b"/") |
175 | 181 | } |
176 | 182 | } |
177 | 183 |
|
@@ -205,29 +211,6 @@ pub fn normalize_path(path: Cow<Path>) -> Cow<Path> { |
205 | 211 | false |
206 | 212 | } |
207 | 213 |
|
208 | | - // Warning: this makes some assumptions like not handling a |
209 | | - // path like `/path/../` because it's assumed paths like that |
210 | | - // won't be passed here because they'd be normalized by looping |
211 | | - // over the components instead. |
212 | | - fn ensure_no_trailing_slash(path: Cow<Path>) -> Cow<Path> { |
213 | | - let is_windows = sys_traits::impls::is_windows(); |
214 | | - let mut bytes = path.as_os_str().as_encoded_bytes(); |
215 | | - let start_len = bytes.len(); |
216 | | - while bytes.len() > 1 |
217 | | - && (is_windows && bytes.ends_with(b"\\") || bytes.ends_with(b"/")) |
218 | | - { |
219 | | - bytes = &bytes[..bytes.len() - 1]; |
220 | | - } |
221 | | - |
222 | | - if bytes.len() == start_len { |
223 | | - return path; |
224 | | - } |
225 | | - |
226 | | - let new_len = bytes.len(); |
227 | | - let os_string = path.into_owned().into_os_string(); |
228 | | - Cow::Owned(PathBuf::from(truncate_os_string(os_string, new_len))) |
229 | | - } |
230 | | - |
231 | 214 | fn inner(path: &Path) -> PathBuf { |
232 | 215 | let mut components = path.components().peekable(); |
233 | 216 | let mut ret = |
@@ -256,29 +239,13 @@ pub fn normalize_path(path: Cow<Path>) -> Cow<Path> { |
256 | 239 | ret |
257 | 240 | } |
258 | 241 |
|
259 | | - match should_normalize(&path) { |
260 | | - ShouldNormalize::Yes => Cow::Owned(inner(&path)), |
261 | | - ShouldNormalize::No => path, |
262 | | - ShouldNormalize::EnsureNoTrailingSlash => ensure_no_trailing_slash(path), |
| 242 | + if should_normalize(&path) { |
| 243 | + Cow::Owned(inner(&path)) |
| 244 | + } else { |
| 245 | + path |
263 | 246 | } |
264 | 247 | } |
265 | 248 |
|
266 | | -#[cfg(unix)] |
267 | | -fn truncate_os_string(mut os: OsString, n: usize) -> OsString { |
268 | | - use std::os::unix::ffi::OsStringExt; |
269 | | - let mut bytes = os.into_vec(); |
270 | | - bytes.truncate(n); |
271 | | - OsString::from_vec(bytes) |
272 | | -} |
273 | | - |
274 | | -#[cfg(windows)] |
275 | | -fn truncate_os_string(os: OsString, n: usize) -> OsString { |
276 | | - use std::os::windows::ffi::OsStrExt; |
277 | | - use std::os::windows::ffi::OsStringExt; |
278 | | - let wide: Vec<u16> = os.encode_wide().take(n).collect(); |
279 | | - OsString::from_wide(&wide) |
280 | | -} |
281 | | - |
282 | 249 | #[derive(Debug, Clone, Error, deno_error::JsError, PartialEq, Eq)] |
283 | 250 | #[class(uri)] |
284 | 251 | #[error("Could not convert path to URL.\n Path: {0}")] |
|
0 commit comments