Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch from termcolor to anstream and anstyle #737

Merged
merged 20 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 2 additions & 27 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ serde = { version = "1.0.185", features = ["derive"] }
semver = "1.0.12"
handlebars = "5.1.0"
atty = "0.2.14"
termcolor = "1.1.3"
termcolor_output = "1.0.1"
cargo_metadata = "0.18.1"
clap-cargo = { version = "0.14.0", features = ["cargo_metadata"] }
ignore = "0.4.18"
Expand All @@ -45,6 +43,8 @@ directories = "5.0.1"
sha2 = "0.10.6"
rustc_version = "0.4.0"
rayon = "1.8.0"
anstyle = "1.0.6"
anstream = "0.6.13"

[dev-dependencies]
assert_cmd = "2.0"
Expand Down
173 changes: 73 additions & 100 deletions src/check_release.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::{collections::BTreeMap, sync::Arc, time::Instant};

use anstream::{eprintln, println};
use anstyle::{AnsiColor, Color, Reset, Style};

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

use anyhow::Context;
use clap::crate_version;
use itertools::Itertools;
use rayon::prelude::*;
use termcolor::Color;
use termcolor_output::{colored, colored_ln};
use trustfall::TransparentValue;
use trustfall_rustdoc::{VersionedCrate, VersionedIndexedCrate, VersionedRustdocAdapter};

