Skip to content

Commit 9eeae42

Browse files
authored
Rollup merge of #132515 - kornelski:home_fix, r=jhpratt
Fix and undeprecate home_dir() `home_dir()` has been deprecated for 6 years due to using `HOME` env var on Windows. It's been a long time, and having a perpetually buggy and deprecated function in the standard library is not useful. I propose fixing and undeprecating it. 6 years seems more than long enough to warn users against relying on this function. The change in behavior is minor, and it's more of a bug fix than breakage. The old behavior is unlikely to be useful, and even if anybody actually needed to specifically use the non-standard `HOME` on Windows, they can trivially mitigate this change by reading the env var themselves. ---- Use of `USERPROFILE` is in line with the `home` crate: https://github.com/rust-lang/cargo/blob/37bc5f0232a0bb72dedd2c14149614fd8cdae649/crates/home/src/windows.rs#L12 The `home` crate uses `SHGetKnownFolderPath` instead of `GetUserProfileDirectoryW`. AFAIK it doesn't make any difference in practice, because `SHGetKnownFolderPath` merely adds support for more kinds of folders, including virtual (non-filesystem) folders identified by a GUID, but the specific case of [`FOLDERID_Profile`](https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#FOLDERID_Profile) is documented as a FIXED folder (a regular filesystem path). Just in case, I've added a note to documentation that the use of `GetUserProfileDirectoryW` can change. I've used `CURRENT_RUSTC_VERSION` in a doccomment. `replace-version-placeholder` tool seems to perform a simple string replacement, so hopefully it'll get updated.
2 parents 1aa0192 + 4b7f56a commit 9eeae42

File tree

3 files changed

+14
-18
lines changed

3 files changed

+14
-18
lines changed

library/std/src/env.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -608,20 +608,16 @@ impl Error for JoinPathsError {
608608
///
609609
/// # Windows
610610
///
611-
/// - Returns the value of the 'HOME' environment variable if it is set
612-
/// (including to an empty string).
613-
/// - Otherwise, returns the value of the 'USERPROFILE' environment variable if it is set
614-
/// (including to an empty string).
615-
/// - If both do not exist, [`GetUserProfileDirectory`][msdn] is used to return the path.
611+
/// - Returns the value of the 'USERPROFILE' environment variable if it is set, and is not an empty string.
612+
/// - Otherwise, [`GetUserProfileDirectory`][msdn] is used to return the path. This may change in the future.
616613
///
617614
/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectorya
618615
///
619-
/// # Deprecation
616+
/// In UWP (Universal Windows Platform) targets this function is unimplemented and always returns `None`.
620617
///
621-
/// This function is deprecated because the behavior on Windows is not correct.
622-
/// The 'HOME' environment variable is not standard on Windows, and may not produce
623-
/// desired results; for instance, under Cygwin or Mingw it will return `/home/you`
624-
/// when it should return `C:\Users\you`.
618+
/// Before Rust CURRENT_RUSTC_VERSION, this function used to return the value of the 'HOME' environment variable
619+
/// on Windows, which in Cygwin or Mingw environments could return non-standard paths like `/home/you`
620+
/// instead of `C:\Users\you`.
625621
///
626622
/// # Examples
627623
///

library/std/src/sys/pal/windows/os.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,8 @@ fn home_dir_crt() -> Option<PathBuf> {
377377
}
378378

379379
pub fn home_dir() -> Option<PathBuf> {
380-
crate::env::var_os("HOME")
381-
.or_else(|| crate::env::var_os("USERPROFILE"))
380+
crate::env::var_os("USERPROFILE")
381+
.filter(|s| !s.is_empty())
382382
.map(PathBuf::from)
383383
.or_else(home_dir_crt)
384384
}

library/std/tests/env.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -122,19 +122,19 @@ fn env_home_dir() {
122122

123123
assert!(home_dir().is_some());
124124

125-
set_var("HOME", "/home/MountainView");
125+
set_var("HOME", "/home/PaloAlto");
126+
assert_ne!(home_dir(), Some(PathBuf::from("/home/PaloAlto")), "HOME must not be used");
127+
128+
set_var("USERPROFILE", "/home/MountainView");
126129
assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
127130

128131
remove_var("HOME");
129132

130-
set_var("USERPROFILE", "/home/MountainView");
131133
assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
132134

133-
set_var("HOME", "/home/MountainView");
134-
set_var("USERPROFILE", "/home/PaloAlto");
135-
assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
135+
set_var("USERPROFILE", "");
136+
assert_ne!(home_dir(), Some(PathBuf::from("")), "Empty USERPROFILE must be ignored");
136137

137-
remove_var("HOME");
138138
remove_var("USERPROFILE");
139139

140140
if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }

0 commit comments

Comments
 (0)