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`.
This commit is contained in:
Alex Crichton 2019-11-08 15:48:04 -08:00
parent 8280633db6
commit 366ae3f7ba
4 changed files with 68 additions and 50 deletions

View File

@ -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,
}
}

View File

@ -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);
}

View File

@ -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\
[..]",
),

View File

@ -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"));
}