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                        return Ok(LogOptions::Log(path.canonicalize()?));
32                    }
33                    return Err(format!("{} {:?}", PATH_PROVIDED_ERROR, tail).into());
34                }
35                Err(format!("{WEIDU_LOG_MODE_ERROR}, Provided {value}").into())
36            }
37            "autolog" => Ok(LogOptions::AutoLog),
38            "logapp" => Ok(LogOptions::LogAppend),
39            "log-extern" => Ok(LogOptions::LogExternal),
40            _ => Err(format!("{WEIDU_LOG_MODE_ERROR}, Provided {value}").into()),
41        }
42    }
43}
44
45impl From<String> for LogOptions {
46    fn from(value: String) -> Self {
47        LogOptions::try_from(value.as_str()).unwrap()
48    }
49}
50
51impl LogOptions {
52    pub fn value_parser(arg: &str) -> Result<LogOptions, String> {
53        LogOptions::try_from(arg).map_err(|err| err.to_string())
54    }
55    pub fn to_string(&self, path: &str) -> String {
56        match self {
57            LogOptions::Log(path_buf) if path_buf.is_file() => {
58                format!(
59                    "--log {}",
60                    path_buf.as_os_str().to_str().unwrap_or_default()
61                )
62            }
63            LogOptions::Log(path_buf) => {
64                format!(
65                    "--log {}",
66                    path_buf.join(path).as_os_str().to_str().unwrap_or_default()
67                )
68            }
69            LogOptions::AutoLog => "--autolog".to_string(),
70            LogOptions::LogAppend => "--logapp".to_string(),
71            LogOptions::LogExternal => "--log-extern".to_string(),
72        }
73    }
74}
75
76#[cfg(test)]
77mod tests {
78
79    use super::*;
80    use pretty_assertions::assert_eq;
81
82    #[test]
83    fn test_parse_weidu_log_mode() -> Result<(), Box<dyn Error>> {
84        let tests = vec![
85            (
86                "log log",
87                Err("No such file or directory (os error 2)".to_string()),
88            ),
89            ("autolog", Ok(LogOptions::AutoLog)),
90            ("logapp", Ok(LogOptions::LogAppend)),
91            ("log-extern", Ok(LogOptions::LogExternal)),
92            ("", Err(format!("{WEIDU_LOG_MODE_ERROR}, Provided "))),
93        ];
94        for (test, expected) in tests {
95            let result = LogOptions::value_parser(test);
96            assert_eq!(
97                result, expected,
98                "Result {result:?} didn't match Expected {expected:?}",
99            );
100        }
101        Ok(())
102    }
103}