-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Update etcetera to 0.11; no longer depend on home; MSRV 1.87
#3464
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
How does std::env::home_dir() and home::home_dir() implementations differ? |
Good question. The PR rust-lang/rust#132515 that fixed the standard-library implementation talks about this a bit. The standard-library function uses a different API function on Windows than the The https://github.com/rust-lang/cargo/blob/home-0.5.12/crates/home/src/lib.rs#L65-L67 pub fn home_dir() -> Option<PathBuf> {
env::home_dir_with_env(&env::OS_ENV)
}It turns out that, for the OS context, this ultimately ends up dispatching to #[cfg(windows)]
use windows::home_dir_inner;
#[cfg(unix)]
fn home_dir_inner() -> Option<PathBuf> {
#[allow(deprecated)]
std::env::home_dir()
}So for non-Windows platforms, the answer is easy: 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<PathBuf> {
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<PathBuf> {
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<PathBuf> {
None
}
unsafe extern "C" {
fn wcslen(buf: *const u16) -> usize;
}Briefly, it uses the value of the For the standard library, we have a similar dispatching scheme, https://github.com/rust-lang/rust/blob/1.91.0/library/std/src/env.rs#L643: pub fn home_dir() -> Option<PathBuf> {
os_imp::home_dir()
}This ends up dispatching to pub fn home_dir() -> Option<PathBuf> {
crate::env::var_os("USERPROFILE")
.filter(|s| !s.is_empty())
.map(PathBuf::from)
.or_else(home_dir_crt)
}So far, this is identical to the code in the So the very short version is just as rust-lang/rust#132515 said: on Windows, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, thanks for explaining.
Release 0.11 of `etcetera` requires MSRV 1.87, in which `std::env::home_dir` is no longer deprecated, rust-lang/rust#137327. Update to that MSRV and to `etcetera`, and drop the dependency on the `home` crate just as `etcetera` 0.11 did.
89d3dbb to
9762b38
Compare
Release 0.11 of
etceterarequires MSRV 1.87, in whichstd::env::home_diris no longer deprecated,rust-lang/rust#137327.
Update to that MSRV and to
etcetera, and drop the dependency on thehomecrate just asetcetera0.11 did.