1use std::{
7 fs::create_dir_all,
8 path::{Path, PathBuf},
9};
10
11use git2::Repository;
12
13use crate::errors::DiaryError;
14
15pub struct InitOptions {
17 pub path: PathBuf,
19 pub prefix: Option<String>,
21 pub git_repo: bool,
23}
24
25enum InitStatus {
26 UseConfig(PathBuf),
27 UseOpt(PathBuf),
28}
29
30fn establish_path(opts: &InitOptions, potential_path: &Path) -> Result<InitStatus, DiaryError> {
42 if potential_path == PathBuf::from("") {
43 let diary_path = opts.path.join("diary");
44 if diary_path.exists() {
45 return Err(DiaryError::ExistsHere);
46 }
47 Ok(InitStatus::UseOpt(diary_path))
48 } else if potential_path.exists() {
49 Err(DiaryError::ExistsElsewhere)
50 } else {
51 Ok(InitStatus::UseConfig(potential_path.to_path_buf()))
52 }
53}
54
55pub fn init(opts: &InitOptions, potential_path: &Path) -> Result<PathBuf, DiaryError> {
67 let init_status = establish_path(opts, potential_path);
68 let path = match init_status? {
69 InitStatus::UseConfig(path) => {
70 print!("It appears the config file already has a diary path set. ");
71 println!("Creating a diary folder here: {:?}", path);
72 path
73 }
74 InitStatus::UseOpt(path) => {
75 println!("Creating a diary folder.");
76 path
77 }
78 };
79 let path = match create_dir_all(&path) {
80 Ok(_) => path,
81 Err(e) => return Err(DiaryError::from(e)), };
83
84 if opts.git_repo {
85 match Repository::init(&path) {
86 Ok(_) => (),
87 Err(e) => return Err(DiaryError::from(e)), };
89 };
90 Ok(path)
91}
92
93#[cfg(test)]
94mod tests {
95 use std::fs::create_dir_all;
96
97 use super::{init, InitOptions};
98 use crate::{config::Config, ops::testing};
99
100 #[test]
101 fn blank_config_valid_path() {
102 let dir = testing::temp_path();
103 let diary_dir = dir.join("diary");
104 let opts = InitOptions {
105 path: dir,
106 prefix: None,
107 git_repo: false,
108 };
109 let config = Config::default();
110
111 init(&opts, config.diary_path()).unwrap();
112
113 assert!(diary_dir.exists());
114 }
115
116 #[test]
117 fn blank_config_invalid_path() {
118 let dir = testing::temp_path();
119 let diary_dir = dir.join("diary");
120 let opts = InitOptions {
121 path: dir,
122 prefix: None,
123 git_repo: false,
124 };
125 let config = Config::default();
126 create_dir_all(diary_dir).unwrap();
127
128 init(&opts, config.diary_path()).expect_err("No error produced.");
129 }
130
131 #[test]
132 fn filled_config_non_existing_path() {
133 let dir = testing::temp_path();
134 let diary_dir = dir.join("diary");
135
136 let config = Config::builder().diary_path(diary_dir.clone()).build();
137
138 let opts = InitOptions {
139 path: testing::temp_path(),
140 prefix: None,
141 git_repo: false,
142 };
143
144 init(&opts, config.diary_path()).unwrap();
145
146 assert!(diary_dir.exists());
147 }
148
149 #[test]
150 fn filled_config_existing_path() {
151 let dir = testing::temp_path();
152 let diary_dir = dir.join("diary");
153 let config = Config::builder().diary_path(diary_dir.clone()).build();
154
155 let opts = InitOptions {
156 path: testing::temp_path(),
157 prefix: None,
158 git_repo: false,
159 };
160
161 create_dir_all(diary_dir).unwrap();
162
163 init(&opts, config.diary_path()).expect_err("No error produced.");
164 }
165
166 #[test]
167 fn blank_config_valid_path_git_repo() {
168 let dir = testing::temp_path();
169 let mut diary_dir = dir.join("diary");
170 let opts = InitOptions {
171 path: dir,
172 prefix: None,
173 git_repo: true,
174 };
175 let config = Config::default();
176
177 init(&opts, config.diary_path()).unwrap();
178
179 diary_dir.push(".git");
180
181 assert!(diary_dir.exists());
182 }
183
184 #[test]
185 fn filled_config_non_existing_path_git_repo() {
186 let dir = testing::temp_path();
187 let mut diary_dir = dir.join("diary");
188 let config = Config::builder().diary_path(diary_dir.clone()).build();
189
190 let opts = InitOptions {
191 path: testing::temp_path(),
192 prefix: None,
193 git_repo: true,
194 };
195
196 init(&opts, config.diary_path()).unwrap();
197
198 diary_dir.push(".git");
199
200 assert!(diary_dir.exists());
201 }
202
203 #[test]
204 fn filled_config_existing_path_git_repo() {
205 let dir = testing::temp_path();
206 let diary_dir = dir.join("diary");
207 let config = Config::builder().diary_path(diary_dir.clone()).build();
208
209 let opts = InitOptions {
210 path: testing::temp_path(),
211 prefix: None,
212 git_repo: true,
213 };
214
215 create_dir_all(diary_dir).unwrap();
216
217 init(&opts, config.diary_path()).expect_err("No error produced.");
218 }
219}