From 366ae3f7bae7e84f6d0d2f9e31f19b0e19c84f4b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 8 Nov 2019 15:48:04 -0800 Subject: [PATCH] Turn the new lock file format on by default This commit enables the support added in #7070 by default. This means that gradually over time all `Cargo.lock` files will be migrated to the new format. Cargo shipped with Rust 1.38.0 supports this new lock file format, so any project using Rust 1.38.0 or above will converge quickly onto the new lock file format and continue working. The main benefit of the new format is to be more friendly to git merge conflicts. Information is deduplicated throughout the lock file to avoid verbose `depedencies` lists and the `checksum` data is all listed inline with `[[package]]`. This has been deployed with rust-lang/rust for some time now and it subjectively at least seems to have greatly reduced the amount of bouncing that happens for touching `Cargo.lock`. --- src/cargo/core/resolver/resolve.rs | 25 ++++++++- tests/testsuite/lockfile_compat.rs | 89 +++++++++++++++--------------- tests/testsuite/publish.rs | 2 +- tests/testsuite/resolve.rs | 2 +- 4 files changed, 68 insertions(+), 50 deletions(-) diff --git a/src/cargo/core/resolver/resolve.rs b/src/cargo/core/resolver/resolve.rs index dcb7cd443..00d7eb5f0 100644 --- a/src/cargo/core/resolver/resolve.rs +++ b/src/cargo/core/resolver/resolve.rs @@ -15,7 +15,6 @@ use super::encode::Metadata; /// /// Each instance of `Resolve` also understands the full set of features used /// for each package. -#[derive(PartialEq)] pub struct Resolve { /// A graph, whose vertices are packages and edges are dependency specifications /// from `Cargo.toml`. We need a `Vec` here because the same package @@ -358,6 +357,26 @@ unable to verify that `{0}` is the same as when the lockfile was generated } } +impl PartialEq for Resolve { + fn eq(&self, other: &Resolve) -> bool { + macro_rules! compare { + ($($fields:ident)* | $($ignored:ident)*) => { + let Resolve { $($fields,)* $($ignored,)* } = self; + $(drop($ignored);)* + $($fields == &other.$fields)&&* + } + } + compare! { + // fields to compare + graph replacements reverse_replacements empty_features features + checksums metadata unused_patches public_dependencies + | + // fields to ignore + version + } + } +} + impl fmt::Debug for Resolve { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(fmt, "graph: {:?}", self.graph)?; @@ -376,7 +395,7 @@ impl ResolveVersion { /// previous `Cargo.lock` files, and generally matches with what we want to /// encode. pub fn default() -> ResolveVersion { - ResolveVersion::V1 + ResolveVersion::V2 } /// Returns whether this encoding version is "from the future". @@ -385,7 +404,7 @@ impl ResolveVersion { /// intended to become the default "soon". pub fn from_the_future(&self) -> bool { match self { - ResolveVersion::V2 => true, + ResolveVersion::V2 => false, ResolveVersion::V1 => false, } } diff --git a/tests/testsuite/lockfile_compat.rs b/tests/testsuite/lockfile_compat.rs index abe4e4397..faf35e435 100644 --- a/tests/testsuite/lockfile_compat.rs +++ b/tests/testsuite/lockfile_compat.rs @@ -10,6 +10,14 @@ fn oldest_lockfile_still_works() { } } +fn assert_lockfiles_eq(expected: &str, actual: &str) { + for (l, r) in expected.lines().zip(actual.lines()) { + assert!(lines_match(l, r), "Lines differ:\n{}\n\n{}", l, r); + } + + assert_eq!(expected.lines().count(), actual.lines().count()); +} + fn oldest_lockfile_still_works_with_command(cargo_command: &str) { Package::new("bar", "0.1.0").publish(); @@ -19,16 +27,14 @@ fn oldest_lockfile_still_works_with_command(cargo_command: &str) { name = "bar" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "[..]" [[package]] name = "foo" version = "0.0.1" dependencies = [ - "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bar", ] - -[metadata] -"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "[..]" "#; let old_lockfile = r#" @@ -65,11 +71,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" p.cargo(cargo_command).run(); let lock = p.read_lockfile(); - for (l, r) in expected_lockfile.lines().zip(lock.lines()) { - assert!(lines_match(l, r), "Lines differ:\n{}\n\n{}", l, r); - } - - assert_eq!(lock.lines().count(), expected_lockfile.lines().count()); + assert_lockfiles_eq(expected_lockfile, &lock); } #[cargo_test] @@ -115,11 +117,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" p.cargo("build --locked").run(); let lock = p.read_lockfile(); - for (l, r) in old_lockfile.lines().zip(lock.lines()) { - assert!(lines_match(l, r), "Lines differ:\n{}\n\n{}", l, r); - } - - assert_eq!(lock.lines().count(), old_lockfile.lines().count()); + assert_lockfiles_eq(&old_lockfile, &lock); } #[cargo_test] @@ -166,26 +164,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" p.cargo("build").run(); let lock = p.read_lockfile(); - assert!(lock.starts_with( - r#" -# This file is automatically @generated by Cargo. + assert_lockfiles_eq( + r#"# This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] name = "bar" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "[..]" [[package]] name = "foo" version = "0.0.1" dependencies = [ - "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bar", ] - -[metadata] -"# - .trim() - )); +"#, + &lock, + ); } #[cargo_test] @@ -413,22 +409,16 @@ fn current_lockfile_format() { name = \"bar\" version = \"0.1.0\" source = \"registry+https://github.com/rust-lang/crates.io-index\" +checksum = \"[..]\" [[package]] name = \"foo\" version = \"0.0.1\" dependencies = [ - \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\", + \"bar\", ] - -[metadata] -\"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\" = \"[..]\""; - - for (l, r) in expected.lines().zip(actual.lines()) { - assert!(lines_match(l, r), "Lines differ:\n{}\n\n{}", l, r); - } - - assert_eq!(actual.lines().count(), expected.lines().count()); +"; + assert_lockfiles_eq(expected, &actual); } #[cargo_test] @@ -447,7 +437,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "foo" version = "0.0.1" dependencies = [ - "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bar", ] "#; @@ -472,7 +462,24 @@ dependencies = [ p.cargo("build").run(); let lock = p.read_lockfile(); - assert!(lock.starts_with(lockfile.trim())); + assert_lockfiles_eq( + r#"# [..] +# [..] +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "[..]" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar", +] +"#, + &lock, + ); } #[cargo_test] @@ -549,11 +556,7 @@ dependencies = [ p.cargo("fetch").run(); let lock = p.read_lockfile(); - for (l, r) in lockfile.lines().zip(lock.lines()) { - assert!(lines_match(l, r), "Lines differ:\n{}\n\n{}", l, r); - } - - assert_eq!(lock.lines().count(), lockfile.lines().count()); + assert_lockfiles_eq(&lockfile, &lock); } #[cargo_test] @@ -624,9 +627,5 @@ dependencies = [ p.cargo("fetch").run(); let lock = p.read_lockfile(); - for (l, r) in lockfile.lines().zip(lock.lines()) { - assert!(lines_match(l, r), "Lines differ:\n{}\n\n{}", l, r); - } - - assert_eq!(lock.lines().count(), lockfile.lines().count()); + assert_lockfiles_eq(&lockfile, &lock); } diff --git a/tests/testsuite/publish.rs b/tests/testsuite/publish.rs index e94cabc07..545f2302c 100644 --- a/tests/testsuite/publish.rs +++ b/tests/testsuite/publish.rs @@ -1171,7 +1171,7 @@ fn publish_git_with_version() { name = \"foo\"\n\ version = \"0.1.0\"\n\ dependencies = [\n\ - \x20\"dep1 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)\",\n\ + \x20\"dep1\",\n\ ]\n\ [..]", ), diff --git a/tests/testsuite/resolve.rs b/tests/testsuite/resolve.rs index f20008ecf..d40094946 100644 --- a/tests/testsuite/resolve.rs +++ b/tests/testsuite/resolve.rs @@ -30,5 +30,5 @@ fn minimal_version_cli() { let lock = p.read_lockfile(); - assert!(lock.contains("dep 1.0.0")); + assert!(!lock.contains("1.1.0")); }