Skip to content

Commit 90fb62f

Browse files
committed
Auto merge of #12796 - dtolnay-contrib:switching, r=epage
Do not call it "Downgrading" when difference is only build metadata ### What does this PR try to resolve? When a `cargo update --precise` changes a dependency between 2 versions which differ only in build metadata, Cargo prints a log referring to it as "Updating" or "Downgrading" the dependency, depending on a comparison between the build metadatas. This is usually not meaningful, given that build metadata is often stuff like git commit hashes, which are not meaningfully ordered. ```console Updating crates.io index Downgrading foo v0.0.1+43ef4fe -> v0.0.1+2c65d16 Updating bar v0.0.2+bc17664 -> v0.0.2+c144a98 ``` ~~This PR changes to the word "Switching" when the version major, minor, patch, and pre-release value are not being changed.~~ This PR uses the word "Updating" when the version major, minor, patch, and pre-release value are unchanged, regardless of whether the build metadata is going up or down. ### How should we test and review this PR? - `cargo test` - `cargo build --release` - `/path/to/cargo/target/release/cargo add tonic_datastore_v1` - `/path/to/cargo/target/release/cargo update -p tonic_datastore_v1 --precise 0.1.0+3562b6cb3` - `/path/to/cargo/target/release/cargo update -p tonic_datastore_v1 --precise 0.1.0+ee9e8e4e6` Before: <img src="https://github.com/rust-lang/cargo/assets/1940490/93e377e7-928e-4cec-aff6-451166ef7c81" width="500"> ~~After:~~ <img src="https://github.com/rust-lang/cargo/assets/1940490/bb71459e-469a-4e09-bb8a-4083f34bce79" width="500"> After: <img src="https://github.com/rust-lang/cargo/assets/1940490/8804e2fe-d0de-4c9e-b463-a5742daf9446" width="500">
2 parents 4ae21bd + f1d2237 commit 90fb62f

File tree

7 files changed

+81
-27
lines changed

7 files changed

+81
-27
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ rand = "0.8.5"
7676
rustfix = "0.6.1"
7777
same-file = "1.0.6"
7878
security-framework = "2.9.2"
79-
semver = { version = "1.0.19", features = ["serde"] }
79+
semver = { version = "1.0.20", features = ["serde"] }
8080
serde = "1.0.188"
8181
serde-untagged = "0.1.1"
8282
serde-value = "0.7.0"

src/cargo/core/package_id.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ struct PackageIdInner {
2929
source_id: SourceId,
3030
}
3131

32-
// Custom equality that uses full equality of SourceId, rather than its custom equality,
33-
// and Version, which usually ignores `build` metadata.
32+
// Custom equality that uses full equality of SourceId, rather than its custom equality.
3433
//
3534
// The `build` part of the version is usually ignored (like a "comment").
3635
// However, there are some cases where it is important. The download path from
@@ -40,11 +39,7 @@ struct PackageIdInner {
4039
impl PartialEq for PackageIdInner {
4140
fn eq(&self, other: &Self) -> bool {
4241
self.name == other.name
43-
&& self.version.major == other.version.major
44-
&& self.version.minor == other.version.minor
45-
&& self.version.patch == other.version.patch
46-
&& self.version.pre == other.version.pre
47-
&& self.version.build == other.version.build
42+
&& self.version == other.version
4843
&& self.source_id.full_eq(other.source_id)
4944
}
5045
}
@@ -53,11 +48,7 @@ impl PartialEq for PackageIdInner {
5348
impl Hash for PackageIdInner {
5449
fn hash<S: hash::Hasher>(&self, into: &mut S) {
5550
self.name.hash(into);
56-
self.version.major.hash(into);
57-
self.version.minor.hash(into);
58-
self.version.patch.hash(into);
59-
self.version.pre.hash(into);
60-
self.version.build.hash(into);
51+
self.version.hash(into);
6152
self.source_id.full_hash(into);
6253
}
6354
}
@@ -237,6 +228,16 @@ impl fmt::Debug for PackageId {
237228
}
238229
}
239230

231+
impl fmt::Debug for PackageIdInner {
232+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
233+
f.debug_struct("PackageIdInner")
234+
.field("name", &self.name)
235+
.field("version", &self.version.to_string())
236+
.field("source", &self.source_id.to_string())
237+
.finish()
238+
}
239+
}
240+
240241
#[cfg(test)]
241242
mod tests {
242243
use super::PackageId;
@@ -261,4 +262,14 @@ mod tests {
261262
let pkg_id = PackageId::new("foo", "1.0.0", SourceId::for_registry(&loc).unwrap()).unwrap();
262263
assert_eq!("foo v1.0.0", pkg_id.to_string());
263264
}
265+
266+
#[test]
267+
fn unequal_build_metadata() {
268+
let loc = CRATES_IO_INDEX.into_url().unwrap();
269+
let repo = SourceId::for_registry(&loc).unwrap();
270+
let first = PackageId::new("foo", "0.0.1+first", repo).unwrap();
271+
let second = PackageId::new("foo", "0.0.1+second", repo).unwrap();
272+
assert_ne!(first, second);
273+
assert_ne!(first.inner, second.inner);
274+
}
264275
}

