From 5ea52fdf0e6d5c571d20c1dbf3fadac3a60afa08 Mon Sep 17 00:00:00 2001 From: Steppy Date: Mon, 16 Dec 2024 14:34:40 +0100 Subject: [PATCH 1/6] Add basic logger --- src/logger.rs | 35 +++++++++++++++++++++++++++++++++++ src/main.rs | 4 ++++ 2 files changed, 39 insertions(+) create mode 100644 src/logger.rs diff --git a/src/logger.rs b/src/logger.rs new file mode 100644 index 0000000..a3d9a92 --- /dev/null +++ b/src/logger.rs @@ -0,0 +1,35 @@ +#[derive(Debug, Default)] +pub struct Logger { + pub quiet: bool, +} + +impl Logger { + pub fn info(&self, message: impl ToString) { + if self.quiet { + return; + } + println!("{}", message.to_string()); + } +} + +#[macro_export] +macro_rules! log { + ($logger:expr, $level:ident, $($args:tt)*) => { + $logger.$level(format!($($args)*)); + }; + ($logger:expr, $($args:tt)*) => { + log!($logger, info, $($args)*); + } +} + +#[cfg(test)] +mod test { + use crate::logger::Logger; + + #[test] + #[ignore] + fn syntax_test() { + let logger = Logger { quiet: false }; + log!(logger, "Foo {}", "bar"); + } +} diff --git a/src/main.rs b/src/main.rs index 87f3bd0..2f95742 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,9 +2,11 @@ mod action; mod file; mod os_string_builder; mod server; +mod logger; use crate::action::{Action, FileAction, ServerActions}; use crate::file::{FileMatcher, FileNameInfo}; +use crate::logger::Logger; use crate::os_string_builder::ReplaceWithOsStr; use clap::{Parser, Subcommand, ValueEnum}; use lazy_regex::{lazy_regex, Lazy, Regex}; @@ -109,6 +111,8 @@ enum OldVersionPolicy { fn main() -> Result<(), String> { let args = Args::parse(); + + let logger = Logger { quiet: false }; let mut configured_servers = LazyCell::new(parse_server_configuration_from_env); let servers = args -- 2.34.1 From 058830e510d01735d5e7e907f1e3df1ac1252e51 Mon Sep 17 00:00:00 2001 From: Leonard Steppy Date: Mon, 16 Dec 2024 15:41:15 +0100 Subject: [PATCH 2/6] Refactor logger module --- src/logger.rs | 31 +++++++++++++++++++++++++------ src/main.rs | 2 +- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/logger.rs b/src/logger.rs index a3d9a92..29fc31e 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -1,15 +1,34 @@ #[derive(Debug, Default)] pub struct Logger { - pub quiet: bool, + pub level: LogLevel, +} + +macro_rules! define_log_function { + ($name:ident, $level:ident) => { + pub fn $name(&self, message: S) where S: ToString { + self.log(LogLevel::$level, message.to_string()); + } + }; } impl Logger { - pub fn info(&self, message: impl ToString) { - if self.quiet { - return; + pub fn log(&self, level: LogLevel, message: S) where S: ToString { + if level >= self.level { + println!("{}", message.to_string()); } - println!("{}", message.to_string()); } + + define_log_function!(info, Info); + define_log_function!(debug, Debug); + define_log_function!(error, Error); +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)] +pub enum LogLevel { + Debug, + #[default] + Info, + Error, } #[macro_export] @@ -29,7 +48,7 @@ mod test { #[test] #[ignore] fn syntax_test() { - let logger = Logger { quiet: false }; + let logger = Logger::default(); log!(logger, "Foo {}", "bar"); } } diff --git a/src/main.rs b/src/main.rs index 2f95742..a33f187 100644 --- a/src/main.rs +++ b/src/main.rs @@ -112,7 +112,7 @@ enum OldVersionPolicy { fn main() -> Result<(), String> { let args = Args::parse(); - let logger = Logger { quiet: false }; + let logger = Logger::default(); let mut configured_servers = LazyCell::new(parse_server_configuration_from_env); let servers = args -- 2.34.1 From c25e0264b4cc69a59796acef25f4e4462fc393cb Mon Sep 17 00:00:00 2001 From: Leonard Steppy Date: Mon, 16 Dec 2024 15:48:05 +0100 Subject: [PATCH 3/6] Add log level parameters to CLI (untested) --- src/logger.rs | 6 ++++-- src/main.rs | 11 ++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/logger.rs b/src/logger.rs index 29fc31e..89226b6 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -1,3 +1,5 @@ +use clap::ValueEnum; + #[derive(Debug, Default)] pub struct Logger { pub level: LogLevel, @@ -17,13 +19,13 @@ impl Logger { println!("{}", message.to_string()); } } - + define_log_function!(info, Info); define_log_function!(debug, Debug); define_log_function!(error, Error); } -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default, ValueEnum)] pub enum LogLevel { Debug, #[default] diff --git a/src/main.rs b/src/main.rs index a33f187..996482a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ mod logger; use crate::action::{Action, FileAction, ServerActions}; use crate::file::{FileMatcher, FileNameInfo}; -use crate::logger::Logger; +use crate::logger::{LogLevel, Logger}; use crate::os_string_builder::ReplaceWithOsStr; use clap::{Parser, Subcommand, ValueEnum}; use lazy_regex::{lazy_regex, Lazy, Regex}; @@ -43,6 +43,15 @@ struct Args { /// The ssh names and optionally home directories of the servers to perform the action on #[arg(num_args = 1.., value_parser = ServerReference::from_str)] servers: Vec, + /// How verbose logging output should be + #[arg(long, conflicts_with_all = ["quiet", "info"], default_value = "info")] + log_level: Option, + /// Only log errors + #[arg(short, long, default_value = "false")] + quiet: bool, + /// Log additional debugging info + #[arg(short='v', long, default_value = "false")] + info: bool, } #[derive(Subcommand, Debug)] -- 2.34.1 From 7f3adc9bc267b9b2fc9f2b89640e36bd424ed84c Mon Sep 17 00:00:00 2001 From: Leonard Steppy Date: Tue, 17 Dec 2024 05:38:39 +0100 Subject: [PATCH 4/6] fix --quit not conflicting with --info and use default value for log level --- src/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 996482a..54ea392 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,10 +44,10 @@ struct Args { #[arg(num_args = 1.., value_parser = ServerReference::from_str)] servers: Vec, /// How verbose logging output should be - #[arg(long, conflicts_with_all = ["quiet", "info"], default_value = "info")] - log_level: Option, + #[arg(long, default_value = "info", conflicts_with_all = ["quiet", "info"])] + log_level: LogLevel, /// Only log errors - #[arg(short, long, default_value = "false")] + #[arg(short, long, default_value = "false", conflicts_with_all = ["info"])] quiet: bool, /// Log additional debugging info #[arg(short='v', long, default_value = "false")] -- 2.34.1 From 4a3fd978a4ed054f313cf526a5c2ec4b76c0bb2c Mon Sep 17 00:00:00 2001 From: Leonard Steppy Date: Tue, 17 Dec 2024 05:49:37 +0100 Subject: [PATCH 5/6] fix --quit not conflicting with --info and use default value for log level --- src/main.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 54ea392..29d4982 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,8 @@ mod action; mod file; +mod logger; mod os_string_builder; mod server; -mod logger; use crate::action::{Action, FileAction, ServerActions}; use crate::file::{FileMatcher, FileNameInfo}; @@ -50,7 +50,7 @@ struct Args { #[arg(short, long, default_value = "false", conflicts_with_all = ["info"])] quiet: bool, /// Log additional debugging info - #[arg(short='v', long, default_value = "false")] + #[arg(short = 'v', long, default_value = "false")] info: bool, } @@ -120,8 +120,17 @@ enum OldVersionPolicy { fn main() -> Result<(), String> { let args = Args::parse(); - - let logger = Logger::default(); + + let logger = Logger { + //all the below options are conflicting with each other so an if else is fine + level: if args.quiet { + LogLevel::Error + } else if args.info { + LogLevel::Debug + } else { + args.log_level + }, + }; let mut configured_servers = LazyCell::new(parse_server_configuration_from_env); let servers = args -- 2.34.1 From b88fabb7251ea8060abc74757fa912bd3e785b55 Mon Sep 17 00:00:00 2001 From: Leonard Steppy Date: Tue, 17 Dec 2024 06:02:25 +0100 Subject: [PATCH 6/6] replace print calls with log calls --- src/main.rs | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/main.rs b/src/main.rs index 29d4982..b9ec631 100644 --- a/src/main.rs +++ b/src/main.rs @@ -158,11 +158,7 @@ fn main() -> Result<(), String> { no_confirm, file_name, } => { - if servers.is_empty() { - println!("Please provide some servers to upload to. See --help"); - return Ok(()); - } - + require_non_empty_servers(&servers)?; start_ssh_agent()?; let file_name_info = @@ -248,13 +244,13 @@ fn main() -> Result<(), String> { }) .collect::, String>>()?; - println!("The following actions will be performed:"); + log!(logger, "The following actions will be performed: "); for server_actions in &actions { - println!("{server_actions}"); + log!(logger, "{server_actions}"); } if !no_confirm { - print!("Continue? [Y|n] "); + log!(logger, "Continue? [Y|n] "); std::io::stdout().flush().expect("failed to flush stdout"); let mut buffer = String::new(); std::io::stdin() @@ -262,7 +258,7 @@ fn main() -> Result<(), String> { .expect("failed to read stdin"); match buffer.to_lowercase().trim() { "n" | "no" => { - println!("Aborting..."); + log!(logger, "Aborting..."); return Ok(()); } _ => {} @@ -271,7 +267,7 @@ fn main() -> Result<(), String> { for server_actions in actions { let server = server_actions.server; - println!("Performing actions on {}...", server.ssh_name); + log!(logger, "Performing actions on {}...", server.ssh_name); for file_action in server_actions.actions { match file_action.kind { Action::Add | Action::Replace => { @@ -312,12 +308,13 @@ fn main() -> Result<(), String> { } } - println!("Done!"); + log!(logger, "Done!"); } Command::Command { command } => { start_ssh_agent()?; + require_non_empty_servers(&servers)?; for server in servers { - println!("Running command on '{}'...", server.ssh_name); + log!(logger, "Running command on '{}'...", server.ssh_name); ShellCmd::new("ssh") .arg(server.ssh_name) .arg(osf!("cd ") + server.server_directory_path + "; " + &command) @@ -326,7 +323,7 @@ fn main() -> Result<(), String> { .wait() .map_err(|e| format!("failed to wait for ssh command completion: {e}"))?; } - println!("Done!"); + log!(logger, "Done!"); } Command::Editor { file, @@ -353,16 +350,17 @@ fn main() -> Result<(), String> { .any(|entry| entry.file_name() == file_name) { return Err(format!( - "A file with the name {} already exists in {}. You can override it with --override", + "A file with the name {} already exists in {}. You can override it with --override or -f", file_name.to_string_lossy(), working_directory.to_string_lossy() )); } + require_non_empty_servers(&servers)?; start_ssh_agent()?; for server in servers { - println!("Downloading file from {}...", server.ssh_name); + log!(logger, "Downloading file from {}...", server.ssh_name); ShellCmd::new("scp") .arg(osf!(&server.ssh_name) + ":" + server.server_directory_path.join(&file)) .arg(&working_directory) @@ -390,13 +388,21 @@ fn main() -> Result<(), String> { .map_err(|e| format!("failed to upload file again: {e}"))?; } - println!("Done!"); + log!(logger, "Done!"); } } Ok(()) } +fn require_non_empty_servers(servers: &[Server]) -> Result<(), String> { + if servers.is_empty() { + Err("You did not provide any servers for this operation. Please see --help".to_string()) + } else { + Ok(()) + } +} + fn start_ssh_agent() -> Result<(), String> { //start the ssh agent let agent_output = ShellCmd::new("ssh-agent") -- 2.34.1