notes/
config.rs

1extern crate dirs;
2
3use crate::env::{Env, EnvImpl};
4use std::path::PathBuf;
5
6pub const NOTES_STORAGE_DIRECTORY: &str = "NOTES_STORAGE_DIRECTORY";
7
8pub struct Config {
9    pub storage_directory: PathBuf,
10    pub template_path: PathBuf,
11}
12
13impl<'a> Config {
14    pub fn new(env: &'a dyn Env) -> Self {
15        let storage_directory = Config::get_storage_path(env);
16        Config::from_path(&storage_directory)
17    }
18
19    pub fn from_path(path: &PathBuf) -> Self {
20        let storage_directory = path.clone();
21        let template_path: PathBuf = [storage_directory.to_str().unwrap(), ".template.md"].iter().collect();
22
23        Config {
24            storage_directory,
25            template_path,
26        }
27    }
28
29    fn get_storage_path(env: &'a dyn Env) -> PathBuf {
30        let env_path = env.get(NOTES_STORAGE_DIRECTORY).map(PathBuf::from);
31        let mut alternative = dirs::home_dir().unwrap_or_else(|| "/tmp".into());
32        alternative.push(".notes");
33
34        match env_path {
35            Ok(repository_path) => repository_path,
36            _ => alternative,
37        }
38    }
39}
40
41impl Default for Config {
42    fn default() -> Self {
43        Config::new(&EnvImpl::new())
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50    use crate::env::MockEnv;
51    use mockall::predicate::*;
52    use std::env::VarError;
53    use std::path::PathBuf;
54
55    #[test]
56    fn should_return_path_from_env_var() {
57        let mut mock_env = MockEnv::new();
58        mock_env
59            .expect_get()
60            .with(eq(NOTES_STORAGE_DIRECTORY))
61            .times(1)
62            .returning(|_| Ok("/path/to/dir".to_string()));
63
64        let config = Config::new(&mock_env);
65        assert_eq!(config.storage_directory, PathBuf::from("/path/to/dir"))
66    }
67
68    #[test]
69    fn should_return_path_from_home() {
70        let mut mock_env = MockEnv::new();
71        mock_env
72            .expect_get()
73            .with(eq(NOTES_STORAGE_DIRECTORY))
74            .times(1)
75            .returning(|_| Err(VarError::NotPresent));
76
77        let config = Config::new(&mock_env);
78        let path_str: String = config.storage_directory.to_str().unwrap().to_string();
79        assert!(
80            path_str.starts_with("/home") || path_str.starts_with("/root"),
81            format!("Path must start with /home actual={}", path_str)
82        );
83        assert!(path_str.ends_with(".notes"), format!("Path must end with .notes {}", path_str));
84    }
85}