Skip to content

Commit

Permalink
fix: use same UNC path normalization logic with libuv
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red committed Nov 12, 2024
1 parent 1fe94ec commit 7147925
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 13 deletions.
7 changes: 0 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ serde_json = { version = "1", features = [
"preserve_order",
] } # preserve_order: package_json.exports requires order such as `["require", "import", "default"]`
rustc-hash = { version = "2" }
dunce = "1" # Normalize Windows paths to the most compatible format, avoiding UNC where possible
once_cell = "1" # Use `std::sync::OnceLock::get_or_try_init` when it is stable.
thiserror = "1"
json-strip-comments = "1"
Expand Down
3 changes: 3 additions & 0 deletions fixtures/pnpm/longfilename/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const test = 'hello world'

export default test
7 changes: 7 additions & 0 deletions fixtures/pnpm/longfilename/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "@oxc-resolver/test-longfilename-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"private": true,
"version": "0.0.0",
"main": "index.js",
"type": "module"
}
1 change: 1 addition & 0 deletions fixtures/pnpm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "1.0.0",
"private": true,
"devDependencies": {
"@oxc-resolver/test-longfilename-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa": "file:./longfilename",
"axios": "1.6.2",
"ipaddr.js": "2.2.0",
"postcss": "8.4.33",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 38 additions & 5 deletions src/file_system.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
use std::{
fs, io,
path::{Path, PathBuf},
path::{Component, Path, PathBuf, Prefix},
};

use cfg_if::cfg_if;
#[cfg(feature = "yarn_pnp")]
use pnp::fs::{LruZipCache, VPath, VPathInfo, ZipCache};

#[cfg(windows)]
const UNC_PATH_PREFIX: &str = "\\\\?\\UNC\\";
#[cfg(windows)]
const LONG_PATH_PREFIX: &str = "\\\\?\\";

/// File System abstraction used for `ResolverGeneric`
pub trait FileSystem: Send + Sync {
/// See [std::fs::read_to_string]
Expand Down Expand Up @@ -165,13 +170,13 @@ impl FileSystem for FileSystemOs {
if #[cfg(feature = "yarn_pnp")] {
match VPath::from(path)? {
VPath::Zip(info) => {
dunce::canonicalize(info.physical_base_path().join(info.zip_path))
node_compatible_raw_canonicalize(info.physical_base_path().join(info.zip_path))
}
VPath::Virtual(info) => dunce::canonicalize(info.physical_base_path()),
VPath::Native(path) => dunce::canonicalize(path),
VPath::Virtual(info) => node_compatible_raw_canonicalize(info.physical_base_path()),
VPath::Native(path) => node_compatible_raw_canonicalize(path),
}
} else if #[cfg(windows)] {
dunce::canonicalize(path)
node_compatible_raw_canonicalize(path)
} else {
use std::path::Component;
let mut path_buf = path.to_path_buf();
Expand Down Expand Up @@ -227,3 +232,31 @@ fn metadata() {
);
let _ = meta;
}

fn node_compatible_raw_canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
cfg_if! {
if #[cfg(windows)] {
// same logic with https://github.com/libuv/libuv/blob/d4ab6fbba4669935a6bc23645372dfe4ac29ab39/src/win/fs.c#L2774-L2784
let canonicalized = fs::canonicalize(path)?;
let first_component = canonicalized.components().next();
match first_component {
Some(Component::Prefix(prefix)) => {
match prefix.kind() {
Prefix::VerbatimUNC(_, _) => {
Ok(canonicalized.to_str().and_then(|s| s.get(UNC_PATH_PREFIX.len()..)).map(PathBuf::from).unwrap_or(canonicalized))
}
Prefix::VerbatimDisk(_) => {
Ok(canonicalized.to_str().and_then(|s| s.get(LONG_PATH_PREFIX.len()..)).map(PathBuf::from).unwrap_or(canonicalized))
}
_ => {
Ok(canonicalized)
}
}
}
_ => Ok(canonicalized),
}
} else {
fs::canonicalize(path)
}
}
}
10 changes: 10 additions & 0 deletions tests/resolve_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,13 @@ fn nested_symlinks() {
Ok(dir.join("nm/index.js"))
);
}

#[test]
fn windows_symlinked_longfilename() {
let dir = dir();
let path = dir.join("fixtures/pnpm");
let module_path = dir.join("node_modules/.pnpm/@oxc-resolver+test-longfilename-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_m464apeldykmdsyzlfhtrggk24/node_modules/@oxc-resolver/test-longfilename-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/index.js");

let resolution = Resolver::new(ResolveOptions::default()).resolve(&path, "@oxc-resolver/test-longfilename-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").map(|r| r.full_path());
assert_eq!(resolution, Ok(module_path));
}

0 comments on commit 7147925

Please sign in to comment.