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}