mirror of
https://github.com/denoland/deno.git
synced 2025-01-03 04:48:52 -05:00
fix(cli): don't panic when no "HOME" env var is set (#6728)
This commit is contained in:
parent
11560387bb
commit
d619e3c7ac
2 changed files with 84 additions and 11 deletions
|
@ -14,24 +14,22 @@ pub struct DenoDir {
|
||||||
|
|
||||||
impl DenoDir {
|
impl DenoDir {
|
||||||
pub fn new(maybe_custom_root: Option<PathBuf>) -> std::io::Result<Self> {
|
pub fn new(maybe_custom_root: Option<PathBuf>) -> std::io::Result<Self> {
|
||||||
// Only setup once.
|
|
||||||
let home_dir = dirs::home_dir().expect("Could not get home directory.");
|
|
||||||
let fallback = home_dir.join(".deno");
|
|
||||||
// We use the OS cache dir because all files deno writes are cache files
|
|
||||||
// Once that changes we need to start using different roots if DENO_DIR
|
|
||||||
// is not set, and keep a single one if it is.
|
|
||||||
let default = dirs::cache_dir()
|
|
||||||
.map(|d| d.join("deno"))
|
|
||||||
.unwrap_or(fallback);
|
|
||||||
|
|
||||||
let root: PathBuf = if let Some(root) = maybe_custom_root {
|
let root: PathBuf = if let Some(root) = maybe_custom_root {
|
||||||
if root.is_absolute() {
|
if root.is_absolute() {
|
||||||
root
|
root
|
||||||
} else {
|
} else {
|
||||||
std::env::current_dir()?.join(root)
|
std::env::current_dir()?.join(root)
|
||||||
}
|
}
|
||||||
|
} else if let Some(cache_dir) = dirs::cache_dir() {
|
||||||
|
// We use the OS cache dir because all files deno writes are cache files
|
||||||
|
// Once that changes we need to start using different roots if DENO_DIR
|
||||||
|
// is not set, and keep a single one if it is.
|
||||||
|
cache_dir.join("deno")
|
||||||
|
} else if let Some(home_dir) = dirs::home_dir() {
|
||||||
|
// fallback path
|
||||||
|
home_dir.join(".deno")
|
||||||
} else {
|
} else {
|
||||||
default
|
panic!("Could not set the Deno root directory")
|
||||||
};
|
};
|
||||||
assert!(root.is_absolute());
|
assert!(root.is_absolute());
|
||||||
let gen_path = root.join("gen");
|
let gen_path = root.join("gen");
|
||||||
|
@ -64,8 +62,35 @@ mod dirs {
|
||||||
pub fn home_dir() -> Option<PathBuf> {
|
pub fn home_dir() -> Option<PathBuf> {
|
||||||
std::env::var_os("HOME")
|
std::env::var_os("HOME")
|
||||||
.and_then(|h| if h.is_empty() { None } else { Some(h) })
|
.and_then(|h| if h.is_empty() { None } else { Some(h) })
|
||||||
|
.or_else(|| unsafe { fallback() })
|
||||||
.map(PathBuf::from)
|
.map(PathBuf::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This piece of code is taken from the deprecated home_dir() function in Rust's standard library: https://github.com/rust-lang/rust/blob/master/src/libstd/sys/unix/os.rs#L579
|
||||||
|
// The same code is used by the dirs crate
|
||||||
|
unsafe fn fallback() -> Option<std::ffi::OsString> {
|
||||||
|
let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
|
||||||
|
n if n < 0 => 512 as usize,
|
||||||
|
n => n as usize,
|
||||||
|
};
|
||||||
|
let mut buf = Vec::with_capacity(amt);
|
||||||
|
let mut passwd: libc::passwd = std::mem::zeroed();
|
||||||
|
let mut result = std::ptr::null_mut();
|
||||||
|
match libc::getpwuid_r(
|
||||||
|
libc::getuid(),
|
||||||
|
&mut passwd,
|
||||||
|
buf.as_mut_ptr(),
|
||||||
|
buf.capacity(),
|
||||||
|
&mut result,
|
||||||
|
) {
|
||||||
|
0 if !result.is_null() => {
|
||||||
|
let ptr = passwd.pw_dir as *const _;
|
||||||
|
let bytes = std::ffi::CStr::from_ptr(ptr).to_bytes().to_vec();
|
||||||
|
Some(std::os::unix::ffi::OsStringExt::from_vec(bytes))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// To avoid the poorly managed dirs crate
|
/// To avoid the poorly managed dirs crate
|
||||||
|
|
|
@ -3197,3 +3197,51 @@ fn should_not_panic_on_no_stderr() {
|
||||||
);
|
);
|
||||||
output.unwrap();
|
output.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
#[test]
|
||||||
|
fn should_not_panic_on_undefined_home_environment_variable() {
|
||||||
|
let output = util::deno_cmd()
|
||||||
|
.current_dir(util::root_path())
|
||||||
|
.arg("run")
|
||||||
|
.arg("cli/tests/echo.ts")
|
||||||
|
.env_remove("HOME")
|
||||||
|
.stdout(std::process::Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.unwrap()
|
||||||
|
.wait_with_output()
|
||||||
|
.unwrap();
|
||||||
|
assert!(output.status.success());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_not_panic_on_undefined_deno_dir_environment_variable() {
|
||||||
|
let output = util::deno_cmd()
|
||||||
|
.current_dir(util::root_path())
|
||||||
|
.arg("run")
|
||||||
|
.arg("cli/tests/echo.ts")
|
||||||
|
.env_remove("DENO_DIR")
|
||||||
|
.stdout(std::process::Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.unwrap()
|
||||||
|
.wait_with_output()
|
||||||
|
.unwrap();
|
||||||
|
assert!(output.status.success());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
#[test]
|
||||||
|
fn should_not_panic_on_undefined_deno_dir_and_home_environment_variables() {
|
||||||
|
let output = util::deno_cmd()
|
||||||
|
.current_dir(util::root_path())
|
||||||
|
.arg("run")
|
||||||
|
.arg("cli/tests/echo.ts")
|
||||||
|
.env_remove("DENO_DIR")
|
||||||
|
.env_remove("HOME")
|
||||||
|
.stdout(std::process::Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.unwrap()
|
||||||
|
.wait_with_output()
|
||||||
|
.unwrap();
|
||||||
|
assert!(output.status.success());
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue