1use std::{error::Error, path::PathBuf};
2
3use crate::args::path_must_exist;
4
5pub const PATH_PROVIDED_ERROR: &str = "Path provided, does not exist: ";
6
7pub const WEIDU_LOG_MODE_ERROR: &str = r"
8Please provide a valid weidu logging setting, options are:
9--weidu-log-mode log X log output and details to X
10--weidu-log-mode autolog log output and details to WSETUP.DEBUG
11--weidu-log-mode logapp append to log instead of overwriting
12--weidu-log-mode log-extern also log output from commands invoked by WeiDU
13";
14
15#[derive(Debug, PartialEq, Clone)]
16pub enum LogOptions {
17 Log(PathBuf),
18 AutoLog,
19 LogAppend,
20 LogExternal,
21}
22
23impl TryFrom<&str> for LogOptions {
24 type Error = Box<dyn Error>;
25
26 fn try_from(value: &str) -> Result<Self, Self::Error> {
27 match value {
28 x if x.starts_with("log ") => {
29 if let Some((_, tail)) = value.split_once(' ') {
30 if let Ok(path) = path_must_exist(tail) {
31 #[cfg(not(target_os = "windows"))]
32 return Ok(LogOptions::Log(path.canonicalize()?));
33 #[cfg(windows)]
34 return Ok(LogOptions::Log(path));
35 }
36 return Err(format!("{} {:?}", PATH_PROVIDED_ERROR, tail).into());
37 }
38 Err(format!("{WEIDU_LOG_MODE_ERROR}, Provided {value}").into())
39 }
40 "autolog" => Ok(LogOptions::AutoLog),
41 "logapp" => Ok(LogOptions::LogAppend),
42 "log-extern" => Ok(LogOptions::LogExternal),
43 _ => Err(format!("{WEIDU_LOG_MODE_ERROR}, Provided {value}").into()),
44 }
45 }
46}
47
48impl LogOptions {
49 pub fn value_parser(arg: &str) -> Result<LogOptions, String> {
50 LogOptions::try_from(arg).map_err(|err| err.to_string())
51 }
52 pub fn to_args(&self, path: &str) -> Vec<String> {
53 match self {
54 LogOptions::LogAppend => vec!["--logapp".to_string()],
55 LogOptions::Log(path_buf) if path_buf.is_file() => vec![
56 "--log".to_string(),
57 path_buf
58 .as_os_str()
59 .to_str()
60 .unwrap_or_default()
61 .to_string(),
62 ],
63 LogOptions::Log(path_buf) => vec![
64 "--log".to_string(),
65 path_buf
66 .join(path)
67 .as_os_str()
68 .to_str()
69 .unwrap_or_default()
70 .to_string(),
71 ],
72 LogOptions::AutoLog => vec!["--autolog".to_string()],
73 LogOptions::LogExternal => vec!["--log-extern".to_string()],
74 }
75 }
76}
77
78#[cfg(test)]
79mod tests {
80
81 use super::*;
82 use pretty_assertions::assert_eq;
83
84 #[test]
85 fn test_parse_weidu_log_mode() -> Result<(), Box<dyn Error>> {
86 let tests = vec![
87 (
88 "log log",
89 Err("No such file or directory (os error 2)".to_string()),
90 ),
91 ("autolog", Ok(LogOptions::AutoLog)),
92 ("logapp", Ok(LogOptions::LogAppend)),
93 ("log-extern", Ok(LogOptions::LogExternal)),
94 ("", Err(format!("{WEIDU_LOG_MODE_ERROR}, Provided "))),
95 ];
96 for (test, expected) in tests {
97 let result = LogOptions::value_parser(test);
98 assert_eq!(
99 result, expected,
100 "Result {result:?} didn't match Expected {expected:?}",
101 );
102 }
103 Ok(())
104 }
105}