diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2023-05-02 02:35:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-02 02:35:33 +0200 |
commit | 2f651b2d64523bdd377d22b8b7213a04ad82f459 (patch) | |
tree | f5776da1ee7e25b70bd736bf2428c3fbb06b35a0 /core/path.rs | |
parent | 000315e75a20e82616a227702c98346f2b5e8b59 (diff) |
fix(npm): canonicalize filename before returning (#18948)
This commit changes how paths for npm packages are handled,
by canonicalizing them when resolving. This is done so that instead
of returning
"node_modules/<package_name>@<version>/node_modules/<dep>/index.js"
(which is a symlink) we "node_modules/<dep>@<dep_version>/index.js.
Fixes https://github.com/denoland/deno/issues/18924
Fixes https://github.com/bluwy/create-vite-extra/issues/31
---------
Co-authored-by: David Sherret <dsherret@gmail.com>
Diffstat (limited to 'core/path.rs')
-rw-r--r-- | core/path.rs | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/core/path.rs b/core/path.rs new file mode 100644 index 000000000..fd8b1a9b6 --- /dev/null +++ b/core/path.rs @@ -0,0 +1,91 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. + +use std::path::PathBuf; + +#[cfg(not(windows))] +#[inline] +pub fn strip_unc_prefix(path: PathBuf) -> PathBuf { + path +} + +/// Strips the unc prefix (ex. \\?\) from Windows paths. +#[cfg(windows)] +pub fn strip_unc_prefix(path: PathBuf) -> PathBuf { + use std::path::Component; + use std::path::Prefix; + + let mut components = path.components(); + match components.next() { + Some(Component::Prefix(prefix)) => { + match prefix.kind() { + // \\?\device + Prefix::Verbatim(device) => { + let mut path = PathBuf::new(); + path.push(format!(r"\\{}\", device.to_string_lossy())); + path.extend(components.filter(|c| !matches!(c, Component::RootDir))); + path + } + // \\?\c:\path + Prefix::VerbatimDisk(_) => { + let mut path = PathBuf::new(); + path.push(prefix.as_os_str().to_string_lossy().replace(r"\\?\", "")); + path.extend(components); + path + } + // \\?\UNC\hostname\share_name\path + Prefix::VerbatimUNC(hostname, share_name) => { + let mut path = PathBuf::new(); + path.push(format!( + r"\\{}\{}\", + hostname.to_string_lossy(), + share_name.to_string_lossy() + )); + path.extend(components.filter(|c| !matches!(c, Component::RootDir))); + path + } + _ => path, + } + } + _ => path, + } +} + +#[cfg(test)] +mod test { + #[cfg(windows)] + #[test] + fn test_strip_unc_prefix() { + use std::path::PathBuf; + + run_test(r"C:\", r"C:\"); + run_test(r"C:\test\file.txt", r"C:\test\file.txt"); + + run_test(r"\\?\C:\", r"C:\"); + run_test(r"\\?\C:\test\file.txt", r"C:\test\file.txt"); + + run_test(r"\\.\C:\", r"\\.\C:\"); + run_test(r"\\.\C:\Test\file.txt", r"\\.\C:\Test\file.txt"); + + run_test(r"\\?\UNC\localhost\", r"\\localhost"); + run_test(r"\\?\UNC\localhost\c$\", r"\\localhost\c$"); + run_test( + r"\\?\UNC\localhost\c$\Windows\file.txt", + r"\\localhost\c$\Windows\file.txt", + ); + run_test(r"\\?\UNC\wsl$\deno.json", r"\\wsl$\deno.json"); + + run_test(r"\\?\server1", r"\\server1"); + run_test(r"\\?\server1\e$\", r"\\server1\e$\"); + run_test( + r"\\?\server1\e$\test\file.txt", + r"\\server1\e$\test\file.txt", + ); + + fn run_test(input: &str, expected: &str) { + assert_eq!( + super::strip_unc_prefix(PathBuf::from(input)), + PathBuf::from(expected) + ); + } + } +} |