diff --git a/Cargo.lock b/Cargo.lock index 2c46eaaff1e..5200fa99f58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2655,9 +2655,6 @@ dependencies = [ [[package]] name = "home" version = "0.5.13" -dependencies = [ - "windows-sys 0.61.2", -] [[package]] name = "html-escape" diff --git a/crates/home/Cargo.toml b/crates/home/Cargo.toml index 678b3165b87..11e22a76297 100644 --- a/crates/home/Cargo.toml +++ b/crates/home/Cargo.toml @@ -16,8 +16,5 @@ license.workspace = true repository.workspace = true description = "Shared definitions of home directories." -[target.'cfg(windows)'.dependencies] -windows-sys = { workspace = true, features = ["Win32_Foundation", "Win32_UI_Shell", "Win32_System_Com"] } - [lints] workspace = true diff --git a/crates/home/README.md b/crates/home/README.md index 0211b5a0cd9..d6c977a8729 100644 --- a/crates/home/README.md +++ b/crates/home/README.md @@ -7,31 +7,21 @@ This provides the definition of `home_dir` used by Cargo and rustup, as well functions to find the correct value of `CARGO_HOME` and `RUSTUP_HOME`. -The definition of [`home_dir`] provided by the standard library is -incorrect because it considers the `HOME` environment variable on -Windows. This causes surprising situations where a Rust program will -behave differently depending on whether it is run under a Unix -emulation environment like Cygwin or MinGW. Neither Cargo nor rustup -use the standard library's definition - they use the definition here. - -**Note:** This has been fixed in Rust 1.85 to no longer use the `HOME` -environment variable on Windows. If you are still using this crate for the -purpose of getting a home directory, you are strongly encouraged to switch to -using the standard library's [`home_dir`] instead. It is planned to have the -deprecation notice removed in 1.87. +This crate previously used its own definition of `home_dir` on Windows to avoid +[rust-lang/rust#43321], but this was fixed in [1.85.0] so this crate now +simply forwards to [`home_dir`]. This crate further provides two functions, `cargo_home` and `rustup_home`, which are the canonical way to determine the location that Cargo and rustup store their data. -See [rust-lang/rust#43321]. - > This crate is maintained by the Cargo team, primarily for use by Cargo and Rustup > and not intended for external use. This > crate may make major changes to its APIs or be deprecated without warning. [rust-lang/rust#43321]: https://github.com/rust-lang/rust/issues/43321 [`home_dir`]: https://doc.rust-lang.org/nightly/std/env/fn.home_dir.html +[1.85.0]: https://blog.rust-lang.org/2025/02/20/Rust-1.85.0/#updates-to-std-env-home-dir ## License diff --git a/crates/home/src/env.rs b/crates/home/src/env.rs index f5a6a2231a8..8c393a2a065 100644 --- a/crates/home/src/env.rs +++ b/crates/home/src/env.rs @@ -30,7 +30,7 @@ pub trait Env { pub struct OsEnv; impl Env for OsEnv { fn home_dir(&self) -> Option { - crate::home_dir_inner() + std::env::home_dir() } fn current_dir(&self) -> io::Result { std::env::current_dir() diff --git a/crates/home/src/lib.rs b/crates/home/src/lib.rs index cc3e93a1905..1ab9e5d6a31 100644 --- a/crates/home/src/lib.rs +++ b/crates/home/src/lib.rs @@ -26,33 +26,13 @@ pub mod env; -#[cfg(target_os = "windows")] -mod windows; - use std::io; use std::path::{Path, PathBuf}; /// Returns the path of the current user's home directory using environment /// variables or OS-specific APIs. /// -/// # Unix -/// -/// Returns the value of the `HOME` environment variable if it is set -/// **even** if it is an empty string. Otherwise, it tries to determine the -/// home directory by invoking the [`getpwuid_r`][getpwuid] function with -/// the UID of the current user. -/// -/// [getpwuid]: https://linux.die.net/man/3/getpwuid_r -/// -/// # Windows -/// -/// Returns the value of the `USERPROFILE` environment variable if it is set -/// **and** it is not an empty string. Otherwise, it tries to determine the -/// home directory by invoking the [`SHGetKnownFolderPath`][shgkfp] function with -/// [`FOLDERID_Profile`][knownfolderid]. -/// -/// [shgkfp]: https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath -/// [knownfolderid]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid +/// This function is just a wrapper around [`std::env::home_dir`](https://doc.rust-lang.org/std/env/fn.home_dir.html) /// /// # Examples /// @@ -66,15 +46,6 @@ pub fn home_dir() -> Option { env::home_dir_with_env(&env::OS_ENV) } -#[cfg(windows)] -use windows::home_dir_inner; - -#[cfg(unix)] -fn home_dir_inner() -> Option { - #[allow(deprecated)] - std::env::home_dir() -} - /// Returns the storage directory used by Cargo, often known as /// `.cargo` or `CARGO_HOME`. /// diff --git a/crates/home/src/windows.rs b/crates/home/src/windows.rs deleted file mode 100644 index 652733ec0ff..00000000000 --- a/crates/home/src/windows.rs +++ /dev/null @@ -1,84 +0,0 @@ -use std::env; -use std::ffi::OsString; -use std::os::windows::ffi::OsStringExt; -use std::path::PathBuf; -use std::ptr; -use std::slice; - -use windows_sys::Win32::Foundation::S_OK; -use windows_sys::Win32::System::Com::CoTaskMemFree; -use windows_sys::Win32::UI::Shell::{FOLDERID_Profile, KF_FLAG_DONT_VERIFY, SHGetKnownFolderPath}; - -pub fn home_dir_inner() -> Option { - env::var_os("USERPROFILE") - .filter(|s| !s.is_empty()) - .map(PathBuf::from) - .or_else(home_dir_crt) -} - -#[cfg(not(target_vendor = "uwp"))] -fn home_dir_crt() -> Option { - unsafe { - let mut path = ptr::null_mut(); - match SHGetKnownFolderPath( - &FOLDERID_Profile, - KF_FLAG_DONT_VERIFY as u32, - std::ptr::null_mut(), - &mut path, - ) { - S_OK => { - let path_slice = slice::from_raw_parts(path, wcslen(path)); - let s = OsString::from_wide(&path_slice); - CoTaskMemFree(path.cast()); - Some(PathBuf::from(s)) - } - _ => { - // Free any allocated memory even on failure. A null ptr is a no-op for `CoTaskMemFree`. - CoTaskMemFree(path.cast()); - None - } - } - } -} - -#[cfg(target_vendor = "uwp")] -fn home_dir_crt() -> Option { - None -} - -unsafe extern "C" { - fn wcslen(buf: *const u16) -> usize; -} - -#[cfg(not(target_vendor = "uwp"))] -#[cfg(test)] -mod tests { - use super::home_dir_inner; - use std::env; - use std::ops::Deref; - use std::path::{Path, PathBuf}; - - #[test] - fn test_with_without() { - let olduserprofile = env::var_os("USERPROFILE").unwrap(); - - unsafe { - env::remove_var("HOME"); - env::remove_var("USERPROFILE"); - } - - assert_eq!(home_dir_inner(), Some(PathBuf::from(olduserprofile))); - - let home = Path::new(r"C:\Users\foo tar baz"); - - unsafe { - env::set_var("HOME", home.as_os_str()); - } - assert_ne!(home_dir_inner().as_ref().map(Deref::deref), Some(home)); - - unsafe { - env::set_var("USERPROFILE", home.as_os_str()); - } - assert_eq!(home_dir_inner().as_ref().map(Deref::deref), Some(home)); - } -}