diff --git a/src/check_release.rs b/src/check_release.rs index 56fa9456..c2092372 100644 --- a/src/check_release.rs +++ b/src/check_release.rs @@ -134,7 +134,7 @@ pub(super) fn run_check_release( ), )?; config - .verbose(|config| { + .log_verbose(|config| { config.shell_status( "Starting", format_args!( @@ -153,7 +153,7 @@ pub(super) fn run_check_release( RequiredSemverUpdate::Minor => "minor", }; config - .verbose(|config| { + .log_verbose(|config| { if config.is_stderr_tty() { colored!( config.stderr(), @@ -182,7 +182,7 @@ pub(super) fn run_check_release( if peeked.is_none() { config - .verbose(|config| { + .log_verbose(|config| { if config.is_stderr_tty() { write!(config.stderr(), "\r")?; } @@ -206,7 +206,7 @@ pub(super) fn run_check_release( queries_with_errors.push(QueryWithResults::new(query_id.as_str(), results_iter)); config - .verbose(|config| { + .log_verbose(|config| { if config.is_stderr_tty() { write!(config.stderr(), "\r")?; } @@ -251,58 +251,72 @@ pub(super) fn run_check_release( for query_with_results in queries_with_errors { let semver_query = &queries[query_with_results.name]; required_versions.push(semver_query.required_update); - colored_ln(config.stdout(), |w| { - colored!( - w, - "\n--- failure {}: {} ---\n", - &semver_query.id, - &semver_query.human_readable_name, - ) - }) - .expect("print failed"); + config + .log_info(|config| { + colored_ln(config.stdout(), |w| { + colored!( + w, + "\n--- failure {}: {} ---\n", + &semver_query.id, + &semver_query.human_readable_name, + ) + })?; + Ok(()) + }) + .expect("print failed"); if let Some(ref_link) = semver_query.reference_link.as_deref() { - colored_ln(config.stdout(), |w| { - colored!( - w, - "{}Description:{}\n{}\n{:>12} {}\n{:>12} {}\n", - bold!(true), - reset!(), - &semver_query.error_message, - "ref:", - ref_link, - "impl:", - format!( - "https://github.com/obi1kenobi/cargo-semver-checks/tree/v{}/src/lints/{}.ron", - crate_version!(), - semver_query.id, + config.log_info(|config| { + colored_ln(config.stdout(), |w| { + colored!( + w, + "{}Description:{}\n{}\n{:>12} {}\n{:>12} {}\n", + bold!(true), + reset!(), + &semver_query.error_message, + "ref:", + ref_link, + "impl:", + format!( + "https://github.com/obi1kenobi/cargo-semver-checks/tree/v{}/src/lints/{}.ron", + crate_version!(), + semver_query.id, + ) ) - ) + })?; + Ok(()) }) .expect("print failed"); } else { - colored_ln(config.stdout(), |w| { - colored!( - w, - "{}Description:{}\n{}\n{:>12} {}\n", - bold!(true), - reset!(), - &semver_query.error_message, - "impl:", - format!( - "https://github.com/obi1kenobi/cargo-semver-checks/tree/v{}/src/lints/{}.ron", - crate_version!(), - semver_query.id, + config.log_info(|config| { + colored_ln(config.stdout(), |w| { + colored!( + w, + "{}Description:{}\n{}\n{:>12} {}\n", + bold!(true), + reset!(), + &semver_query.error_message, + "impl:", + format!( + "https://github.com/obi1kenobi/cargo-semver-checks/tree/v{}/src/lints/{}.ron", + crate_version!(), + semver_query.id, + ) ) - ) + })?; + Ok(()) }) .expect("print failed"); } - colored_ln(config.stdout(), |w| { - colored!(w, "{}Failed in:{}", bold!(true), reset!(),) - }) - .expect("print failed"); + config + .log_info(|config| { + colored_ln(config.stdout(), |w| { + colored!(w, "{}Failed in:{}", bold!(true), reset!()) + })?; + Ok(()) + }) + .expect("print failed"); let start_instant = std::time::Instant::now(); for semver_violation_result in query_with_results.results { @@ -317,11 +331,15 @@ pub(super) fn run_check_release( .render_template(template, &pretty_result) .context("Error instantiating semver query template.") .expect("could not materialize template"); - colored_ln(config.stdout(), |w| colored!(w, " {}", message,)) + config + .log_info(|config| { + colored_ln(config.stdout(), |w| colored!(w, " {}", message,))?; + Ok(()) + }) .expect("print failed"); config - .extra_verbose(|config| { + .log_extra_verbose(|config| { colored_ln(config.stdout(), |w| { let serde_pretty = serde_json::to_string_pretty(&pretty_result) .expect("serde failed"); @@ -335,14 +353,20 @@ pub(super) fn run_check_release( }) .expect("print failed"); } else { - colored_ln(config.stdout(), |w| { - colored!( - w, - "{}\n", - serde_json::to_string_pretty(&pretty_result).expect("serde failed"), - ) - }) - .expect("print failed"); + config + .log_info(|config| { + colored_ln(config.stdout(), |w| { + colored!( + w, + "{}\n", + serde_json::to_string_pretty(&pretty_result) + .expect("serde failed"), + ) + }) + .expect("print failed"); + Ok(()) + }) + .expect("print failed"); } } total_duration += start_instant.elapsed(); diff --git a/src/config.rs b/src/config.rs index 93b5c55f..b688fca3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -69,11 +69,19 @@ impl GlobalConfig { self } + pub fn is_info(&self) -> bool { + self.level.is_some() && self.level.unwrap() >= log::Level::Info + } + pub fn is_verbose(&self) -> bool { - log::Level::Debug <= self.level.unwrap_or(log::Level::Error) + self.level.is_some() && self.level.unwrap() >= log::Level::Debug + } + + pub fn is_extra_verbose(&self) -> bool { + self.level.is_some() && self.level.unwrap() >= log::Level::Trace } - pub fn verbose( + pub fn log_verbose( &mut self, callback: impl Fn(&mut Self) -> anyhow::Result<()>, ) -> anyhow::Result<()> { @@ -83,15 +91,21 @@ impl GlobalConfig { Ok(()) } - pub fn is_extra_verbose(&self) -> bool { - log::Level::Trace <= self.level.unwrap_or(log::Level::Error) + pub fn log_extra_verbose( + &mut self, + callback: impl Fn(&mut Self) -> anyhow::Result<()>, + ) -> anyhow::Result<()> { + if self.is_extra_verbose() { + callback(self)?; + } + Ok(()) } - pub fn extra_verbose( + pub fn log_info( &mut self, callback: impl Fn(&mut Self) -> anyhow::Result<()>, ) -> anyhow::Result<()> { - if self.is_extra_verbose() { + if self.is_info() { callback(self)?; } Ok(()) @@ -117,25 +131,27 @@ impl GlobalConfig { color: termcolor::Color, justified: bool, ) -> anyhow::Result<()> { - use std::io::Write; - use termcolor::WriteColor; - - self.stderr().set_color( - termcolor::ColorSpec::new() - .set_fg(Some(color)) - .set_bold(true), - )?; - if justified { - write!(self.stderr(), "{status:>12}")?; - } else { - write!(self.stderr(), "{status}")?; - self.stderr() - .set_color(termcolor::ColorSpec::new().set_bold(true))?; - write!(self.stderr(), ":")?; + if self.is_info() { + use std::io::Write; + use termcolor::WriteColor; + + self.stderr().set_color( + termcolor::ColorSpec::new() + .set_fg(Some(color)) + .set_bold(true), + )?; + if justified { + write!(self.stderr(), "{status:>12}")?; + } else { + write!(self.stderr(), "{status}")?; + self.stderr() + .set_color(termcolor::ColorSpec::new().set_bold(true))?; + write!(self.stderr(), ":")?; + } + self.stderr().reset()?; + + writeln!(self.stderr(), " {message}")?; } - self.stderr().reset()?; - - writeln!(self.stderr(), " {message}")?; Ok(()) } @@ -157,3 +173,48 @@ impl GlobalConfig { self.shell_print("warning", message, termcolor::Color::Yellow, false) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log_level_info() { + let mut config = GlobalConfig::new(); + config = config.set_level(Some(log::Level::Info)); + + assert!(config.is_info()); + assert!(!config.is_verbose()); + assert!(!config.is_extra_verbose()); + } + + #[test] + fn test_log_level_debug() { + let mut config = GlobalConfig::new(); + config = config.set_level(Some(log::Level::Debug)); + + assert!(config.is_info()); + assert!(config.is_verbose()); + assert!(!config.is_extra_verbose()); + } + + #[test] + fn test_log_level_trace() { + let mut config = GlobalConfig::new(); + config = config.set_level(Some(log::Level::Trace)); + + assert!(config.is_info()); + assert!(config.is_verbose()); + assert!(config.is_extra_verbose()); + } + + #[test] + fn test_log_level_none() { + let mut config = GlobalConfig::new(); + config = config.set_level(None); + + assert!(!config.is_info()); + assert!(!config.is_verbose()); + assert!(!config.is_extra_verbose()); + } +} diff --git a/src/lib.rs b/src/lib.rs index badce97b..9316365b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -253,8 +253,10 @@ impl Check { self } - pub fn with_log_level(&mut self, log_level: log::Level) -> &mut Self { - self.log_level = Some(log_level); + /// Set the log level. + /// If not set or set to `None`, logging is disabled. + pub fn with_log_level(&mut self, log_level: Option) -> &mut Self { + self.log_level = log_level; self } @@ -354,9 +356,7 @@ impl Check { pub fn check_release(&self) -> anyhow::Result { let mut config = GlobalConfig::new().set_level(self.log_level); - let rustdoc_cmd = RustdocCommand::new() - .deps(false) - .silence(!config.is_verbose()); + let rustdoc_cmd = RustdocCommand::new().deps(false).silence(config.is_info()); // If both the current and baseline rustdoc are given explicitly as a file path, // we don't need to use the installed rustc, and this check can be skipped. @@ -461,7 +461,7 @@ impl Check { && metadata.workspace_members.len() > 1 && selected.publish == Some(vec![]); if is_implied { - config.verbose(|config| { + config.log_verbose(|config| { config.shell_status( "Skipping", format_args!("{crate_name} v{version} (current)"), diff --git a/src/main.rs b/src/main.rs index a64ecbb1..64cdad10 100644 --- a/src/main.rs +++ b/src/main.rs @@ -319,9 +319,9 @@ impl From for cargo_semver_checks::Check { if let Some(baseline) = custom_baseline { check.with_baseline(baseline); } - if let Some(log_level) = value.verbosity.log_level() { - check.with_log_level(log_level); - } + + check.with_log_level(value.verbosity.log_level()); + if let Some(release_type) = value.release_type { check.with_release_type(release_type); }