config/
log_options.rs

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}