cargo_hatch/settings/
global.rs

1use std::collections::{BTreeMap, HashMap, HashSet};
2
3use anyhow::Result;
4use camino::Utf8PathBuf;
5use serde::Deserialize;
6
7use crate::dirs::Utf8ProjectDirs;
8
9#[derive(Deserialize)]
10#[cfg_attr(test, derive(Debug, PartialEq))]
11pub struct Settings {
12    #[serde(default)]
13    pub git: Git,
14    #[serde(default)]
15    pub bookmarks: BTreeMap<String, Bookmark>,
16    #[serde(default)]
17    pub update_deps: bool,
18}
19
20#[derive(Default, Deserialize)]
21#[cfg_attr(test, derive(Debug, Eq, PartialEq))]
22pub struct Git {
23    pub ssh_key: Option<Utf8PathBuf>,
24}
25
26#[derive(Deserialize)]
27#[cfg_attr(test, derive(Debug, PartialEq))]
28pub struct Bookmark {
29    pub repository: String,
30    pub description: Option<String>,
31    pub folder: Option<Utf8PathBuf>,
32    #[serde(default)]
33    pub defaults: HashMap<String, DefaultSetting>,
34}
35
36#[derive(Deserialize)]
37#[cfg_attr(test, derive(Debug, PartialEq))]
38pub struct DefaultSetting {
39    pub value: DefaultValue,
40    pub skip_prompt: bool,
41}
42
43#[derive(Debug, Deserialize)]
44#[cfg_attr(test, derive(PartialEq))]
45#[serde(rename_all = "snake_case")]
46pub enum DefaultValue {
47    Bool(bool),
48    String(String),
49    Number(i64),
50    Float(f64),
51    List(String),
52    MultiList(HashSet<String>),
53}
54
55pub fn load(dirs: &Utf8ProjectDirs) -> Result<Settings> {
56    let buf = std::fs::read(dirs.config_dir().join("settings.toml"))?;
57    basic_toml::from_slice(&buf).map_err(Into::into)
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn defaults() {
66        let raw = r#"
67        update_deps = true
68
69        [git]
70        ssh_key = ".ssh/id_ed25519"
71
72        [bookmarks.server]
73        repository = "test"
74        description = "sample"
75        folder = "a/b/c"
76
77        [bookmarks.server.defaults]
78        test_bool = { value = { bool = true }, skip_prompt = false }
79        test_string = { value = { string = "value" }, skip_prompt = false }
80        test_number = { value = { number = 10 }, skip_prompt = false }
81        test_float = { value = { float = 2.5 }, skip_prompt = false }
82        test_list = { value = { list = "one" }, skip_prompt = true }
83        test_multi_list = { value = { multi_list = ["one", "two"] }, skip_prompt = true }
84    "#;
85        let expect = Settings {
86            git: Git {
87                ssh_key: Some(Utf8PathBuf::from(".ssh/id_ed25519")),
88            },
89            bookmarks: [(
90                "server".to_owned(),
91                Bookmark {
92                    repository: "test".to_owned(),
93                    description: Some("sample".to_owned()),
94                    folder: Some(Utf8PathBuf::from("a/b/c")),
95                    defaults: [
96                        (
97                            "test_bool".to_owned(),
98                            DefaultSetting {
99                                value: DefaultValue::Bool(true),
100                                skip_prompt: false,
101                            },
102                        ),
103                        (
104                            "test_string".to_owned(),
105                            DefaultSetting {
106                                value: DefaultValue::String("value".to_owned()),
107                                skip_prompt: false,
108                            },
109                        ),
110                        (
111                            "test_number".to_owned(),
112                            DefaultSetting {
113                                value: DefaultValue::Number(10),
114                                skip_prompt: false,
115                            },
116                        ),
117                        (
118                            "test_float".to_owned(),
119                            DefaultSetting {
120                                value: DefaultValue::Float(2.5),
121                                skip_prompt: false,
122                            },
123                        ),
124                        (
125                            "test_list".to_owned(),
126                            DefaultSetting {
127                                value: DefaultValue::List("one".to_owned()),
128                                skip_prompt: true,
129                            },
130                        ),
131                        (
132                            "test_multi_list".to_owned(),
133                            DefaultSetting {
134                                value: DefaultValue::MultiList(
135                                    ["one".to_owned(), "two".to_owned()].into_iter().collect(),
136                                ),
137                                skip_prompt: true,
138                            },
139                        ),
140                    ]
141                    .into_iter()
142                    .collect(),
143                },
144            )]
145            .into_iter()
146            .collect(),
147            update_deps: true,
148        };
149
150        let result = basic_toml::from_str::<Settings>(raw);
151        assert_eq!(expect, result.unwrap());
152    }
153}