src/cargo/ops/cargo_generate_lockfile.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::util::config::Config;
88
use crate::util::style;
99
use crate::util::CargoResult;
1010
use anstyle::Style;
11+
use std::cmp::Ordering;
1112
use std::collections::{BTreeMap, HashSet};
1213
use tracing::debug;
1314

@@ -152,7 +153,11 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
152153
format!("{} -> v{}", removed[0], added[0].version())
153154
};
154155

155-
if removed[0].version() > added[0].version() {
156+
// If versions differ only in build metadata, we call it an "update"
157+
// regardless of whether the build metadata has gone up or down.
158+
// This metadata is often stuff like git commit hashes, which are
159+
// not meaningfully ordered.
160+
if removed[0].version().cmp_precedence(added[0].version()) == Ordering::Greater {
156161
print_change("Downgrading", msg, &style::WARN)?;
157162
} else {
158163
print_change("Updating", msg, &style::GOOD)?;

src/cargo/sources/registry/index.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ use cargo_util::{paths, registry::make_dep_path};
9898
use semver::Version;
9999
use serde::Deserialize;
100100
use std::borrow::Cow;
101+
use std::cmp::Ordering;
101102
use std::collections::BTreeMap;
102103
use std::collections::{HashMap, HashSet};
103104
use std::fs;
@@ -674,11 +675,8 @@ impl<'cfg> RegistryIndex<'cfg> {
674675
(true, true) => s_vers == requested,
675676
(true, false) => false,
676677
(false, true) => {
677-
// Strip out the metadata.
678-
s_vers.major == requested.major
679-
&& s_vers.minor == requested.minor
680-
&& s_vers.patch == requested.patch
681-
&& s_vers.pre == requested.pre
678+
// Compare disregarding the metadata.
679+
s_vers.cmp_precedence(requested) == Ordering::Equal
682680
}
683681
(false, false) => s_vers == requested,
684682
}

src/cargo/util/semver_ext.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use semver::{Comparator, Op, Version, VersionReq};
22
use serde_untagged::UntaggedEnumVisitor;
3+
use std::cmp::Ordering;
34
use std::fmt::{self, Display};
45

56
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
@@ -83,12 +84,7 @@ impl OptVersionReq {
8384
match self {
8485
OptVersionReq::Any => true,
8586
OptVersionReq::Req(req) => req.matches(version),
86-
OptVersionReq::Locked(v, _) => {
87-
v.major == version.major
88-
&& v.minor == version.minor
89-
&& v.patch == version.patch
90-
&& v.pre == version.pre
91-
}
87+
OptVersionReq::Locked(v, _) => v.cmp_precedence(version) == Ordering::Equal,
9288
}
9389
}
9490
}

tests/testsuite/update.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,50 @@ fn update_precise() {
391391
.run();
392392
}
393393

394+
#[cargo_test]
395+
fn update_precise_build_metadata() {
396+
Package::new("serde", "0.0.1+first").publish();
397+
Package::new("serde", "0.0.1+second").publish();
398+
399+
let p = project()
400+
.file(
401+
"Cargo.toml",
402+
r#"
403+
[package]
404+
name = "foo"
405+
version = "0.0.0"
406+
407+
[dependencies]
408+
serde = "0.0.1"
409+
"#,
410+
)
411+
.file("src/lib.rs", "")
412+
.build();
413+
414+
p.cargo("generate-lockfile").run();
415+
p.cargo("update serde --precise 0.0.1+first").run();
416+
417+
p.cargo("update serde --precise 0.0.1+second")
418+
.with_stderr(
419+
"\
420+
[UPDATING] `[..]` index
421+
[UPDATING] serde v0.0.1+first -> v0.0.1+second
422+
",
423+
)
424+
.run();
425+
426+
// This is not considered "Downgrading". Build metadata are not assumed to
427+
// be ordered.
428+
p.cargo("update serde --precise 0.0.1+first")
429+
.with_stderr(
430+
"\
431+
[UPDATING] `[..]` index
432+
[UPDATING] serde v0.0.1+second -> v0.0.1+first
433+
",
434+
)
435+
.run();
436+
}
437+
394438
#[cargo_test]
395439
fn update_precise_do_not_force_update_deps() {
396440
Package::new("log", "0.1.0").publish();

0 commit comments

Comments
 (0)