diff --git a/crates/uv-fs/src/path.rs b/crates/uv-fs/src/path.rs index 3a3c051d8..11e88feef 100644 --- a/crates/uv-fs/src/path.rs +++ b/crates/uv-fs/src/path.rs @@ -1,5 +1,5 @@ use std::borrow::Cow; -use std::path::{Component, Path, PathBuf}; +use std::path::{absolute, Component, Path, PathBuf}; use std::sync::LazyLock; use either::Either; @@ -13,7 +13,7 @@ pub static CWD: LazyLock = pub static CANONICAL_CWD: LazyLock = LazyLock::new(|| { std::env::current_dir() .expect("The current directory must exist") - .canonicalize() + .simple_canonicalize() .expect("The current directory must be canonicalized") }); @@ -30,6 +30,8 @@ pub trait Simplified { fn simplified_display(&self) -> impl std::fmt::Display; /// Canonicalize a path without a `\\?\` prefix on Windows. + /// For a path that can't be canonicalized (e.g. on network drive or RAM drive on Windows), + /// this will return the absolute path if it exists. fn simple_canonicalize(&self) -> std::io::Result; /// Render a [`Path`] for user-facing display. @@ -59,7 +61,21 @@ impl> Simplified for T { } fn simple_canonicalize(&self) -> std::io::Result { - dunce::canonicalize(self.as_ref()) + match dunce::canonicalize(self.as_ref()) { + Ok(path) => Ok(path), + // On Windows, `dunce::canonicalize` can't canonicalize paths on network drives or RAM + // drives. In that case, fall back on `std::path::absolute`, but also verify that the + // path exists. + Err(e) if std::env::consts::OS != "windows" => Err(e), + _ => match absolute(self.as_ref()) { + Ok(path) if path.exists() => Ok(path), + Ok(_) => Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + format!("Path does not exist: {}", self.simplified_display()), + )), + Err(e) => Err(e), + }, + } } fn user_display(&self) -> impl std::fmt::Display {