1use crate::error::RokError;
2use crate::schema::Options;
3use std::path::Path;
4
5#[derive(Debug)]
6pub struct Config {
7 pub options: Options,
8 pub cwd: std::path::PathBuf,
9 pub env: std::collections::HashMap<String, String>,
10}
11
12impl Config {
13 pub fn from_options(options: Options) -> Result<Self, RokError> {
14 let cwd_str = options.cwd.clone();
15 let cwd = Path::new(&cwd_str);
16
17 if !cwd.exists() {
18 return Err(RokError::startup(format!(
19 "Working directory does not exist: {}",
20 cwd_str
21 )));
22 }
23
24 if !cwd.is_dir() {
25 return Err(RokError::startup(format!(
26 "Working directory is not a directory: {}",
27 cwd_str
28 )));
29 }
30
31 let mut env = std::env::vars().collect::<std::collections::HashMap<_, _>>();
32 env.extend(options.env.clone());
33
34 Ok(Self {
35 options,
36 cwd: cwd.to_path_buf(),
37 env,
38 })
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use std::collections::HashMap;
46 use std::fs;
47 use tempfile::TempDir;
48
49 #[test]
50 fn test_config_from_options_valid() {
51 let temp_dir = TempDir::new().unwrap();
52 let options = Options {
53 cwd: temp_dir.path().to_string_lossy().to_string(),
54 stop_on_error: true,
55 timeout_ms: 30000,
56 env: HashMap::new(),
57 cache: false,
58 cache_dir: None,
59 incremental: false,
60 };
61
62 let config = Config::from_options(options);
63 assert!(config.is_ok());
64 let config = config.unwrap();
65 assert_eq!(config.cwd, temp_dir.path());
66 }
67
68 #[test]
69 fn test_config_from_options_nonexistent_dir() {
70 let options = Options {
71 cwd: "/nonexistent/path/that/does/not/exist".to_string(),
72 stop_on_error: true,
73 timeout_ms: 30000,
74 env: HashMap::new(),
75 cache: false,
76 cache_dir: None,
77 incremental: false,
78 };
79
80 let config = Config::from_options(options);
81 assert!(config.is_err());
82 let err = config.unwrap_err();
83 assert!(err.message.contains("Working directory does not exist"));
84 }
85
86 #[test]
87 fn test_config_from_options_file_not_dir() {
88 let temp_dir = TempDir::new().unwrap();
89 let file_path = temp_dir.path().join("test.txt");
90 fs::write(&file_path, "content").unwrap();
91
92 let options = Options {
93 cwd: file_path.to_string_lossy().to_string(),
94 stop_on_error: true,
95 timeout_ms: 30000,
96 env: HashMap::new(),
97 cache: false,
98 cache_dir: None,
99 incremental: false,
100 };
101
102 let config = Config::from_options(options);
103 assert!(config.is_err());
104 let err = config.unwrap_err();
105 assert!(err.message.contains("is not a directory"));
106 }
107
108 #[test]
109 fn test_config_merges_env_vars() {
110 let temp_dir = TempDir::new().unwrap();
111 let mut custom_env = HashMap::new();
112 custom_env.insert("CUSTOM_VAR".to_string(), "custom_value".to_string());
113
114 let options = Options {
115 cwd: temp_dir.path().to_string_lossy().to_string(),
116 stop_on_error: true,
117 timeout_ms: 30000,
118 env: custom_env,
119 cache: false,
120 cache_dir: None,
121 incremental: false,
122 };
123
124 let config = Config::from_options(options);
125 assert!(config.is_ok());
126 let config = config.unwrap();
127 assert_eq!(
128 config.env.get("CUSTOM_VAR"),
129 Some(&"custom_value".to_string())
130 );
131 }
132
133 #[test]
134 fn test_config_default_cwd() {
135 let options = Options::default();
136 assert_eq!(options.cwd, ".");
137 }
138}