use std::path::PathBuf;
use crate::config::ConfigEnv;
#[must_use]
pub fn config_home(env: &impl ConfigEnv) -> Option<PathBuf> {
if let Some(xdg) = env.var("XDG_CONFIG_HOME") {
return Some(PathBuf::from(xdg).join("midnight-manual"));
}
if let Some(home) = env.var("HOME") {
return Some(PathBuf::from(home).join(".config").join("midnight-manual"));
}
None
}
#[must_use]
pub fn auth_file_path(env: &impl ConfigEnv) -> Option<PathBuf> {
config_home(env).map(|p| p.join("auth.toml"))
}
#[must_use]
pub fn keys_dir(env: &impl ConfigEnv) -> Option<PathBuf> {
config_home(env).map(|p| p.join("keys"))
}
#[must_use]
pub fn private_key_path(env: &impl ConfigEnv, user_id: &str) -> Option<PathBuf> {
keys_dir(env).map(|p| p.join(format!("{user_id}.private")))
}
#[must_use]
pub fn telemetry_marker_path(env: &impl ConfigEnv) -> Option<PathBuf> {
config_home(env).map(|p| p.join("telemetry-disabled"))
}
#[must_use]
pub fn user_store_path(env: &impl ConfigEnv) -> Option<PathBuf> {
if let Some(p) = env.var("MIDNIGHT_MANUAL_USER_STORE") {
return Some(PathBuf::from(p));
}
config_home(env).map(|p| p.join("users.toml"))
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use super::*;
#[derive(Default)]
struct FakeEnv(HashMap<String, String>);
impl FakeEnv {
fn set(mut self, k: &str, v: &str) -> Self {
self.0.insert(k.into(), v.into());
self
}
}
impl ConfigEnv for FakeEnv {
fn var(&self, name: &str) -> Option<String> {
self.0.get(name).cloned()
}
}
#[test]
fn xdg_beats_home_for_config_dir() {
let env = FakeEnv::default()
.set("XDG_CONFIG_HOME", "/x")
.set("HOME", "/h");
assert_eq!(config_home(&env), Some(PathBuf::from("/x/midnight-manual")));
}
#[test]
fn home_fallback_for_config_dir() {
let env = FakeEnv::default().set("HOME", "/h");
assert_eq!(config_home(&env), Some(PathBuf::from("/h/.config/midnight-manual")),);
}
#[test]
fn none_when_no_env_at_all() {
let env = FakeEnv::default();
assert!(config_home(&env).is_none());
assert!(auth_file_path(&env).is_none());
assert!(keys_dir(&env).is_none());
assert!(private_key_path(&env, "aaron").is_none());
}
#[test]
fn auth_file_under_config_home() {
let env = FakeEnv::default().set("HOME", "/h");
assert_eq!(
auth_file_path(&env),
Some(PathBuf::from("/h/.config/midnight-manual/auth.toml")),
);
}
#[test]
fn private_key_path_uses_user_id() {
let env = FakeEnv::default().set("XDG_CONFIG_HOME", "/x");
assert_eq!(
private_key_path(&env, "aaron"),
Some(PathBuf::from("/x/midnight-manual/keys/aaron.private")),
);
}
#[test]
fn user_store_env_var_wins() {
let env = FakeEnv::default()
.set("MIDNIGHT_MANUAL_USER_STORE", "/etc/users.toml")
.set("XDG_CONFIG_HOME", "/x");
assert_eq!(user_store_path(&env), Some(PathBuf::from("/etc/users.toml")));
}
#[test]
fn telemetry_marker_under_config_home() {
let env = FakeEnv::default().set("XDG_CONFIG_HOME", "/x");
assert_eq!(
telemetry_marker_path(&env),
Some(PathBuf::from("/x/midnight-manual/telemetry-disabled")),
);
}
#[test]
fn telemetry_marker_none_without_env() {
let env = FakeEnv::default();
assert!(telemetry_marker_path(&env).is_none());
}
#[test]
fn user_store_xdg_fallback() {
let env = FakeEnv::default().set("XDG_CONFIG_HOME", "/x");
assert_eq!(user_store_path(&env), Some(PathBuf::from("/x/midnight-manual/users.toml")),);
}
}