From 856e480cb79de75d2be0aabe72bdcd7bb4e3c38e Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 29 May 2025 13:20:30 -0400 Subject: [PATCH] cli: Don't emit ANSI codes to stderr It seems the tracing crate is broken in this respect. Digging through best practices, `anstream` is used by clap and looks sane. We're basically just following their example. Signed-off-by: Colin Walters --- Cargo.lock | 20 +++++++++++++------ Cargo.toml | 2 ++ cli/Cargo.toml | 2 ++ cli/src/main.rs | 9 ++++++++- tmt/tests/booted/readonly/002-test-cli.nu | 8 ++++++++ .../booted/test-install-outside-container.nu | 4 ++-- 6 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 tmt/tests/booted/readonly/002-test-cli.nu diff --git a/Cargo.lock b/Cargo.lock index 86e593c6..d7dfbfd6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,10 +175,12 @@ dependencies = [ name = "bootc" version = "0.1.9" dependencies = [ + "anstream", "anyhow", "bootc-lib", "bootc-utils", "log", + "owo-colors", "tokio", "tracing", ] @@ -365,7 +367,7 @@ dependencies = [ "ipnet", "maybe-owned", "rustix 0.38.44", - "windows-sys 0.52.0", + "windows-sys 0.59.0", "winx", ] @@ -855,7 +857,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1080,7 +1082,7 @@ dependencies = [ "gobject-sys", "libc", "system-deps", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1757,6 +1759,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "owo-colors" +version = "4.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec" + [[package]] name = "parking_lot" version = "0.12.3" @@ -2039,7 +2047,7 @@ dependencies = [ "libc", "linux-raw-sys 0.4.14", "once_cell", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2052,7 +2060,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.9.3", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2407,7 +2415,7 @@ dependencies = [ "fastrand", "once_cell", "rustix 0.38.44", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 10310ee6..cc945af2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ inherits = "release" lto = "yes" [workspace.dependencies] +anstream = "0.6" anyhow = "1.0.82" camino = "1.1.6" cap-std-ext = "4.0.3" @@ -55,6 +56,7 @@ indicatif = "0.17.0" fn-error-context = "0.2.1" libc = "0.2.154" openssl = "0.10.72" +owo-colors = { version = "4" } rustix = { "version" = "1", features = ["thread", "net", "fs", "system", "process", "mount"] } serde = "1.0.199" serde_json = "1.0.116" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index c9153b15..5b4def79 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -14,11 +14,13 @@ default-run = "bootc" platforms = ["*-unknown-linux-gnu"] [dependencies] +anstream = { workspace = true } anyhow = { workspace = true } bootc-lib = { version = "1.0", path = "../lib" } bootc-utils = { path = "../utils" } tokio = { workspace = true, features = ["macros"] } log = "0.4.21" +owo-colors = { workspace = true } tracing = { workspace = true } [lints] diff --git a/cli/src/main.rs b/cli/src/main.rs index d9429aa3..e9b6d178 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,5 +1,8 @@ //! The main entrypoint for bootc, which just performs global initialization, and then //! calls out into the library. +//! +use std::io::Write as _; + use anyhow::Result; /// The code called after we've done process global init and created @@ -32,11 +35,15 @@ fn run() -> Result<()> { } fn main() { + use owo_colors::OwoColorize; + // In order to print the error in a custom format (with :#) our // main simply invokes a run() where all the work is done. // This code just captures any errors. if let Err(e) = run() { - tracing::error!("{:#}", e); + let mut stderr = anstream::stderr(); + // Don't panic if writing fails + let _ = writeln!(stderr, "{}{:#}", "error: ".red(), e); std::process::exit(1); } } diff --git a/tmt/tests/booted/readonly/002-test-cli.nu b/tmt/tests/booted/readonly/002-test-cli.nu new file mode 100644 index 00000000..096aafcc --- /dev/null +++ b/tmt/tests/booted/readonly/002-test-cli.nu @@ -0,0 +1,8 @@ +use std assert +use tap.nu + +tap begin "verify bootc status output formats" + +assert equal (bootc switch blah:// e>| find "\u{1B}") [] + +tap ok diff --git a/tmt/tests/booted/test-install-outside-container.nu b/tmt/tests/booted/test-install-outside-container.nu index 4d3cef1f..5f07ff97 100644 --- a/tmt/tests/booted/test-install-outside-container.nu +++ b/tmt/tests/booted/test-install-outside-container.nu @@ -8,7 +8,7 @@ mkfs.ext4 disk.img mount -o loop disk.img /var/mnt # attempt to install to filesystem without specifying a source-imgref -let result = bootc install to-filesystem /var/mnt e>| ansi strip -assert equal $result "ERROR Installing to filesystem: Either --source-imgref must be defined or this command must be executed inside a podman container." +let result = bootc install to-filesystem /var/mnt e>| find "--source-imgref must be defined" +assert not equal $result null tap ok