# env_home rust crate A pure-Rust crate for determining user home directories via environment variables in a platform independent manner with no external dependencies. Check `HOME` on Unix and `USERPROFILE` on Windows. ## Description env_home is a general purpose crate for determining the current user home directory via environment variables. It can be used as drop-in replacement for [`std::env::home_dir` (deprecated)](https://doc.rust-lang.org/std/env/fn.home_dir.html) from the rust standard library. Unlike `std::env::home_dir` this crate **only** looks at environment variables and does attempt to fallback on platform specific APIs. As a result implementation of `env_home_dir` is [very simple](src/lib.rs) with no dependencies on other crates. This functionality is comparable to Golang's [os.UserHomeDir()](https://pkg.go.dev/os#UserHomeDir) or Python's [Path.home()](https://docs.python.org/3/library/pathlib.html#pathlib.Path.home). ## env_home::env_home_dir Behavior The API of this crate is a single function `env_home_dir` which attempts to fetch a user's home directory from environment variables in a platform independent way supporting Windows and Unix (Linux/MacOS/BSD/WSL, etc). | Platform | Environment Variable | Example | | --------------------------------- | -------------------- | ----------------- | | MacOS, Linux or other Unix | `HOME` | `/home/user` | | Windows Subsystem for Linux (WSL) | `HOME` | `/home/user` | | Windows Native | `USERPROFILE` | `C:\\Users\\user` | | Others (WASM, etc) | N/A | None | 1. If the environment variable is unset, `None` is returned. 2. If the environment variable is set to an empty string, `None` is returned. 3. On non-unix / non-windows platforms (like WASM) that don't implement a home directory `None` will be returned. 4. If the environment variable is set to a non-empty string, the value is returned as a `PathBuf`. That's it. If you need a more full-service crate consider using the [dirs](https://crates.io/crates/dirs) crate. ## Usage ```shell cargo add env_home ``` Crate exports a single function `env_home_dir` that returns `Option<PathBuf>` ```rust use env_home::env_home_dir as home_dir; fn main() { match home_dir() { Some(path) => println!("User home directory: {}", path.display()), None => println!("No home found. HOME/USERPROFILE not set or empty"), } } ``` See the [std::path::PathBuf documentation](https://doc.rust-lang.org/std/path/struct.PathBuf.html) for more information on how to use `PathBuf` objects. ## Differences with `std::env::home_dir` env_home_dir returns `None` instead of `""` when `HOME` or `USERPROFILE` is set to an empty string. I believe [`std::env::home_dir`](https://doc.rust-lang.org/std/env/fn.home_dir.html) was trying to be too smart. It calls Platform specific APIs like ([GetUserProfileDirectoryW](https://learn.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectoryw) on Windows or [getpwuid_r](https://linux.die.net/man/3/getpwuid_r) on Unix as a fallback when `HOME` or `USERPROFILE` environment variables are not set. We just give up and return `None`. This crate exists because the behavior of [`home_dir`](https://doc.rust-lang.org/std/env/fn.home_dir.html) provided by the standard library may be unexpected on Windows. And thus was [deprecated](https://doc.rust-lang.org/std/env/fn.home_dir.html#deprecation) and has remained broken / unfixed since Rust 1.29.0 (Sept 2018). ## As an alternative to the `home` crate Although many projects have switched from `std::env::home_dir` to `home::home_dir` provided by the [home](https://crates.io/crates/home) crate because it was maintained by the cargo team and thus presumably more "official". The Cargo team has clarified that the `home` crate is not intended for general use: > "the cargo team doesn't want to take on the maintenance of home as a general-purpose crate for the community" [...] > "we are thinking of documenting that home is not intended for anything but use inside of cargo and rustup, and suggest people use some other crate instead." > [source](https://github.com/rust-lang/cargo/issues/12297) As a result the `home` crate refuses to compile for WASM target and they have have no plans to fix this. env_home crate implements a fallback no-op which returns `None` on non-windows / non-unix platforms like WASM. ## Other Notes Using [std::env::set_var](https://doc.rust-lang.org/std/env/fn.set_var.html) to alter your environment at runtime is unsafe in multi-threaded applications. Full stop. It may result in random panics or undefined behavior. You have have been warned. Bonus: cargo runs tests in parallel threads by-default, so even if you app is not multi-threaded if you have tests that invoke `std::env::set_var` be sure to set `RUST_TEST_THREADS=1` or use `cargo test -- --test-threads=1` or your tests may intermittently panic and fail. See [rust-lang/rust#27970](https://github.com/rust-lang/rust/issues/27970) and [Setenv is not Thread Safe and C Doesn't Want to Fix It](https://www.evanjones.ca/setenv-is-not-thread-safe.html) for more. ## License Copyright (c) 2024 Peter Tripp This project is licensed under the [MIT License](LICENSE-MIT) or [Apache License, Version 2.0](LICENSE-APACHE) at your option.