diff --git a/crates/cargo-test-support/src/compare.rs b/crates/cargo-test-support/src/compare.rs index 7ebb330f8ce..62559747d47 100644 --- a/crates/cargo-test-support/src/compare.rs +++ b/crates/cargo-test-support/src/compare.rs @@ -204,6 +204,7 @@ fn substitute_macros(input: &str) -> String { ("[SCRAPING]", " Scraping"), ("[FRESH]", " Fresh"), ("[DIRTY]", " Dirty"), + ("[LOCKING]", " Locking"), ("[UPDATING]", " Updating"), ("[ADDING]", " Adding"), ("[REMOVING]", " Removing"), diff --git a/src/cargo/ops/cargo_generate_lockfile.rs b/src/cargo/ops/cargo_generate_lockfile.rs index 394dde6c90f..cb7a2a8114c 100644 --- a/src/cargo/ops/cargo_generate_lockfile.rs +++ b/src/cargo/ops/cargo_generate_lockfile.rs @@ -10,7 +10,6 @@ use crate::util::cache_lock::CacheLockMode; use crate::util::context::GlobalContext; use crate::util::style; use crate::util::CargoResult; -use anstyle::Style; use std::cmp::Ordering; use std::collections::{BTreeMap, HashSet}; use tracing::debug; @@ -26,17 +25,19 @@ pub struct UpdateOptions<'a> { pub fn generate_lockfile(ws: &Workspace<'_>) -> CargoResult<()> { let mut registry = PackageRegistry::new(ws.gctx())?; + let previous_resolve = None; let mut resolve = ops::resolve_with_previous( &mut registry, ws, &CliFeatures::new_all(true), HasDevUnits::Yes, - None, + previous_resolve, None, &[], true, )?; ops::write_pkg_lockfile(ws, &mut resolve)?; + print_lockfile_changes(ws.gctx(), previous_resolve, &resolve, &mut registry)?; Ok(()) } @@ -154,7 +155,7 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes true, )?; - print_lockfile_update(opts.gctx, &previous_resolve, &resolve, &mut registry)?; + print_lockfile_updates(opts.gctx, &previous_resolve, &resolve, &mut registry)?; if opts.dry_run { opts.gctx .shell() @@ -165,30 +166,177 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes Ok(()) } -fn print_lockfile_update( +pub fn print_lockfile_changes( + gctx: &GlobalContext, + previous_resolve: Option<&Resolve>, + resolve: &Resolve, + registry: &mut PackageRegistry<'_>, +) -> CargoResult<()> { + if let Some(previous_resolve) = previous_resolve { + print_lockfile_sync(gctx, previous_resolve, resolve, registry) + } else { + print_lockfile_generation(gctx, resolve, registry) + } +} + +fn print_lockfile_generation( + gctx: &GlobalContext, + resolve: &Resolve, + registry: &mut PackageRegistry<'_>, +) -> CargoResult<()> { + let mut shell = gctx.shell(); + + let diff = PackageDiff::new(&resolve); + let num_pkgs: usize = diff.iter().map(|d| d.added.len()).sum(); + if num_pkgs <= 1 { + // just ourself, nothing worth reporting + return Ok(()); + } + shell.status("Locking", format!("{num_pkgs} packages"))?; + + for diff in diff { + fn format_latest(version: semver::Version) -> String { + let warn = style::WARN; + format!(" {warn}(latest: v{version}){warn:#}") + } + let possibilities = if let Some(query) = diff.alternatives_query() { + loop { + match registry.query_vec(&query, QueryKind::Exact) { + std::task::Poll::Ready(res) => { + break res?; + } + std::task::Poll::Pending => registry.block_until_ready()?, + } + } + } else { + vec![] + }; + + for package in diff.added.iter() { + let latest = if !possibilities.is_empty() { + possibilities + .iter() + .map(|s| s.as_summary()) + .filter(|s| is_latest(s.version(), package.version())) + .map(|s| s.version().clone()) + .max() + .map(format_latest) + } else { + None + }; + + if let Some(latest) = latest { + shell.status_with_color("Adding", format!("{package}{latest}"), &style::NOTE)?; + } + } + } + + Ok(()) +} + +fn print_lockfile_sync( gctx: &GlobalContext, previous_resolve: &Resolve, resolve: &Resolve, registry: &mut PackageRegistry<'_>, ) -> CargoResult<()> { - // Summarize what is changing for the user. - let print_change = |status: &str, msg: String, color: &Style| { - gctx.shell().status_with_color(status, msg, color) - }; + let mut shell = gctx.shell(); + + let diff = PackageDiff::diff(&previous_resolve, &resolve); + let num_pkgs: usize = diff.iter().map(|d| d.added.len()).sum(); + if num_pkgs == 0 { + return Ok(()); + } + let plural = if num_pkgs == 1 { "" } else { "s" }; + shell.status("Locking", format!("{num_pkgs} package{plural}"))?; + + for diff in diff { + fn format_latest(version: semver::Version) -> String { + let warn = style::WARN; + format!(" {warn}(latest: v{version}){warn:#}") + } + let possibilities = if let Some(query) = diff.alternatives_query() { + loop { + match registry.query_vec(&query, QueryKind::Exact) { + std::task::Poll::Ready(res) => { + break res?; + } + std::task::Poll::Pending => registry.block_until_ready()?, + } + } + } else { + vec![] + }; + + if let Some((removed, added)) = diff.change() { + let latest = if !possibilities.is_empty() { + possibilities + .iter() + .map(|s| s.as_summary()) + .filter(|s| is_latest(s.version(), added.version())) + .map(|s| s.version().clone()) + .max() + .map(format_latest) + } else { + None + } + .unwrap_or_default(); + + let msg = if removed.source_id().is_git() { + format!( + "{removed} -> #{}", + &added.source_id().precise_git_fragment().unwrap()[..8], + ) + } else { + format!("{removed} -> v{}{latest}", added.version()) + }; + + // If versions differ only in build metadata, we call it an "update" + // regardless of whether the build metadata has gone up or down. + // This metadata is often stuff like git commit hashes, which are + // not meaningfully ordered. + if removed.version().cmp_precedence(added.version()) == Ordering::Greater { + shell.status_with_color("Downgrading", msg, &style::WARN)?; + } else { + shell.status_with_color("Updating", msg, &style::GOOD)?; + } + } else { + for package in diff.added.iter() { + let latest = if !possibilities.is_empty() { + possibilities + .iter() + .map(|s| s.as_summary()) + .filter(|s| is_latest(s.version(), package.version())) + .map(|s| s.version().clone()) + .max() + .map(format_latest) + } else { + None + } + .unwrap_or_default(); + + shell.status_with_color("Adding", format!("{package}{latest}"), &style::NOTE)?; + } + } + } + + Ok(()) +} + +pub fn print_lockfile_updates( + gctx: &GlobalContext, + previous_resolve: &Resolve, + resolve: &Resolve, + registry: &mut PackageRegistry<'_>, +) -> CargoResult<()> { + let mut shell = gctx.shell(); + let mut unchanged_behind = 0; for diff in PackageDiff::diff(&previous_resolve, &resolve) { fn format_latest(version: semver::Version) -> String { let warn = style::WARN; format!(" {warn}(latest: v{version}){warn:#}") } - fn is_latest(candidate: &semver::Version, current: &semver::Version) -> bool { - current < candidate - // Only match pre-release if major.minor.patch are the same - && (candidate.pre.is_empty() - || (candidate.major == current.major - && candidate.minor == current.minor - && candidate.patch == current.patch)) - } let possibilities = if let Some(query) = diff.alternatives_query() { loop { match registry.query_vec(&query, QueryKind::Exact) { @@ -230,13 +378,13 @@ fn print_lockfile_update( // This metadata is often stuff like git commit hashes, which are // not meaningfully ordered. if removed.version().cmp_precedence(added.version()) == Ordering::Greater { - print_change("Downgrading", msg, &style::WARN)?; + shell.status_with_color("Downgrading", msg, &style::WARN)?; } else { - print_change("Updating", msg, &style::GOOD)?; + shell.status_with_color("Updating", msg, &style::GOOD)?; } } else { for package in diff.removed.iter() { - print_change("Removing", format!("{package}"), &style::ERROR)?; + shell.status_with_color("Removing", format!("{package}"), &style::ERROR)?; } for package in diff.added.iter() { let latest = if !possibilities.is_empty() { @@ -252,7 +400,7 @@ fn print_lockfile_update( } .unwrap_or_default(); - print_change("Adding", format!("{package}{latest}"), &style::NOTE)?; + shell.status_with_color("Adding", format!("{package}{latest}"), &style::NOTE)?; } } for package in &diff.unchanged { @@ -270,8 +418,8 @@ fn print_lockfile_update( if let Some(latest) = latest { unchanged_behind += 1; - if gctx.shell().verbosity() == Verbosity::Verbose { - gctx.shell().status_with_color( + if shell.verbosity() == Verbosity::Verbose { + shell.status_with_color( "Unchanged", format!("{package}{latest}"), &anstyle::Style::new().bold(), @@ -280,13 +428,13 @@ fn print_lockfile_update( } } } - if gctx.shell().verbosity() == Verbosity::Verbose { - gctx.shell().note( + if shell.verbosity() == Verbosity::Verbose { + shell.note( "to see how you depend on a package, run `cargo tree --invert --package @`", )?; } else { if 0 < unchanged_behind { - gctx.shell().note(format!( + shell.note(format!( "pass `--verbose` to see {unchanged_behind} unchanged dependencies behind latest" ))?; } @@ -295,6 +443,15 @@ fn print_lockfile_update( Ok(()) } +fn is_latest(candidate: &semver::Version, current: &semver::Version) -> bool { + current < candidate + // Only match pre-release if major.minor.patch are the same + && (candidate.pre.is_empty() + || (candidate.major == current.major + && candidate.minor == current.minor + && candidate.patch == current.patch)) +} + fn fill_with_deps<'a>( resolve: &'a Resolve, dep: PackageId, @@ -319,11 +476,21 @@ pub struct PackageDiff { } impl PackageDiff { - pub fn diff(previous_resolve: &Resolve, resolve: &Resolve) -> Vec { - fn key(dep: PackageId) -> (&'static str, SourceId) { - (dep.name().as_str(), dep.source_id()) + pub fn new(resolve: &Resolve) -> Vec { + let mut changes = BTreeMap::new(); + let empty = Self::default(); + for dep in resolve.iter() { + changes + .entry(Self::key(dep)) + .or_insert_with(|| empty.clone()) + .added + .push(dep); } + changes.into_iter().map(|(_, v)| v).collect() + } + + pub fn diff(previous_resolve: &Resolve, resolve: &Resolve) -> Vec { fn vec_subset(a: &[PackageId], b: &[PackageId]) -> Vec { a.iter().filter(|a| !contains_id(b, a)).cloned().collect() } @@ -364,14 +531,14 @@ impl PackageDiff { let empty = Self::default(); for dep in previous_resolve.iter() { changes - .entry(key(dep)) + .entry(Self::key(dep)) .or_insert_with(|| empty.clone()) .removed .push(dep); } for dep in resolve.iter() { changes - .entry(key(dep)) + .entry(Self::key(dep)) .or_insert_with(|| empty.clone()) .added .push(dep); @@ -397,6 +564,10 @@ impl PackageDiff { changes.into_iter().map(|(_, v)| v).collect() } + fn key(dep: PackageId) -> (&'static str, SourceId) { + (dep.name().as_str(), dep.source_id()) + } + /// Guess if a package upgraded/downgraded /// /// All `PackageDiff` knows is that entries were added/removed within [`Resolve`]. diff --git a/src/cargo/ops/lockfile.rs b/src/cargo/ops/lockfile.rs index 22942eb8cd0..162cb6031bd 100644 --- a/src/cargo/ops/lockfile.rs +++ b/src/cargo/ops/lockfile.rs @@ -28,20 +28,23 @@ pub fn load_pkg_lockfile(ws: &Workspace<'_>) -> CargoResult> { } /// Generate a toml String of Cargo.lock from a Resolve. -pub fn resolve_to_string(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoResult { +pub fn resolve_to_string(ws: &Workspace<'_>, resolve: &Resolve) -> CargoResult { let (_orig, out, _lock_root) = resolve_to_string_orig(ws, resolve); Ok(out) } +/// Ensure the resolve result is written to fisk +/// +/// Returns `true` if the lockfile changed #[tracing::instrument(skip_all)] -pub fn write_pkg_lockfile(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoResult<()> { +pub fn write_pkg_lockfile(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoResult { let (orig, mut out, lock_root) = resolve_to_string_orig(ws, resolve); // If the lock file contents haven't changed so don't rewrite it. This is // helpful on read-only filesystems. if let Some(orig) = &orig { if are_equal_lockfiles(orig, &out, ws) { - return Ok(()); + return Ok(false); } } @@ -93,12 +96,12 @@ pub fn write_pkg_lockfile(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoRes lock_root.as_path_unlocked().join("Cargo.lock").display() ) })?; - Ok(()) + Ok(true) } fn resolve_to_string_orig( ws: &Workspace<'_>, - resolve: &mut Resolve, + resolve: &Resolve, ) -> (Option, String, Filesystem) { // Load the original lock file if it exists. let lock_root = lock_root(ws); diff --git a/src/cargo/ops/mod.rs b/src/cargo/ops/mod.rs index 09709ce2d00..9a751793da2 100644 --- a/src/cargo/ops/mod.rs +++ b/src/cargo/ops/mod.rs @@ -8,6 +8,8 @@ pub use self::cargo_compile::{CompileFilter, FilterRule, LibRule, Packages}; pub use self::cargo_doc::{doc, DocOptions, OutputFormat}; pub use self::cargo_fetch::{fetch, FetchOptions}; pub use self::cargo_generate_lockfile::generate_lockfile; +pub use self::cargo_generate_lockfile::print_lockfile_changes; +pub use self::cargo_generate_lockfile::print_lockfile_updates; pub use self::cargo_generate_lockfile::update_lockfile; pub use self::cargo_generate_lockfile::UpdateOptions; pub use self::cargo_install::{install, install_list}; diff --git a/src/cargo/ops/resolve.rs b/src/cargo/ops/resolve.rs index 71b386df3fe..1042c897bcf 100644 --- a/src/cargo/ops/resolve.rs +++ b/src/cargo/ops/resolve.rs @@ -250,8 +250,18 @@ fn resolve_with_registry<'gctx>( true, )?; - if !ws.is_ephemeral() && ws.require_optional_deps() { - ops::write_pkg_lockfile(ws, &mut resolve)?; + let print = if !ws.is_ephemeral() && ws.require_optional_deps() { + ops::write_pkg_lockfile(ws, &mut resolve)? + } else { + false + }; + if print { + // We only want one Cargo at a time resolving a crate graph since this can + // involve a lot of frobbing of the global caches. + let _lock = ws + .gctx() + .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?; + ops::print_lockfile_changes(ws.gctx(), prev.as_ref(), &resolve, registry)?; } Ok(resolve) } diff --git a/tests/testsuite/alt_registry.rs b/tests/testsuite/alt_registry.rs index ec9ec5c67a7..e122199baa4 100644 --- a/tests/testsuite/alt_registry.rs +++ b/tests/testsuite/alt_registry.rs @@ -33,6 +33,7 @@ fn depend_on_alt_registry() { .with_stderr( "\ [UPDATING] `alternative` index +[LOCKING] 2 packages [DOWNLOADING] crates ... [DOWNLOADED] bar v0.0.1 (registry `alternative`) [CHECKING] bar v0.0.1 (registry `alternative`) @@ -87,6 +88,7 @@ fn depend_on_alt_registry_depends_on_same_registry_no_index() { .with_stderr( "\ [UPDATING] `alternative` index +[LOCKING] 3 packages [DOWNLOADING] crates ... [DOWNLOADED] [..] v0.0.1 (registry `alternative`) [DOWNLOADED] [..] v0.0.1 (registry `alternative`) @@ -130,6 +132,7 @@ fn depend_on_alt_registry_depends_on_same_registry() { .with_stderr( "\ [UPDATING] `alternative` index +[LOCKING] 3 packages [DOWNLOADING] crates ... [DOWNLOADED] [..] v0.0.1 (registry `alternative`) [DOWNLOADED] [..] v0.0.1 (registry `alternative`) @@ -174,6 +177,7 @@ fn depend_on_alt_registry_depends_on_crates_io() { "\ [UPDATING] `alternative` index [UPDATING] `dummy-registry` index +[LOCKING] 3 packages [DOWNLOADING] crates ... [DOWNLOADED] baz v0.0.1 (registry `dummy-registry`) [DOWNLOADED] bar v0.0.1 (registry `alternative`) @@ -213,6 +217,7 @@ fn registry_and_path_dep_works() { p.cargo("check") .with_stderr( "\ +[LOCKING] 2 packages [CHECKING] bar v0.0.1 ([CWD]/bar) [CHECKING] foo v0.0.1 ([CWD]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s @@ -416,6 +421,7 @@ fn alt_registry_and_crates_io_deps() { "\ [UPDATING] `alternative` index [UPDATING] `dummy-registry` index +[LOCKING] 3 packages [DOWNLOADING] crates ... [DOWNLOADED] crates_io_dep v0.0.1 (registry `dummy-registry`) [DOWNLOADED] alt_reg_dep v0.1.0 (registry `alternative`) @@ -692,6 +698,7 @@ fn patch_alt_reg() { .with_stderr( "\ [UPDATING] `alternative` index +[LOCKING] 2 packages [CHECKING] bar v0.1.0 ([CWD]/bar) [CHECKING] foo v0.0.1 ([CWD]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] @@ -784,6 +791,7 @@ fn no_api() { .with_stderr( "\ [UPDATING] `alternative` index +[LOCKING] 2 packages [DOWNLOADING] crates ... [DOWNLOADED] bar v0.0.1 (registry `alternative`) [CHECKING] bar v0.0.1 (registry `alternative`) @@ -1346,6 +1354,7 @@ fn registries_index_relative_url() { .with_stderr( "\ [UPDATING] `relative` index +[LOCKING] 2 packages [DOWNLOADING] crates ... [DOWNLOADED] bar v0.0.1 (registry `relative`) [CHECKING] bar v0.0.1 (registry `relative`) diff --git a/tests/testsuite/artifact_dep.rs b/tests/testsuite/artifact_dep.rs index 89556d86740..4d77668214e 100644 --- a/tests/testsuite/artifact_dep.rs +++ b/tests/testsuite/artifact_dep.rs @@ -213,6 +213,7 @@ fn disallow_artifact_and_no_artifact_dep_to_same_package_within_the_same_dep_cat .masquerade_as_nightly_cargo(&["bindeps"]) .with_status(101) .with_stderr("\ +[LOCKING] 2 packages [WARNING] foo v0.0.0 ([CWD]) ignoring invalid dependency `bar_stable` which is missing a lib target [ERROR] the crate `foo v0.0.0 ([CWD])` depends on crate `bar v0.5.0 ([CWD]/bar)` multiple times with different names", ) @@ -322,6 +323,7 @@ fn features_are_unified_among_lib_and_bin_dep_of_same_target() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr( "\ +[LOCKING] 3 packages [COMPILING] d2 v0.0.1 ([CWD]/d2) [COMPILING] d1 v0.0.1 ([CWD]/d1) [COMPILING] foo v0.0.1 ([CWD]) @@ -773,6 +775,7 @@ fn build_script_with_selected_dashed_bin_artifact_and_lib_true() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] bar-baz v0.5.0 ([CWD]/bar) [COMPILING] foo [..] [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]", @@ -874,6 +877,7 @@ fn lib_with_selected_dashed_bin_artifact_and_lib_true() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] bar-baz v0.5.0 ([CWD]/bar) [COMPILING] foo [..] [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]", @@ -992,7 +996,11 @@ fn disallow_using_example_binaries_as_artifacts() { p.cargo("build -Z bindeps") .masquerade_as_nightly_cargo(&["bindeps"]) .with_status(101) - .with_stderr(r#"[ERROR] dependency `bar` in package `foo` requires a `bin:one-example` artifact to be present."#) + .with_stderr( + "\ +[LOCKING] 2 packages +[ERROR] dependency `bar` in package `foo` requires a `bin:one-example` artifact to be present.", + ) .run(); } @@ -1160,7 +1168,9 @@ fn build_script_deps_adopt_do_not_allow_multiple_targets_under_different_name_an .masquerade_as_nightly_cargo(&["bindeps"]) .with_status(101) .with_stderr(format!( - "error: the crate `foo v0.0.0 ([CWD])` depends on crate `bar v0.5.0 ([CWD]/bar)` multiple times with different names", + "\ +[LOCKING] 2 packages +error: the crate `foo v0.0.0 ([CWD])` depends on crate `bar v0.5.0 ([CWD]/bar)` multiple times with different names", )) .run(); } @@ -1264,6 +1274,7 @@ fn no_cross_doctests_works_with_artifacts() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr(&format!( "\ +[LOCKING] 2 packages [COMPILING] bar v0.5.0 ([CWD]/bar) [COMPILING] foo v0.0.1 ([CWD]) [FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [..] @@ -1746,6 +1757,7 @@ fn allow_artifact_and_non_artifact_dependency_to_same_crate_if_these_are_not_the .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] bar [..] [COMPILING] foo [..] [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] @@ -1782,6 +1794,7 @@ fn prevent_no_lib_warning_with_artifact_dependencies() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr( "\ + [LOCKING] 2 packages\n\ [COMPILING] bar v0.5.0 ([CWD]/bar)\n\ [CHECKING] foo v0.0.0 ([CWD])\n\ [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]", @@ -1881,7 +1894,9 @@ fn check_missing_crate_type_in_package_fails() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_status(101) .with_stderr( - "[ERROR] dependency `bar` in package `foo` requires a `[..]` artifact to be present.", + "\ +[LOCKING] 2 packages +[ERROR] dependency `bar` in package `foo` requires a `[..]` artifact to be present.", ) .run(); } @@ -2027,6 +2042,7 @@ fn env_vars_and_build_products_for_various_build_targets() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] bar [..] [COMPILING] foo [..] [FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [..] @@ -2203,6 +2219,7 @@ fn doc_lib_true() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] bar v0.0.1 ([CWD]/bar) [DOCUMENTING] bar v0.0.1 ([CWD]/bar) [DOCUMENTING] foo v0.0.1 ([CWD]) @@ -2285,6 +2302,7 @@ fn rustdoc_works_on_libs_with_artifacts_and_lib_false() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] bar v0.5.0 ([CWD]/bar) [DOCUMENTING] foo v0.0.1 ([CWD]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] @@ -2492,6 +2510,7 @@ fn calc_bin_artifact_fingerprint() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] bar v0.5.0 ([CWD]/bar) [CHECKING] foo v0.1.0 ([CWD]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] @@ -2573,6 +2592,7 @@ fn with_target_and_optional() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] d1 v0.0.1 [..] [RUNNING] `rustc --crate-name d1 [..]--crate-type bin[..] [CHECKING] foo v0.0.1 [..] @@ -2622,6 +2642,7 @@ fn with_assumed_host_target_and_optional_build_dep() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr_unordered( "\ +[LOCKING] 2 packages [COMPILING] foo v0.0.1 ([CWD]) [COMPILING] d1 v0.0.1 ([CWD]/d1) [RUNNING] `rustc --crate-name build_script_build --edition=2021 [..]--crate-type bin[..] @@ -2749,6 +2770,7 @@ fn decouple_same_target_transitive_dep_from_artifact_dep() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr( "\ +[LOCKING] 5 packages [COMPILING] c v0.1.0 ([CWD]/c) [COMPILING] b v0.1.0 ([CWD]/b) [COMPILING] a v0.1.0 ([CWD]/a) @@ -2852,6 +2874,7 @@ fn decouple_same_target_transitive_dep_from_artifact_dep_lib() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr( "\ +[LOCKING] 4 packages [COMPILING] b v0.1.0 ([CWD]/b) [COMPILING] a v0.1.0 ([CWD]/a) [COMPILING] bar v0.1.0 ([CWD]/bar) @@ -2978,6 +3001,7 @@ fn decouple_same_target_transitive_dep_from_artifact_dep_and_proc_macro() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr_unordered( "\ +[LOCKING] 6 packages [COMPILING] d v0.1.0 ([CWD]/d) [COMPILING] a v0.1.0 ([CWD]/a) [COMPILING] b v0.1.0 ([CWD]/b) @@ -3043,6 +3067,7 @@ fn same_target_artifact_dep_sharing() { .masquerade_as_nightly_cargo(&["bindeps"]) .with_stderr( "\ +[LOCKING] 3 packages [COMPILING] a v0.1.0 ([CWD]/a) [COMPILING] bar v0.1.0 ([CWD]/bar) [COMPILING] foo v0.1.0 ([CWD]) diff --git a/tests/testsuite/bench.rs b/tests/testsuite/bench.rs index 35c78454a91..a9603b36c71 100644 --- a/tests/testsuite/bench.rs +++ b/tests/testsuite/bench.rs @@ -438,6 +438,7 @@ fn bench_with_deep_lib_dep() { p.cargo("bench") .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] foo v0.0.1 ([..]) [COMPILING] bar v0.0.1 ([CWD]) [FINISHED] `bench` profile [optimized] target(s) in [..] @@ -903,6 +904,7 @@ fn bench_dylib() { p.cargo("bench -v") .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] bar v0.0.1 ([CWD]/bar) [RUNNING] [..] -C opt-level=3 [..] [COMPILING] foo v0.0.1 ([CWD]) diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index c53ce66f89f..17965aa8dcf 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -1454,6 +1454,7 @@ fn cargo_default_env_metadata_env_var() { p.cargo("build -v") .with_stderr(&format!( "\ +[LOCKING] 2 packages [COMPILING] bar v0.0.1 ([CWD]/bar) [RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type dylib \ --emit=[..]link \ @@ -2476,6 +2477,7 @@ fn verbose_release_build_deps() { p.cargo("build -v --release") .with_stderr(&format!( "\ +[LOCKING] 2 packages [COMPILING] foo v0.0.0 ([CWD]/foo) [RUNNING] `rustc --crate-name foo --edition=2015 foo/src/lib.rs [..]\ --crate-type dylib --crate-type rlib \ @@ -4167,7 +4169,11 @@ fn invalid_spec() { p.cargo("build -p notAValidDep") .with_status(101) - .with_stderr("[ERROR] package ID specification `notAValidDep` did not match any packages") + .with_stderr( + "\ +[LOCKING] 2 packages +[ERROR] package ID specification `notAValidDep` did not match any packages", + ) .run(); p.cargo("build -p d1 -p notAValidDep") @@ -4599,6 +4605,7 @@ fn build_all_workspace() { p.cargo("build --workspace") .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] bar v0.1.0 ([..]) [COMPILING] foo v0.1.0 ([..]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] @@ -4633,6 +4640,7 @@ fn build_all_exclude() { .with_stderr_does_not_contain("[COMPILING] baz v0.1.0 [..]") .with_stderr_unordered( "\ +[LOCKING] 3 packages [COMPILING] foo v0.1.0 ([..]) [COMPILING] bar v0.1.0 ([..]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] @@ -4703,6 +4711,7 @@ fn build_all_exclude_not_found() { .with_stderr_does_not_contain("[COMPILING] baz v0.1.0 [..]") .with_stderr_unordered( "\ +[LOCKING] 2 packages [WARNING] excluded package(s) `baz` not found in workspace [..] [COMPILING] foo v0.1.0 ([..]) [COMPILING] bar v0.1.0 ([..]) @@ -4738,6 +4747,7 @@ fn build_all_exclude_glob() { .with_stderr_does_not_contain("[COMPILING] baz v0.1.0 [..]") .with_stderr_unordered( "\ +[LOCKING] 3 packages [COMPILING] foo v0.1.0 ([..]) [COMPILING] bar v0.1.0 ([..]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] @@ -4771,6 +4781,7 @@ fn build_all_exclude_glob_not_found() { .with_stderr( "\ [WARNING] excluded package pattern(s) `*z` not found in workspace [..] +[LOCKING] 2 packages [COMPILING] [..] v0.1.0 ([..]) [COMPILING] [..] v0.1.0 ([..]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] @@ -4821,7 +4832,8 @@ fn build_all_workspace_implicit_examples() { p.cargo("build --workspace --examples") .with_stderr( - "[..] Compiling bar v0.1.0 ([..])\n\ + "[LOCKING] 2 packages\n\ + [..] Compiling bar v0.1.0 ([..])\n\ [..] Compiling foo v0.1.0 ([..])\n\ [..] Finished `dev` profile [unoptimized + debuginfo] target(s) in [..]\n", ) @@ -4856,6 +4868,7 @@ fn build_all_virtual_manifest() { p.cargo("build --workspace") .with_stderr_unordered( "\ +[LOCKING] 2 packages [COMPILING] baz v0.1.0 ([..]) [COMPILING] bar v0.1.0 ([..]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] @@ -4884,6 +4897,7 @@ fn build_virtual_manifest_all_implied() { p.cargo("build") .with_stderr_unordered( "\ +[LOCKING] 2 packages [COMPILING] baz v0.1.0 ([..]) [COMPILING] bar v0.1.0 ([..]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] @@ -4912,6 +4926,7 @@ fn build_virtual_manifest_one_project() { .with_stderr_does_not_contain("[..]baz[..]") .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] bar v0.1.0 ([..]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] ", @@ -4939,6 +4954,7 @@ fn build_virtual_manifest_glob() { .with_stderr_does_not_contain("[..]bar[..]") .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] baz v0.1.0 ([..]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] ", @@ -5014,6 +5030,7 @@ fn build_all_virtual_manifest_implicit_examples() { p.cargo("build --workspace --examples") .with_stderr_unordered( "\ +[LOCKING] 2 packages [COMPILING] baz v0.1.0 ([..]) [COMPILING] bar v0.1.0 ([..]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] @@ -5060,6 +5077,7 @@ fn build_all_member_dependency_same_name() { p.cargo("build --workspace") .with_stderr( "[UPDATING] `[..]` index\n\ + [LOCKING] 2 packages\n\ [DOWNLOADING] crates ...\n\ [DOWNLOADED] a v0.1.0 ([..])\n\ [COMPILING] a v0.1.0\n\ @@ -6092,6 +6110,7 @@ fn target_filters_workspace() { .with_status(101) .with_stderr( "\ +[LOCKING] 2 packages [ERROR] no example target named `ex` Did you mean `ex1`?", @@ -6137,7 +6156,11 @@ fn target_filters_workspace_not_found() { ws.cargo("build -v --lib") .with_status(101) - .with_stderr("[ERROR] no library targets found in packages: a, b") + .with_stderr( + "\ +[LOCKING] 2 packages +[ERROR] no library targets found in packages: a, b", + ) .run(); } @@ -6195,6 +6218,7 @@ fn signal_display() { foo.cargo("build") .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] pm [..] [COMPILING] foo [..] [ERROR] could not compile `foo` [..] @@ -6253,6 +6277,7 @@ fn pipelining_works() { .with_stdout("") .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] [..] [COMPILING] [..] [FINISHED] [..] @@ -6369,6 +6394,7 @@ fn forward_rustc_output() { .with_stdout("a\nb\n{}") .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] [..] [COMPILING] [..] c diff --git a/tests/testsuite/build_script.rs b/tests/testsuite/build_script.rs index a60c59b0b25..433252941e6 100644 --- a/tests/testsuite/build_script.rs +++ b/tests/testsuite/build_script.rs @@ -889,6 +889,7 @@ fn custom_build_script_rustc_flags() { p.cargo("build --verbose") .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] foo [..] [RUNNING] `rustc --crate-name build_script_build --edition=2015 foo/build.rs [..] [RUNNING] `[..]build-script-build` @@ -950,6 +951,7 @@ fn custom_build_script_rustc_flags_no_space() { p.cargo("build --verbose") .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] foo [..] [RUNNING] `rustc --crate-name build_script_build --edition=2015 foo/build.rs [..] [RUNNING] `[..]build-script-build` @@ -1090,6 +1092,7 @@ fn links_duplicates_old_registry() { .with_stderr( "\ [UPDATING] `[..]` index +[LOCKING] 2 packages [DOWNLOADING] crates ... [DOWNLOADED] bar v0.1.0 ([..]) [ERROR] multiple packages link to native library `a`, \ @@ -1242,6 +1245,7 @@ fn overrides_and_links() { [..] [..] [..] +[..] [RUNNING] `rustc --crate-name foo [..] -L foo -L bar` [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] ", @@ -1702,6 +1706,7 @@ fn build_deps_simple() { p.cargo("build -v") .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] a v0.5.0 ([CWD]/a) [RUNNING] `rustc --crate-name a [..]` [COMPILING] foo v0.5.0 ([CWD]) @@ -1814,6 +1819,7 @@ fn build_cmd_with_a_build_cmd() { p.cargo("build -v") .with_stderr( "\ +[LOCKING] 3 packages [COMPILING] b v0.5.0 ([CWD]/b) [RUNNING] `rustc --crate-name b [..]` [COMPILING] a v0.5.0 ([CWD]/a) @@ -2989,6 +2995,7 @@ fn flags_go_into_tests() { p.cargo("test -v --test=foo") .with_stderr( "\ +[LOCKING] 3 packages [COMPILING] a v0.5.0 ([..] [RUNNING] `rustc [..] a/build.rs [..]` [RUNNING] `[..]/build-script-build` @@ -3088,6 +3095,7 @@ fn diamond_passes_args_only_once() { p.cargo("build -v") .with_stderr( "\ +[LOCKING] 4 packages [COMPILING] c v0.5.0 ([..] [RUNNING] `rustc [..]` [RUNNING] `[..]` @@ -3967,6 +3975,7 @@ fn warnings_hidden_for_upstream() { .with_stderr( "\ [UPDATING] `[..]` index +[LOCKING] 2 packages [DOWNLOADING] crates ... [DOWNLOADED] bar v0.1.0 ([..]) [COMPILING] bar v0.1.0 @@ -4028,6 +4037,7 @@ fn warnings_printed_on_vv() { .with_stderr( "\ [UPDATING] `[..]` index +[LOCKING] 2 packages [DOWNLOADING] crates ... [DOWNLOADED] bar v0.1.0 ([..]) [COMPILING] bar v0.1.0 @@ -4766,6 +4776,7 @@ fn optional_build_dep_and_required_normal_dep() { .with_stdout("0") .with_stderr( "\ +[LOCKING] 2 packages [COMPILING] bar v0.5.0 ([..]) [COMPILING] foo v0.1.0 ([..]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] diff --git a/tests/testsuite/build_script_extra_link_arg.rs b/tests/testsuite/build_script_extra_link_arg.rs index 3ef1f98b009..b1731ee278f 100644 --- a/tests/testsuite/build_script_extra_link_arg.rs +++ b/tests/testsuite/build_script_extra_link_arg.rs @@ -261,6 +261,7 @@ fn link_arg_transitive_not_allowed() { .with_stderr( "\ [UPDATING] [..] +[LOCKING] 2 packages [DOWNLOADING] [..] [DOWNLOADED] [..] [COMPILING] bar v1.0.0 diff --git a/tests/testsuite/cargo_add/add_basic/stderr.term.svg b/tests/testsuite/cargo_add/add_basic/stderr.term.svg index 67da0f3dbfd..e9b664e87cc 100644 --- a/tests/testsuite/cargo_add/add_basic/stderr.term.svg +++ b/tests/testsuite/cargo_add/add_basic/stderr.term.svg @@ -1,4 +1,4 @@ - +