|
| 1 | +//! Canonical definitions of `home_dir`, `cargo_home`, and `rustup_home`. |
| 2 | +//! |
| 3 | +//! This provides the definition of `home_dir` used by Cargo and |
| 4 | +//! rustup, as well functions to find the correct value of |
| 5 | +//! `CARGO_HOME` and `RUSTUP_HOME`. |
| 6 | +//! |
| 7 | +//! See also the [`dirs`](https://docs.rs/dirs) crate. |
| 8 | +//! |
| 9 | +//! _Note that as of 2019/08/06 it appears that cargo uses this crate. And |
| 10 | +//! rustup has used this crate since 2019/08/21._ |
| 11 | +//! |
| 12 | +//! The definition of `home_dir` provided by the standard library is |
| 13 | +//! incorrect because it considers the `HOME` environment variable on |
| 14 | +//! Windows. This causes surprising situations where a Rust program |
| 15 | +//! will behave differently depending on whether it is run under a |
| 16 | +//! Unix emulation environment like Cygwin or MinGW. Neither Cargo nor |
| 17 | +//! rustup use the standard libraries definition - they use the |
| 18 | +//! definition here. |
| 19 | +//! |
| 20 | +//! This crate further provides two functions, `cargo_home` and |
| 21 | +//! `rustup_home`, which are the canonical way to determine the |
| 22 | +//! location that Cargo and rustup store their data. |
| 23 | +//! |
| 24 | +//! See also this [discussion]. |
| 25 | +//! |
| 26 | +//! [discussion]: https://github.com/rust-lang/rust/pull/46799#issuecomment-361156935 |
| 27 | +
|
| 28 | +#![doc(html_root_url = "https://docs.rs/home/0.5.4")] |
| 29 | +#![deny(rust_2018_idioms)] |
| 30 | + |
| 31 | +pub mod env; |
| 32 | + |
| 33 | +#[cfg(windows)] |
| 34 | +mod windows; |
| 35 | + |
| 36 | +use std::io; |
| 37 | +use std::path::{Path, PathBuf}; |
| 38 | + |
| 39 | +/// Returns the path of the current user's home directory if known. |
| 40 | +/// |
| 41 | +/// # Unix |
| 42 | +/// |
| 43 | +/// Returns the value of the `HOME` environment variable if it is set |
| 44 | +/// and not equal to the empty string. Otherwise, it tries to determine the |
| 45 | +/// home directory by invoking the `getpwuid_r` function on the UID of the |
| 46 | +/// current user. |
| 47 | +/// |
| 48 | +/// # Windows |
| 49 | +/// |
| 50 | +/// Returns the value of the `USERPROFILE` environment variable if it |
| 51 | +/// is set and not equal to the empty string. If both do not exist, |
| 52 | +/// [`SHGetFolderPathW`][msdn] is used to return the appropriate path. |
| 53 | +/// |
| 54 | +/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetfolderpathw |
| 55 | +/// |
| 56 | +/// # Examples |
| 57 | +/// |
| 58 | +/// ``` |
| 59 | +/// match home::home_dir() { |
| 60 | +/// Some(path) => println!("{}", path.display()), |
| 61 | +/// None => println!("Impossible to get your home dir!"), |
| 62 | +/// } |
| 63 | +/// ``` |
| 64 | +pub fn home_dir() -> Option<PathBuf> { |
| 65 | + env::home_dir_with_env(&env::OS_ENV) |
| 66 | +} |
| 67 | + |
| 68 | +#[cfg(windows)] |
| 69 | +use windows::home_dir_inner; |
| 70 | + |
| 71 | +#[cfg(any(unix, target_os = "redox"))] |
| 72 | +fn home_dir_inner() -> Option<PathBuf> { |
| 73 | + #[allow(deprecated)] |
| 74 | + std::env::home_dir() |
| 75 | +} |
| 76 | + |
| 77 | +/// Returns the storage directory used by Cargo, often knowns as |
| 78 | +/// `.cargo` or `CARGO_HOME`. |
| 79 | +/// |
| 80 | +/// It returns one of the following values, in this order of |
| 81 | +/// preference: |
| 82 | +/// |
| 83 | +/// - The value of the `CARGO_HOME` environment variable, if it is |
| 84 | +/// an absolute path. |
| 85 | +/// - The value of the current working directory joined with the value |
| 86 | +/// of the `CARGO_HOME` environment variable, if `CARGO_HOME` is a |
| 87 | +/// relative directory. |
| 88 | +/// - The `.cargo` directory in the user's home directory, as reported |
| 89 | +/// by the `home_dir` function. |
| 90 | +/// |
| 91 | +/// # Errors |
| 92 | +/// |
| 93 | +/// This function fails if it fails to retrieve the current directory, |
| 94 | +/// or if the home directory cannot be determined. |
| 95 | +/// |
| 96 | +/// # Examples |
| 97 | +/// |
| 98 | +/// ``` |
| 99 | +/// match home::cargo_home() { |
| 100 | +/// Ok(path) => println!("{}", path.display()), |
| 101 | +/// Err(err) => eprintln!("Cannot get your cargo home dir: {:?}", err), |
| 102 | +/// } |
| 103 | +/// ``` |
| 104 | +pub fn cargo_home() -> io::Result<PathBuf> { |
| 105 | + env::cargo_home_with_env(&env::OS_ENV) |
| 106 | +} |
| 107 | + |
| 108 | +/// Returns the storage directory used by Cargo within `cwd`. |
| 109 | +/// For more details, see [`cargo_home`](fn.cargo_home.html). |
| 110 | +pub fn cargo_home_with_cwd(cwd: &Path) -> io::Result<PathBuf> { |
| 111 | + env::cargo_home_with_cwd_env(&env::OS_ENV, cwd) |
| 112 | +} |
| 113 | + |
| 114 | +/// Returns the storage directory used by rustup, often knowns as |
| 115 | +/// `.rustup` or `RUSTUP_HOME`. |
| 116 | +/// |
| 117 | +/// It returns one of the following values, in this order of |
| 118 | +/// preference: |
| 119 | +/// |
| 120 | +/// - The value of the `RUSTUP_HOME` environment variable, if it is |
| 121 | +/// an absolute path. |
| 122 | +/// - The value of the current working directory joined with the value |
| 123 | +/// of the `RUSTUP_HOME` environment variable, if `RUSTUP_HOME` is a |
| 124 | +/// relative directory. |
| 125 | +/// - The `.rustup` directory in the user's home directory, as reported |
| 126 | +/// by the `home_dir` function. |
| 127 | +/// |
| 128 | +/// # Errors |
| 129 | +/// |
| 130 | +/// This function fails if it fails to retrieve the current directory, |
| 131 | +/// or if the home directory cannot be determined. |
| 132 | +/// |
| 133 | +/// # Examples |
| 134 | +/// |
| 135 | +/// ``` |
| 136 | +/// match home::rustup_home() { |
| 137 | +/// Ok(path) => println!("{}", path.display()), |
| 138 | +/// Err(err) => eprintln!("Cannot get your rustup home dir: {:?}", err), |
| 139 | +/// } |
| 140 | +/// ``` |
| 141 | +pub fn rustup_home() -> io::Result<PathBuf> { |
| 142 | + env::rustup_home_with_env(&env::OS_ENV) |
| 143 | +} |
| 144 | + |
| 145 | +/// Returns the storage directory used by rustup within `cwd`. |
| 146 | +/// For more details, see [`rustup_home`](fn.rustup_home.html). |
| 147 | +pub fn rustup_home_with_cwd(cwd: &Path) -> io::Result<PathBuf> { |
| 148 | + env::rustup_home_with_cwd_env(&env::OS_ENV, cwd) |
| 149 | +} |
0 commit comments