diff --git a/Cargo.lock b/Cargo.lock index c4b65b1..d295e00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,6 +61,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + [[package]] name = "clap" version = "4.5.41" @@ -113,6 +119,9 @@ version = "0.1.0" dependencies = [ "clap", "regex", + "tracing", + "tracing-subscriber", + "yansi", ] [[package]] @@ -127,18 +136,58 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + [[package]] name = "memchr" version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + [[package]] name = "once_cell_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + [[package]] name = "proc-macro2" version = "1.0.95" @@ -186,6 +235,21 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + [[package]] name = "strsim" version = "0.11.1" @@ -203,6 +267,72 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + [[package]] name = "unicode-ident" version = "1.0.18" @@ -215,6 +345,34 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.59.0" @@ -294,3 +452,9 @@ version = "0.1.0" dependencies = [ "clap", ] + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" diff --git a/Cargo.toml b/Cargo.toml index 58637fe..116535e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,9 @@ [workspace] -members = ["eh", "xtask"] +members = [ "eh", "xtask" ] resolver = "3" [workspace.package] -authors = [ "NotAShelf "] +authors = [ "NotAShelf " ] description = "Ergonomic Nix CLI helper" edition = "2024" license = "MPL-2.0" @@ -12,5 +12,8 @@ rust-version = "1.85" version = "0.1.0" [workspace.dependencies] -clap = { version = "4.5", features = ["derive"] } -regex = "1.0" +clap = { features = [ "derive" ], version = "4.5" } +regex = "1.0" +tracing = "0.1" +tracing-subscriber = "0.3" +yansi = "1.0" diff --git a/eh/Cargo.toml b/eh/Cargo.toml index 430e9cd..db2736d 100644 --- a/eh/Cargo.toml +++ b/eh/Cargo.toml @@ -7,5 +7,8 @@ authors.workspace = true rust-version.workspace = true [dependencies] -clap.workspace = true -regex.workspace = true +clap.workspace = true +regex.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +yansi.workspace = true diff --git a/eh/src/build.rs b/eh/src/build.rs index b2019d4..016e23e 100644 --- a/eh/src/build.rs +++ b/eh/src/build.rs @@ -1,6 +1,8 @@ use crate::command::{NixCommand, StdIoInterceptor}; use crate::util::{HashExtractor, NixErrorClassifier, NixFileFixer}; use std::io::Write; +use tracing::{info, warn}; +use yansi::Paint; pub fn handle_nix_build( args: &[String], @@ -28,7 +30,7 @@ pub fn handle_nix_build( if let Some(new_hash) = hash_extractor.extract_hash(&stderr) { if fixer.fix_hash_in_files(&new_hash) { - eprintln!("\x1b[32m✔ Fixed hash mismatch, retrying...\x1b[0m"); + info!("{}", Paint::green("✔ Fixed hash mismatch, retrying...")); let retry_status = NixCommand::new("build") .print_build_logs(true) .args(args.iter().cloned()) @@ -40,8 +42,9 @@ pub fn handle_nix_build( if classifier.should_retry(&stderr) { if stderr.contains("unfree") { - eprintln!( - "\x1b[33m⚠ Unfree package detected, retrying with NIXPKGS_ALLOW_UNFREE=1...\x1b[0m" + warn!( + "{}", + Paint::yellow("⚠ Unfree package detected, retrying with NIXPKGS_ALLOW_UNFREE=1...") ); let retry_status = NixCommand::new("build") .print_build_logs(true) @@ -53,8 +56,11 @@ pub fn handle_nix_build( std::process::exit(retry_status.code().unwrap_or(1)); } if stderr.contains("insecure") { - eprintln!( - "\x1b[33m⚠ Insecure package detected, retrying with NIXPKGS_ALLOW_INSECURE=1...\x1b[0m" + warn!( + "{}", + Paint::yellow( + "⚠ Insecure package detected, retrying with NIXPKGS_ALLOW_INSECURE=1..." + ) ); let retry_status = NixCommand::new("build") .print_build_logs(true) @@ -66,8 +72,9 @@ pub fn handle_nix_build( std::process::exit(retry_status.code().unwrap_or(1)); } if stderr.contains("broken") { - eprintln!( - "\x1b[33m⚠ Broken package detected, retrying with NIXPKGS_ALLOW_BROKEN=1...\x1b[0m" + warn!( + "{}", + Paint::yellow("⚠ Broken package detected, retrying with NIXPKGS_ALLOW_BROKEN=1...") ); let retry_status = NixCommand::new("build") .print_build_logs(true) diff --git a/eh/src/main.rs b/eh/src/main.rs index 9b8bfa7..c7aad53 100644 --- a/eh/src/main.rs +++ b/eh/src/main.rs @@ -36,6 +36,14 @@ enum Command { } fn main() { + let format = tracing_subscriber::fmt::format() + .with_level(true) // don't include levels in formatted output + .with_target(true) // don't include targets + .with_thread_ids(false) // include the thread ID of the current thread + .with_thread_names(false) // include the name of the current thread + .compact(); // use the `Compact` formatting style. + tracing_subscriber::fmt().event_format(format).init(); + let mut args = env::args(); let bin = args.next().unwrap_or_else(|| "eh".to_string()); let app_name = Path::new(&bin) @@ -43,6 +51,7 @@ fn main() { .and_then(|name| name.to_str()) .unwrap_or("eh"); + // If invoked as nr/ns/nb, dispatch directly and exit match app_name { "nr" => { let rest: Vec = args.collect(); @@ -52,6 +61,7 @@ fn main() { run::handle_nix_run(&rest, &hash_extractor, &fixer, &classifier); return; } + "ns" => { let rest: Vec = args.collect(); let hash_extractor = util::RegexHashExtractor; @@ -60,6 +70,7 @@ fn main() { shell::handle_nix_shell(&rest, &hash_extractor, &fixer, &classifier); return; } + "nb" => { let rest: Vec = args.collect(); let hash_extractor = util::RegexHashExtractor; @@ -81,13 +92,16 @@ fn main() { Some(Command::Run { args }) => { run::handle_nix_run(&args, &hash_extractor, &fixer, &classifier); } + Some(Command::Shell { args }) => { shell::handle_nix_shell(&args, &hash_extractor, &fixer, &classifier); } + Some(Command::Build { args }) => { build::handle_nix_build(&args, &hash_extractor, &fixer, &classifier); } - None => { + + _ => { Cli::command().print_help().unwrap(); println!(); std::process::exit(0); diff --git a/eh/src/run.rs b/eh/src/run.rs index c8c1785..e488c96 100644 --- a/eh/src/run.rs +++ b/eh/src/run.rs @@ -1,6 +1,8 @@ use crate::command::{NixCommand, StdIoInterceptor}; use crate::util::{HashExtractor, NixErrorClassifier, NixFileFixer}; use std::io::Write; +use tracing::{info, warn}; +use yansi::Paint; pub fn handle_nix_run( args: &[String], @@ -28,7 +30,7 @@ pub fn handle_nix_run( if let Some(new_hash) = hash_extractor.extract_hash(&stderr) { if fixer.fix_hash_in_files(&new_hash) { - eprintln!("\x1b[32m✔ Fixed hash mismatch, retrying...\x1b[0m"); + info!("{}", Paint::green("✔ Fixed hash mismatch, retrying...")); let retry_status = NixCommand::new("run") .print_build_logs(true) .args(args.iter().cloned()) @@ -40,8 +42,9 @@ pub fn handle_nix_run( if classifier.should_retry(&stderr) { if stderr.contains("unfree") { - eprintln!( - "\x1b[33m⚠ Unfree package detected, retrying with NIXPKGS_ALLOW_UNFREE=1...\x1b[0m" + warn!( + "{}", + Paint::yellow("⚠ Unfree package detected, retrying with NIXPKGS_ALLOW_UNFREE=1...") ); let retry_status = NixCommand::new("run") .print_build_logs(true) @@ -53,8 +56,11 @@ pub fn handle_nix_run( std::process::exit(retry_status.code().unwrap_or(1)); } if stderr.contains("insecure") { - eprintln!( - "\x1b[33m⚠ Insecure package detected, retrying with NIXPKGS_ALLOW_INSECURE=1...\x1b[0m" + warn!( + "{}", + Paint::yellow( + "⚠ Insecure package detected, retrying with NIXPKGS_ALLOW_INSECURE=1..." + ) ); let retry_status = NixCommand::new("run") .print_build_logs(true) @@ -66,8 +72,9 @@ pub fn handle_nix_run( std::process::exit(retry_status.code().unwrap_or(1)); } if stderr.contains("broken") { - eprintln!( - "\x1b[33m⚠ Broken package detected, retrying with NIXPKGS_ALLOW_BROKEN=1...\x1b[0m" + warn!( + "{}", + Paint::yellow("⚠ Broken package detected, retrying with NIXPKGS_ALLOW_BROKEN=1...") ); let retry_status = NixCommand::new("run") .print_build_logs(true) diff --git a/eh/src/shell.rs b/eh/src/shell.rs index 1fcb414..5a56147 100644 --- a/eh/src/shell.rs +++ b/eh/src/shell.rs @@ -1,6 +1,8 @@ use crate::command::{NixCommand, StdIoInterceptor}; use crate::util::{HashExtractor, NixErrorClassifier, NixFileFixer}; use std::io::Write; +use tracing::{info, warn}; +use yansi::Paint; pub fn handle_nix_shell( args: &[String], @@ -28,7 +30,7 @@ pub fn handle_nix_shell( if let Some(new_hash) = hash_extractor.extract_hash(&stderr) { if fixer.fix_hash_in_files(&new_hash) { - eprintln!("\x1b[32m✔ Fixed hash mismatch, retrying...\x1b[0m"); + info!("{}", Paint::green("✔ Fixed hash mismatch, retrying...")); let retry_status = NixCommand::new("shell") .print_build_logs(true) .args(args.iter().cloned()) @@ -40,8 +42,9 @@ pub fn handle_nix_shell( if classifier.should_retry(&stderr) { if stderr.contains("unfree") { - eprintln!( - "\x1b[33m⚠ Unfree package detected, retrying with NIXPKGS_ALLOW_UNFREE=1...\x1b[0m" + warn!( + "{}", + Paint::yellow("⚠ Unfree package detected, retrying with NIXPKGS_ALLOW_UNFREE=1...") ); let retry_status = NixCommand::new("shell") .print_build_logs(true) @@ -53,8 +56,11 @@ pub fn handle_nix_shell( std::process::exit(retry_status.code().unwrap_or(1)); } if stderr.contains("insecure") { - eprintln!( - "\x1b[33m⚠ Insecure package detected, retrying with NIXPKGS_ALLOW_INSECURE=1...\x1b[0m" + warn!( + "{}", + Paint::yellow( + "⚠ Insecure package detected, retrying with NIXPKGS_ALLOW_INSECURE=1..." + ) ); let retry_status = NixCommand::new("shell") .print_build_logs(true) @@ -66,8 +72,9 @@ pub fn handle_nix_shell( std::process::exit(retry_status.code().unwrap_or(1)); } if stderr.contains("broken") { - eprintln!( - "\x1b[33m⚠ Broken package detected, retrying with NIXPKGS_ALLOW_BROKEN=1...\x1b[0m" + warn!( + "{}", + Paint::yellow("⚠ Broken package detected, retrying with NIXPKGS_ALLOW_BROKEN=1...") ); let retry_status = NixCommand::new("shell") .print_build_logs(true)