Expand Down Expand Up @@ -157,39 +158,35 @@ pub(super) fn run_check_release(
let mut results_with_errors = vec![];
for (semver_query, time_to_decide, results) in all_results {
config
.log_verbose(|config| {
.log_verbose(|_| {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the callbacks will need config anymore, so we could (1) make the methods log_* take only &self if we go with this architecture, (2) move the shell_print_* methods to (associated) functions, and/or (3) remove the config parameter from the closure argument

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be a good idea to let the config variable carry explicit Box<dyn std::io::Write> fields for stdout and stderr, and pass them here.

Imagine a user is using cargo-semver-checks as a library. It's a bit strange if a library is printing to it's parent program's stdout/stderr, right? It would be nice if the parent program could configure where and how it wants the output printed, and then decide by itself whether to actually put it on stdout/stderr.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a little bit lost. When someone uses cargo-semver-checks as a library, they won't configure a separate stdout/stderr for logging, right? Do you mean running a child process?

@epage IIRC, anstyle takes care of parallel printing, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imagine a user is using cargo-semver-checks as a library. It's a bit strange if a library is printing to it's parent program's stdout/stderr, right? It would be nice if the parent program could configure where and how it wants the output printed, and then decide by itself whether to actually put it on stdout/stderr.

On main branch, I don't think there's a mechanism to set the output streams programmatically. Is that something we want? I can add it in this PR, or a different one.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they won't configure a separate stdout/stderr for logging

Not configure separate stdout/stderr, just give them the option to redirect the cargo-semver-checks-as-library output to a buffer (or drop it altogether) instead of having it printed to their app's stdout/stderr.

I can add it in this PR, or a different one.

Not worth adding here, let's optimize this PR for being easy to review and merge. We can add that in the future, I just wanted to not remove that option from us. If this PR can make sure to print to the configured Box<dyn Write> values (or whatever other representation is best), we can handle the rest later.

let category = match semver_query.required_update {
RequiredSemverUpdate::Major => "major",
RequiredSemverUpdate::Minor => "minor",
};
if results.is_empty() {
colored_ln(config.stderr(), |w| {
colored!(
w,
"{}{}{:>12}{} [{:>8.3}s] {:^18} {}",
fg!(Some(Color::Green)),
bold!(true),
"PASS",
reset!(),
time_to_decide.as_secs_f32(),
category,
semver_query.id,
)
})?;
eprintln!(
"{}{:>12}{} [{:8.3}s] {:^18} {}",
Style::new()
.fg_color(Some(Color::Ansi(AnsiColor::Green)))
.bold(),
"PASS",
Reset,
time_to_decide.as_secs_f32(),
category,
semver_query.id
);
} else {
colored_ln(config.stderr(), |w| {
colored!(
w,
"{}{}{:>12}{} [{:>8.3}s] {:^18} {}",
fg!(Some(Color::Red)),
bold!(true),
"FAIL",
reset!(),
time_to_decide.as_secs_f32(),
category,
semver_query.id,
)
})?;
eprintln!(
"{}{:>12}{} [{:>8.3}s] {:^18} {}",
Style::new()
.fg_color(Some(Color::Ansi(AnsiColor::Red)))
.bold(),
"FAIL",
Reset,
time_to_decide.as_secs_f32(),
category,
semver_query.id
);
}
Ok(())
})
Expand All @@ -211,7 +208,7 @@ pub(super) fn run_check_release(
results_with_errors.len(),
skipped_queries,
),
Color::Red,
Color::Ansi(AnsiColor::Red),
true,
)
.expect("print failed");
Expand All @@ -221,68 +218,54 @@ pub(super) fn run_check_release(
for (semver_query, results) in results_with_errors {
required_versions.push(semver_query.required_update);
config
.log_info(|config| {
colored_ln(config.stdout(), |w| {
colored!(
w,
"\n--- failure {}: {} ---\n",
&semver_query.id,
&semver_query.human_readable_name,
)
})?;
.log_info(|_| {
println!(
"\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() {
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,
)
config.log_info(|_| {
println!("{}Description:{}\n{}\n{:>12} {}\n{:>12} {}\n",
Style::new().bold(), 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 {
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,
)
config.log_info(|_| {
println!(
"{}Description:{}\n{}\n{:>12} {}\n",
Style::new().bold(),
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");
}

config
.log_info(|config| {
colored_ln(config.stdout(), |w| {
colored!(w, "{}Failed in:{}", bold!(true), reset!())
})?;
.log_info(|_| {
println!("{}Failed in:{}", Style::new().bold(), Reset);
Ok(())
})
.expect("print failed");
Expand All @@ -300,38 +283,28 @@ pub(super) fn run_check_release(
.context("Error instantiating semver query template.")
.expect("could not materialize template");
config
.log_info(|config| {
colored_ln(config.stdout(), |w| colored!(w, " {}", message,))?;
.log_info(|_| {
println!(" {}", message);
Ok(())
})
.expect("print failed");

config
.log_extra_verbose(|config| {
colored_ln(config.stdout(), |w| {
let serde_pretty = serde_json::to_string_pretty(&pretty_result)
.expect("serde failed");
let indented_serde = serde_pretty
.split('\n')
.map(|line| format!(" {line}"))
.join("\n");
colored!(w, " lint rule output values:\n{}", indented_serde)
})
.map_err(|e| e.into())
.log_extra_verbose(|_| {
let serde_pretty =
serde_json::to_string_pretty(&pretty_result).expect("serde failed");
let indented_serde = serde_pretty
.split('\n')
.map(|line| format!(" {line}"))
.join("\n");
println!("\tlint rule output values:\n{}", indented_serde);
Ok(())
})
.expect("print failed");
} else {
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");
.log_info(|_| {
println!("{}\n", serde_json::to_string_pretty(&pretty_result)?);
Ok(())
})
.expect("print failed");
Expand Down Expand Up @@ -362,7 +335,7 @@ pub(super) fn run_check_release(
.filter(|x| *x == &RequiredSemverUpdate::Minor)
.count(),
),
Color::Red,
Color::Ansi(AnsiColor::Red),
true,
)
.expect("print failed");
Expand All @@ -382,7 +355,7 @@ pub(super) fn run_check_release(
queries_to_run.len(),
skipped_queries,
),
Color::Green,
Color::Ansi(AnsiColor::Green),
true,
)
.expect("print failed");
Expand Down
Loading
Loading