diff --git a/crates/xtask-bump-check/src/xtask.rs b/crates/xtask-bump-check/src/xtask.rs index dd600cf18a2..7a580abbd47 100644 --- a/crates/xtask-bump-check/src/xtask.rs +++ b/crates/xtask-bump-check/src/xtask.rs @@ -82,6 +82,7 @@ fn global_context_configure(gctx: &mut GlobalContext, args: &ArgMatches) -> CliR // quiet is unusual because it is redefined in some subcommands in order // to provide custom help text. let quiet = args.flag("quiet"); + let is_manifest = false; // TODO let color = args.get_one::("color").map(String::as_str); let frozen = args.flag("frozen"); let locked = args.flag("locked"); @@ -97,6 +98,7 @@ fn global_context_configure(gctx: &mut GlobalContext, args: &ArgMatches) -> CliR gctx.configure( verbose, quiet, + is_manifest, color, frozen, locked, diff --git a/src/bin/cargo/cli.rs b/src/bin/cargo/cli.rs index 253de9a9692..6c945d90217 100644 --- a/src/bin/cargo/cli.rs +++ b/src/bin/cargo/cli.rs @@ -417,7 +417,10 @@ fn configure_gctx( let mut quiet = args.flag("quiet") || subcommand_args.map(|a| a.flag("quiet")).unwrap_or_default() || global_args.quiet; - if matches!(exec, Some(Exec::Manifest(_))) && !quiet { + + let is_manifest = matches!(exec, Some(Exec::Manifest(_))); + + if is_manifest && !quiet { // Verbosity is shifted quieter for `Exec::Manifest` as it is can be used as if you ran // `cargo install` and we especially shouldn't pollute programmatic output. // @@ -449,6 +452,7 @@ fn configure_gctx( gctx.configure( verbose, quiet, + is_manifest, color, frozen, locked, diff --git a/src/cargo/core/compiler/compilation.rs b/src/cargo/core/compiler/compilation.rs index dff2d00ba80..9a6a17ba8f6 100644 --- a/src/cargo/core/compiler/compilation.rs +++ b/src/cargo/core/compiler/compilation.rs @@ -131,6 +131,12 @@ pub struct Compilation<'gctx> { /// The total number of lint warnings emitted by the compilation. pub lint_warning_count: usize, + + /// Were all compiled units up to date? This is initialised to true + /// and then set to false if we have to actually compile anything, instead + /// of using cached artifacts. This is used by `cargo script` to suppress + /// cargo messages when the script is already built. + pub unchanged: bool, } impl<'gctx> Compilation<'gctx> { @@ -170,6 +176,7 @@ impl<'gctx> Compilation<'gctx> { .map(|kind| Ok((*kind, target_linker(bcx, *kind)?))) .collect::>>()?, lint_warning_count: 0, + unchanged: true, }) } diff --git a/src/cargo/core/compiler/job_queue/mod.rs b/src/cargo/core/compiler/job_queue/mod.rs index de8b86f61bb..9bc50511d2a 100644 --- a/src/cargo/core/compiler/job_queue/mod.rs +++ b/src/cargo/core/compiler/job_queue/mod.rs @@ -848,7 +848,13 @@ impl<'gctx> DrainState<'gctx> { "{profile_link}`{profile_name}` profile [{opt_type}]{profile_link:#} target(s) in {time_elapsed}", ); // It doesn't really matter if this fails. - let _ = build_runner.bcx.gctx.shell().status("Finished", message); + let _ = build_runner + .bcx + .gctx + .shell() + .if_unchanged(build_runner.compilation.unchanged, move |shell| { + shell.status("Finished", &message) + }); future_incompat::save_and_display_report( build_runner.bcx, &self.per_package_future_incompat_reports, diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 4ad36afdbb8..1ed6f27e3b4 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -202,6 +202,9 @@ fn compile<'gctx>( let force = exec.force_rebuild(unit) || force_rebuild; let mut job = fingerprint::prepare_target(build_runner, unit, force)?; job.before(if job.freshness().is_dirty() { + // Mark the compilation as having done some work. + build_runner.compilation.unchanged = false; + let work = if unit.mode.is_doc() || unit.mode.is_doc_scrape() { rustdoc(build_runner, unit)? } else { diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs index 2a8ff9c8e14..e2e5455d468 100644 --- a/src/cargo/core/shell.rs +++ b/src/cargo/core/shell.rs @@ -213,6 +213,18 @@ impl Shell { } } + // Runs the callback if unless the verbosity is `QuietIfUnchanged` and + // `unchanged` is true. + pub fn if_unchanged(&mut self, unchanged: bool, mut callback: F) -> CargoResult<()> + where + F: FnMut(&mut Shell) -> CargoResult<()>, + { + match (self.verbosity, unchanged) { + (Verbosity::QuietIfUnchanged, true) => Ok(()), + _ => callback(self), + } + } + /// Prints a red 'error' message. pub fn error(&mut self, message: T) -> CargoResult<()> { if self.needs_clear { @@ -558,6 +570,8 @@ impl TtyWidth { pub enum Verbosity { Verbose, Normal, + /// No output if it's a no-change build with no warnings. + QuietIfUnchanged, Quiet, } diff --git a/src/cargo/ops/cargo_run.rs b/src/cargo/ops/cargo_run.rs index b7a56a8a0b0..4e225eb7b82 100644 --- a/src/cargo/ops/cargo_run.rs +++ b/src/cargo/ops/cargo_run.rs @@ -122,7 +122,11 @@ pub fn run( process.display_env_vars(); } - gctx.shell().status("Running", process.to_string())?; + let process_string = process.to_string(); + + gctx.shell().if_unchanged(compile.unchanged, move |shell| { + shell.status("Running", &process_string) + })?; process.exec_replace() } diff --git a/src/cargo/ops/registry/info/view.rs b/src/cargo/ops/registry/info/view.rs index 7be0a50a771..9bf2ad8b231 100644 --- a/src/cargo/ops/registry/info/view.rs +++ b/src/cargo/ops/registry/info/view.rs @@ -181,7 +181,7 @@ fn pretty_deps( gctx: &GlobalContext, ) -> CargoResult<()> { match verbosity { - Verbosity::Quiet | Verbosity::Normal => { + Verbosity::Quiet | Verbosity::Normal | Verbosity::QuietIfUnchanged => { return Ok(()); } Verbosity::Verbose => {} @@ -345,7 +345,7 @@ fn pretty_features( .filter(|(_, s)| s.is_disabled()) .count(); let show_all = match verbosity { - Verbosity::Quiet | Verbosity::Normal => false, + Verbosity::Quiet | Verbosity::Normal | Verbosity::QuietIfUnchanged => false, Verbosity::Verbose => true, }; let show_activated = total_activated <= MAX_FEATURE_PRINTS || show_all; diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index fa5438a9909..867d61bbb30 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -1095,7 +1095,7 @@ fn fetch_with_cli( cmd.arg(format!("--depth={depth}")); } match gctx.shell().verbosity() { - Verbosity::Normal => {} + Verbosity::Normal | Verbosity::QuietIfUnchanged => {} Verbosity::Verbose => { cmd.arg("--verbose"); } diff --git a/src/cargo/util/command_prelude.rs b/src/cargo/util/command_prelude.rs index 8f139ca58ac..ac8485e9b31 100644 --- a/src/cargo/util/command_prelude.rs +++ b/src/cargo/util/command_prelude.rs @@ -1559,6 +1559,7 @@ pub fn new_gctx_for_completions() -> CargoResult { let verbose = 0; let quiet = true; + let is_manifest = false; let color = None; let frozen = false; let locked = true; @@ -1570,6 +1571,7 @@ pub fn new_gctx_for_completions() -> CargoResult { gctx.configure( verbose, quiet, + is_manifest, color, frozen, locked, diff --git a/src/cargo/util/context/mod.rs b/src/cargo/util/context/mod.rs index a3f2e470553..64a9871aafa 100644 --- a/src/cargo/util/context/mod.rs +++ b/src/cargo/util/context/mod.rs @@ -1115,6 +1115,7 @@ impl GlobalContext { &mut self, verbose: u32, quiet: bool, + is_manifest: bool, color: Option<&str>, frozen: bool, locked: bool, @@ -1163,15 +1164,21 @@ impl GlobalContext { let verbose = verbose != 0; let verbosity = match (verbose, quiet) { (true, true) => bail!("cannot set both --verbose and --quiet"), - (true, false) => Verbosity::Verbose, - (false, true) => Verbosity::Quiet, + (true, _) => Verbosity::Verbose, + (_, true) => Verbosity::Quiet, (false, false) => match (term.verbose, term.quiet) { (Some(true), Some(true)) => { bail!("cannot set both `term.verbose` and `term.quiet`") } (Some(true), _) => Verbosity::Verbose, (_, Some(true)) => Verbosity::Quiet, - _ => Verbosity::Normal, + _ => { + if is_manifest { + Verbosity::QuietIfUnchanged + } else { + Verbosity::Normal + } + } }, }; self.shell().set_verbosity(verbosity); diff --git a/src/cargo/util/dependency_queue.rs b/src/cargo/util/dependency_queue.rs index d4628bc75f3..9ce9b20f88c 100644 --- a/src/cargo/util/dependency_queue.rs +++ b/src/cargo/util/dependency_queue.rs @@ -170,6 +170,11 @@ impl DependencyQueue { self.dep_map.len() } + /// Return an iterator over the values in the queue. + pub fn values(&self) -> impl Iterator { + self.dep_map.values().map(|(_, v)| v) + } + /// Indicate that something has finished. /// /// Calling this function indicates that the `node` has produced `edge`. All