1use super::error::ConfigError;
4use std::path::PathBuf;
5
6#[derive(Debug, Clone)]
12pub struct AppPaths {
13 pub config_file: PathBuf,
15 pub cache_dir: PathBuf,
17 pub state_dir: PathBuf,
19}
20
21impl AppPaths {
22 pub fn resolve() -> Result<Self, ConfigError> {
32 let config_file = dirs::config_dir().map_or_else(
33 || PathBuf::from("config.toml"),
34 |d| d.join("remendo").join("config.toml"),
35 );
36
37 let cache_dir = dirs::cache_dir().map_or_else(
38 || PathBuf::from(".cache").join("remendo"),
39 |d| d.join("remendo"),
40 );
41
42 let state_dir = dirs::state_dir().map_or_else(
43 || PathBuf::from(".local").join("state").join("remendo"),
44 |d| d.join("remendo"),
45 );
46
47 Ok(Self {
48 config_file,
49 cache_dir,
50 state_dir,
51 })
52 }
53}
54
55#[cfg(test)]
56#[allow(clippy::expect_used)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn resolve_produces_paths() {
62 let paths = AppPaths::resolve().expect("resolve paths");
63 assert!(
64 paths.config_file.to_string_lossy().ends_with("config.toml"),
65 "config_file should end with config.toml, got: {:?}",
66 paths.config_file
67 );
68 }
69
70 #[test]
71 fn resolve_config_under_xdg_dir() {
72 let paths = AppPaths::resolve().expect("resolve paths");
73 if dirs::config_dir().is_some() {
76 let path_str = paths.config_file.to_string_lossy();
77 assert!(
78 path_str.contains("remendo"),
79 "config path should contain 'remendo' subdir, got: {path_str}"
80 );
81 }
82 }
83
84 #[test]
85 fn resolve_cache_under_xdg_dir() {
86 let paths = AppPaths::resolve().expect("resolve paths");
87 if dirs::cache_dir().is_some() {
88 let path_str = paths.cache_dir.to_string_lossy();
89 assert!(
90 path_str.contains("remendo"),
91 "cache path should contain 'remendo' subdir, got: {path_str}"
92 );
93 }
94 }
95}