Skip to main content

geekmagic_common/
config.rs

1use std::env;
2use std::fs;
3use std::path::{Path, PathBuf};
4
5use anyhow::{Context, Result};
6use serde::Deserialize;
7
8#[derive(Debug, Default, Deserialize, Clone)]
9pub struct AppConfig {
10    pub host: Option<String>,
11    pub daemon: Option<u64>,
12    pub with_disk: Option<bool>,
13}
14
15fn expand_home(path: &str) -> PathBuf {
16    if path == "~" {
17        return env::var("HOME")
18            .map(PathBuf::from)
19            .unwrap_or_else(|_| PathBuf::from(path));
20    }
21
22    if let Some(rest) = path.strip_prefix("~/") {
23        if let Ok(home) = env::var("HOME") {
24            return PathBuf::from(home).join(rest);
25        }
26    }
27
28    PathBuf::from(path)
29}
30
31pub fn default_config_path() -> PathBuf {
32    let home = env::var("HOME").unwrap_or_else(|_| ".".to_string());
33    PathBuf::from(home)
34        .join(".config")
35        .join("geekmagic-stats")
36        .join("config.toml")
37}
38
39pub fn load(path_override: Option<&str>) -> Result<AppConfig> {
40    let path = path_override
41        .map(expand_home)
42        .unwrap_or_else(default_config_path);
43    load_from_path(&path)
44}
45
46fn load_from_path(path: &Path) -> Result<AppConfig> {
47    if !path.exists() {
48        return Ok(AppConfig::default());
49    }
50
51    let raw = fs::read_to_string(path)
52        .with_context(|| format!("failed to read config at {}", path.display()))?;
53    toml::from_str(&raw).with_context(|| format!("failed to parse config at {}", path.display()))
54}