Skip to content

Commit c89ac1f

Browse files
committed
feat(update): Summarize unchanged packages with updates
`--verbose` will show them. This is prep for telling the user about `--breaking` and other flags.
1 parent b4ad206 commit c89ac1f

File tree

6 files changed

+55
-12
lines changed

6 files changed

+55
-12
lines changed

crates/cargo-test-support/src/compare.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ fn substitute_macros(input: &str) -> String {
208208
("[ADDING]", " Adding"),
209209
("[REMOVING]", " Removing"),
210210
("[REMOVED]", " Removed"),
211+
("[UNCHANGED]", " Unchanged"),
211212
("[DOCTEST]", " Doc-tests"),
212213
("[PACKAGING]", " Packaging"),
213214
("[PACKAGED]", " Packaged"),

src/cargo/ops/cargo_generate_lockfile.rs

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::core::registry::PackageRegistry;
22
use crate::core::resolver::features::{CliFeatures, HasDevUnits};
3+
use crate::core::shell::Verbosity;
34
use crate::core::Registry as _;
45
use crate::core::{PackageId, PackageIdSpec, PackageIdSpecQuery};
56
use crate::core::{Resolve, SourceId, Workspace};
@@ -163,15 +164,19 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
163164
let print_change = |status: &str, msg: String, color: &Style| {
164165
opts.config.shell().status_with_color(status, msg, color)
165166
};
166-
for (removed, added) in compare_dependency_graphs(&previous_resolve, &resolve) {
167-
let latest = if let Some(added) = added
168-
.iter()
169-
.rev()
170-
.next()
171-
.filter(|p| p.source_id().is_registry())
167+
let mut unchanged_behind = 0;
168+
for (removed, added, unchanged) in compare_dependency_graphs(&previous_resolve, &resolve) {
169+
let highest_present = [added.iter().rev().next(), unchanged.iter().rev().next()]
170+
.into_iter()
171+
.flatten()
172+
.max_by_key(|s| s.version());
173+
let latest = if let Some(present) = highest_present.filter(|p| p.source_id().is_registry())
172174
{
173-
let query =
174-
crate::core::dependency::Dependency::parse(added.name(), None, added.source_id())?;
175+
let query = crate::core::dependency::Dependency::parse(
176+
present.name(),
177+
None,
178+
present.source_id(),
179+
)?;
175180
let possibilities = loop {
176181
match registry.query_vec(&query, QueryKind::Exact) {
177182
std::task::Poll::Ready(res) => {
@@ -187,7 +192,7 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
187192
.filter(|s| s.version().pre.is_empty())
188193
.map(|s| s.version().clone())
189194
.max()
190-
.filter(|v| added.version() < v)
195+
.filter(|v| present.version() < v)
191196
.map(|v| format!(" {warn}(latest: v{v}){warn:#}"))
192197
} else {
193198
None
@@ -222,6 +227,26 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
222227
print_change("Adding", format!("{package}{latest}"), &style::NOTE)?;
223228
}
224229
}
230+
if !latest.is_empty() {
231+
if opts.config.shell().verbosity() == Verbosity::Verbose {
232+
for package in &unchanged {
233+
opts.config.shell().status_with_color(
234+
"Unchanged",
235+
format!("{package}{latest}"),
236+
&anstyle::Style::new().bold(),
237+
)?;
238+
}
239+
} else {
240+
if !unchanged.is_empty() {
241+
unchanged_behind += 1;
242+
}
243+
}
244+
}
245+
}
246+
if 0 < unchanged_behind {
247+
opts.config.shell().note(format!(
248+
"Pass `--verbose` to see {unchanged_behind} unchanged dependencies behind latest"
249+
))?;
225250
}
226251
if opts.dry_run {
227252
opts.config
@@ -250,7 +275,7 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
250275
fn compare_dependency_graphs(
251276
previous_resolve: &Resolve,
252277
resolve: &Resolve,
253-
) -> Vec<(Vec<PackageId>, Vec<PackageId>)> {
278+
) -> Vec<(Vec<PackageId>, Vec<PackageId>, Vec<PackageId>)> {
254279
fn key(dep: PackageId) -> (&'static str, SourceId) {
255280
(dep.name().as_str(), dep.source_id())
256281
}
@@ -259,6 +284,10 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
259284
a.iter().filter(|a| !contains_id(b, a)).cloned().collect()
260285
}
261286

287+
fn vec_intersection(a: &[PackageId], b: &[PackageId]) -> Vec<PackageId> {
288+
a.iter().filter(|a| contains_id(b, a)).cloned().collect()
289+
}
290+
262291
// Check if a PackageId is present `b` from `a`.
263292
//
264293
// Note that this is somewhat more complicated because the equality for source IDs does not
@@ -288,7 +317,7 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
288317

289318
// Map `(package name, package source)` to `(removed versions, added versions)`.
290319
let mut changes = BTreeMap::new();
291-
let empty = (Vec::new(), Vec::new());
320+
let empty = (Vec::new(), Vec::new(), Vec::new());
292321
for dep in previous_resolve.iter() {
293322
changes
294323
.entry(key(dep))
@@ -305,13 +334,15 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
305334
}
306335

307336
for v in changes.values_mut() {
308-
let (ref mut old, ref mut new) = *v;
337+
let (ref mut old, ref mut new, ref mut other) = *v;
309338
old.sort();
310339
new.sort();
311340
let removed = vec_subset(old, new);
312341
let added = vec_subset(new, old);
342+
let unchanged = vec_intersection(new, old);
313343
*old = removed;
314344
*new = added;
345+
*other = unchanged;
315346
}
316347
debug!("{:#?}", changes);
317348

tests/testsuite/patch.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2430,6 +2430,7 @@ fn can_update_with_alt_reg() {
24302430
"\
24312431
[UPDATING] `alternative` index
24322432
[UPDATING] `dummy-registry` index
2433+
[NOTE] Pass `--verbose` to see 1 unchanged dependencies behind latest
24332434
",
24342435
)
24352436
.run();

tests/testsuite/registry.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,7 @@ fn update_multiple_packages() {
15721572
[UPDATING] `[..]` index
15731573
[UPDATING] a v0.1.0 -> v0.1.1
15741574
[UPDATING] b v0.1.0 -> v0.1.1
1575+
[NOTE] Pass `--verbose` to see 1 unchanged dependencies behind latest
15751576
",
15761577
)
15771578
.run();

tests/testsuite/replace.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,13 +539,15 @@ fn override_adds_some_deps() {
539539
"\
540540
[UPDATING] git repository `file://[..]`
541541
[UPDATING] `dummy-registry` index
542+
[NOTE] Pass `--verbose` to see 1 unchanged dependencies behind latest
542543
",
543544
)
544545
.run();
545546
p.cargo("update https://github.com/rust-lang/crates.io-index#bar")
546547
.with_stderr(
547548
"\
548549
[UPDATING] `dummy-registry` index
550+
[NOTE] Pass `--verbose` to see 1 unchanged dependencies behind latest
549551
",
550552
)
551553
.run();

tests/testsuite/update.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ fn transitive_minor_update() {
109109
.with_stderr(
110110
"\
111111
[UPDATING] `[..]` index
112+
[NOTE] Pass `--verbose` to see 2 unchanged dependencies behind latest
112113
",
113114
)
114115
.run();
@@ -160,6 +161,7 @@ fn conservative() {
160161
"\
161162
[UPDATING] `[..]` index
162163
[UPDATING] serde v0.1.0 -> v0.1.1
164+
[NOTE] Pass `--verbose` to see 1 unchanged dependencies behind latest
163165
",
164166
)
165167
.run();
@@ -520,6 +522,7 @@ fn update_precise_do_not_force_update_deps() {
520522
"\
521523
[UPDATING] `[..]` index
522524
[UPDATING] serde v0.2.1 -> v0.2.2
525+
[NOTE] Pass `--verbose` to see 1 unchanged dependencies behind latest
523526
",
524527
)
525528
.run();
@@ -898,6 +901,7 @@ fn dry_run_update() {
898901
"\
899902
[UPDATING] `[..]` index
900903
[UPDATING] serde v0.1.0 -> v0.1.1
904+
[NOTE] Pass `--verbose` to see 1 unchanged dependencies behind latest
901905
[WARNING] not updating lockfile due to dry run
902906
",
903907
)
@@ -1522,6 +1526,7 @@ fn report_behind() {
15221526
.with_stderr(
15231527
"\
15241528
[UPDATING] `dummy-registry` index
1529+
[NOTE] Pass `--verbose` to see 1 unchanged dependencies behind latest
15251530
[WARNING] not updating lockfile due to dry run
15261531
",
15271532
)
@@ -1531,6 +1536,7 @@ fn report_behind() {
15311536
.with_stderr(
15321537
"\
15331538
[UPDATING] `dummy-registry` index
1539+
[UNCHANGED] breaking v0.1.1 (latest: v0.2.0)
15341540
[WARNING] not updating lockfile due to dry run
15351541
",
15361542
)
@@ -1566,6 +1572,7 @@ fn update_with_missing_feature() {
15661572
.with_stderr(
15671573
"\
15681574
[UPDATING] `[..]` index
1575+
[NOTE] Pass `--verbose` to see 1 unchanged dependencies behind latest
15691576
",
15701577
)
15711578
.run();

0 commit comments

Comments
 (0)