summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaayan Hanin <maayan.asa.hanin@gmail.com>2020-07-13 19:24:54 +0300
committerGitHub <noreply@github.com>2020-07-13 18:24:54 +0200
commitd619e3c7ac8618c5cd30fcc314db2ef994c604e4 (patch)
treedfd1f1dbe33f438b81ad5fb52c55dabd4f76c46d
parent11560387bb056098c55049db22c63550358c953a (diff)
fix(cli): don't panic when no "HOME" env var is set (#6728)
-rw-r--r--cli/deno_dir.rs47
-rw-r--r--cli/tests/integration_tests.rs48
2 files changed, 84 insertions, 11 deletions
diff --git a/cli/deno_dir.rs b/cli/deno_dir.rs
index 076692621..49f76c7d2 100644
--- a/cli/deno_dir.rs
+++ b/cli/deno_dir.rs
@@ -14,24 +14,22 @@ pub struct DenoDir {
impl DenoDir {
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 {
if root.is_absolute() {
root
} else {
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 {
- default
+ panic!("Could not set the Deno root directory")
};
assert!(root.is_absolute());
let gen_path = root.join("gen");
@@ -64,8 +62,35 @@ mod dirs {
pub fn home_dir() -> Option<PathBuf> {
std::env::var_os("HOME")
.and_then(|h| if h.is_empty() { None } else { Some(h) })
+ .or_else(|| unsafe { fallback() })
.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
diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs
index ec871d927..e93edc79f 100644
--- a/cli/tests/integration_tests.rs
+++ b/cli/tests/integration_tests.rs
@@ -3197,3 +3197,51 @@ fn should_not_panic_on_no_stderr() {
);
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());
+}