1use serde::{Deserialize, Serialize};
4use std::path::PathBuf;
5
6#[derive(Debug, Default, Serialize, Deserialize)]
7pub struct Config {
8 pub gitlab: Option<GitlabConfig>,
9}
10
11#[derive(Debug, Serialize, Deserialize)]
12pub struct GitlabConfig {
13 pub access_token: String,
14}
15
16pub fn config_path() -> Result<PathBuf, Box<dyn std::error::Error>> {
17 let config_dir = std::env::var("XDG_CONFIG_HOME")
18 .map(PathBuf::from)
19 .unwrap_or_else(|_| {
20 let home = std::env::var("HOME")
21 .unwrap_or_else(|_| ".".into());
22 PathBuf::from(home).join(".config")
23 });
24 Ok(config_dir.join("hs-relmon").join("config.toml"))
25}
26
27pub fn load() -> Result<Config, Box<dyn std::error::Error>> {
28 let path = config_path()?;
29 let contents = std::fs::read_to_string(&path)?;
30 Ok(toml::from_str(&contents)?)
31}
32
33pub fn save(config: &Config) -> Result<(), Box<dyn std::error::Error>> {
34 let path = config_path()?;
35 if let Some(parent) = path.parent() {
36 std::fs::create_dir_all(parent)?;
37 }
38 let contents = toml::to_string_pretty(config)?;
39 std::fs::write(&path, contents)?;
40 Ok(())
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn test_config_deserialize() {
49 let toml_str = r#"
50[gitlab]
51access_token = "glpat-abc123"
52"#;
53 let config: Config = toml::from_str(toml_str).unwrap();
54 assert_eq!(
55 config.gitlab.as_ref().unwrap().access_token,
56 "glpat-abc123"
57 );
58 }
59
60 #[test]
61 fn test_config_deserialize_no_gitlab() {
62 let config: Config = toml::from_str("").unwrap();
63 assert!(config.gitlab.is_none());
64 }
65
66 #[test]
67 fn test_config_serialize() {
68 let config = Config {
69 gitlab: Some(GitlabConfig {
70 access_token: "glpat-abc123".into(),
71 }),
72 };
73 let s = toml::to_string_pretty(&config).unwrap();
74 assert!(s.contains("[gitlab]"));
75 assert!(s.contains("access_token = \"glpat-abc123\""));
76 }
77
78 #[test]
79 fn test_config_roundtrip() {
80 let config = Config {
81 gitlab: Some(GitlabConfig {
82 access_token: "test-token".into(),
83 }),
84 };
85 let s = toml::to_string_pretty(&config).unwrap();
86 let parsed: Config = toml::from_str(&s).unwrap();
87 assert_eq!(
88 parsed.gitlab.unwrap().access_token,
89 "test-token"
90 );
91 }
92
93 #[test]
94 fn test_config_path() {
95 let path = config_path().unwrap();
96 assert!(path.ends_with("hs-relmon/config.toml"));
97 }
98}