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}