diff --git a/Cargo.lock b/Cargo.lock index 772bb71..9f1d218 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,6 +95,12 @@ version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "assert_cmd" version = "2.0.14" @@ -301,6 +307,19 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.52.0", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -444,6 +463,12 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encoding_rs" version = "0.8.34" @@ -874,6 +899,30 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "indicatif" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "rayon", + "unicode-width", + "vt100", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -1119,6 +1168,12 @@ dependencies = [ "libc", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "object" version = "0.32.2" @@ -1306,6 +1361,12 @@ dependencies = [ "time", ] +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + [[package]] name = "powerfmt" version = "0.2.0" @@ -2105,6 +2166,18 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tracing-indicatif" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069580424efe11d97c3fef4197fa98c004fa26672cc71ad8770d224e23b1951d" +dependencies = [ + "indicatif", + "tracing", + "tracing-core", + "tracing-subscriber", +] + [[package]] name = "tracing-log" version = "0.2.0" @@ -2161,6 +2234,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + [[package]] name = "unsafe-libyaml" version = "0.2.11" @@ -2191,6 +2270,7 @@ dependencies = [ "glob", "hex", "ignore", + "indicatif", "itertools", "log", "plist", @@ -2214,6 +2294,7 @@ dependencies = [ "toml", "tracing", "tracing-error", + "tracing-indicatif", "tracing-subscriber", "url", "users", @@ -2265,6 +2346,39 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vt100" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84cd863bf0db7e392ba3bd04994be3473491b31e66340672af5d11943c6274de" +dependencies = [ + "itoa", + "log", + "unicode-width", + "vte", +] + +[[package]] +name = "vte" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" +dependencies = [ + "arrayvec", + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "wait-timeout" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index ef92490..b01d061 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,7 @@ git2 = { version = "0.18.3", features = [ ] } hex = "0.4.3" itertools = "0.12.1" +indicatif = { version = "0.17.8", features = ["rayon"] } log = "0.4.21" plist = "1.6.1" rayon = "1.10.0" @@ -77,6 +78,7 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } url = "2.5.0" users = "0.11.0" walkdir = "2.5.0" +tracing-indicatif = "0.3.6" [dev-dependencies] assert_cmd = "2.0.14" diff --git a/src/generate/git.rs b/src/generate/git.rs index 551e844..ff7711b 100644 --- a/src/generate/git.rs +++ b/src/generate/git.rs @@ -53,10 +53,9 @@ pub fn run(configs: &[GenerateGitConfig]) -> Result { /// Run a single git config generation. pub fn run_single(generate_git_config: &GenerateGitConfig) -> Result { - debug!( - "Generating git config for: {path}", - path = generate_git_config.path - ); + let _span = + tracing::info_span!("generate_git", repo = &generate_git_config.path.as_str()).entered(); + debug!("Generating git config"); let mut git_task = Task::from(&generate_git_config.path)?; debug!("Existing git config: {git_task:?}"); let name = git_task.name.as_str(); diff --git a/src/main.rs b/src/main.rs index a5a62cb..48bcee6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,8 +26,11 @@ use tracing::trace; use tracing::warn; use tracing::Level; use tracing_error::ErrorLayer; +use tracing_indicatif::IndicatifLayer; use tracing_subscriber::filter::EnvFilter; +use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::prelude::*; +use tracing_subscriber::util::SubscriberInitExt; use up_rs::log; use up_rs::opts::Opts; @@ -91,11 +94,13 @@ fn main() -> Result<()> { /// Set up logging to stderr and to a temp file path. /// Returns the log level filter chosen by the user if available, and the path to the log file. fn set_up_logging(opts: &Opts) -> (Utf8PathBuf, Option) { + let indicatif_layer = IndicatifLayer::new(); + let stderr_log = tracing_subscriber::fmt::layer() .compact() .with_target(false) .without_time() - .with_writer(std::io::stderr); + .with_writer(indicatif_layer.get_stderr_writer()); let (log_path, log_file) = get_log_file_and_path(opts); let log_file_setup = log_file.is_some(); @@ -123,6 +128,7 @@ fn set_up_logging(opts: &Opts) -> (Utf8PathBuf, Option) { tracing_subscriber::registry() .with(file_log.with_filter(file_envfilter)) .with(stderr_log.with_filter(stderr_envfilter)) + .with(indicatif_layer) // Adds a color_eyre spantrace layer. This isn't used unless we start adding `#[instrument]` // to functions. .with(ErrorLayer::default()) diff --git a/src/tasks.rs b/src/tasks.rs index 5498d01..ea2ec07 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -231,7 +231,9 @@ fn run_tasks( .into_par_iter() .filter(|(_, task)| task.config.auto_run.unwrap_or(true)) .map(|(_, task)| { - let task_tempdir = create_task_tempdir(temp_dir, task.name.as_str())?; + let task_name = task.name.as_str(); + let _span = tracing::info_span!("task", task = task_name).entered(); + let task_tempdir = create_task_tempdir(temp_dir, task_name)?; Ok(run_task(task, env, &task_tempdir)) }) .collect::>>()?, @@ -315,7 +317,7 @@ fn run_task(mut task: Task, env: &HashMap, task_tempdir: &Utf8Pa task.run(env_fn, env, task_tempdir); let elapsed_time = now.elapsed(); if elapsed_time > Duration::from_secs(60) { - warn!("Task {} took {:?}", task.name, elapsed_time); + warn!("Task took {elapsed_time:?}"); } task } diff --git a/src/tasks/git/status.rs b/src/tasks/git/status.rs index 12e6805..89bdc06 100644 --- a/src/tasks/git/status.rs +++ b/src/tasks/git/status.rs @@ -4,7 +4,6 @@ use crate::tasks::git::branch::get_push_branch; use crate::tasks::git::cherry::unmerged_commits; use crate::tasks::git::errors::GitError as E; use crate::utils::files::to_utf8_path; -use camino::Utf8Path; use color_eyre::eyre::ensure; use color_eyre::eyre::eyre; use color_eyre::eyre::Result; @@ -50,16 +49,12 @@ pub(super) fn ensure_repo_clean(repo: &Repository) -> Result<()> { pub(super) fn warn_for_unpushed_changes( repo: &mut Repository, user_git_config: &Config, - git_path: &Utf8Path, ) -> Result<()> { // Warn for uncommitted changes. { let statuses = repo_statuses(repo)?; if !statuses.is_empty() { - warn!( - "Repo {git_path} has uncommitted changes:\n{}", - status_short(repo, &statuses)? - ); + warn!("Uncommitted changes:\n{}", status_short(repo, &statuses)?); } } @@ -71,10 +66,7 @@ pub(super) fn warn_for_unpushed_changes( true })?; if !stash_messages.is_empty() { - warn!( - "Repo {git_path} has stashed changes:\n{:#?}", - stash_messages - ); + warn!("Stashed changes:\n{:#?}", stash_messages); } } @@ -84,27 +76,19 @@ pub(super) fn warn_for_unpushed_changes( if let Some(push_branch) = get_push_branch(repo, &branch_name, user_git_config)? { // Warn for any commits not in @{push} if unmerged_commits(repo, &push_branch, &branch)? { - warn!( - "Repo {git_path} branch '{branch_name}' has changes that aren't in @{{push}}.", - ); + warn!("Branch '{branch_name}' has changes that aren't in @{{push}}.",); } } else { match branch.upstream() { Ok(upstream_branch) => { // If no push, warn for any commits not in @{upstream} if unmerged_commits(repo, &upstream_branch, &branch)? { - warn!( - "Repo {git_path} branch '{branch_name}' has changes that aren't in \ - @{{upstream}}.", - ); + warn!("Branch '{branch_name}' has changes that aren't in @{{upstream}}.",); } } Err(e) if e.code() == ErrorCode::NotFound => { // Warn for any branches with no @{upstream} or @{push} - warn!( - "Repo {git_path} branch '{branch_name}' has no @{{upstream}} or @{{push}} \ - branch.", - ); + warn!("Branch '{branch_name}' has no @{{upstream}} or @{{push}} branch.",); } Err(e) => { // Something else went wrong, raise error. @@ -136,10 +120,7 @@ pub(super) fn warn_for_unpushed_changes( } } if !unmerged_branches.is_empty() { - warn!( - "Repo {git_path} has unmerged fork branches: {} .", - unmerged_branches.join(" "), - ); + warn!("Unmerged fork branches: {} .", unmerged_branches.join(" "),); } Ok(()) diff --git a/src/tasks/git/update.rs b/src/tasks/git/update.rs index dac038f..c22bc1c 100644 --- a/src/tasks/git/update.rs +++ b/src/tasks/git/update.rs @@ -38,6 +38,7 @@ use url::Url; /// Update a git repo. pub(crate) fn update(git_config: &GitConfig) -> Result { let now = Instant::now(); + let _span = tracing::info_span!("git", repo = &git_config.path.as_str()).entered(); let result = real_update(git_config) .map(|did_work| { if did_work { @@ -52,10 +53,7 @@ pub(crate) fn update(git_config: &GitConfig) -> Result { let elapsed_time = now.elapsed(); // TODO(gib): configurable logging for long actions. if elapsed_time > Duration::from_secs(60) { - warn!( - "Git update for {path} took {elapsed_time:?}", - path = git_config.path - ); + warn!("Git update took {elapsed_time:?}",); } result } @@ -213,7 +211,7 @@ pub(crate) fn real_update(git_config: &GitConfig) -> Result { }; drop(default_remote); // Can't mutably use repo while this value is around. if !newly_created_repo { - warn_for_unpushed_changes(&mut repo, &user_git_config, &git_path)?; + warn_for_unpushed_changes(&mut repo, &user_git_config)?; } Ok(did_work) } diff --git a/src/tasks/task.rs b/src/tasks/task.rs index ca9902d..bbe619b 100644 --- a/src/tasks/task.rs +++ b/src/tasks/task.rs @@ -184,21 +184,21 @@ impl Task { F: Fn(&str) -> Result, { let name = &self.name; - info!("Running task '{name}'"); + info!("Running"); if let Some(mut cmd) = self.config.run_if_cmd.clone() { - debug!("Running '{name}' run_if command."); + debug!("Running run_if command."); for s in &mut cmd { *s = env_fn(s)?; } // TODO(gib): Allow choosing how to validate run_if_cmd output (stdout, zero exit // code, non-zero exit code). if !self.run_command(CommandType::RunIf, &cmd, env, task_tempdir)? { - debug!("Skipping task '{name}' as run_if command failed."); + debug!("Skipping task as run_if command failed."); return Ok(TaskStatus::Skipped); } } else { - debug!("You haven't specified a run_if command for '{name}', so it will always be run",); + debug!("You haven't specified a run_if command, so it will always be run",); } if let Some(lib) = &self.config.run_lib {