diff --git a/src/cargo/ops/lockfile.rs b/src/cargo/ops/lockfile.rs index 8dc5b45672e..0a7aef5a956 100644 --- a/src/cargo/ops/lockfile.rs +++ b/src/cargo/ops/lockfile.rs @@ -40,10 +40,7 @@ pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()> Ok(s) }); - let toml = toml::Value::try_from(WorkspaceResolve { - ws: ws, - resolve: resolve, - }).unwrap(); + let toml = toml::Value::try_from(WorkspaceResolve { ws, resolve }).unwrap(); let mut out = String::new(); @@ -72,10 +69,7 @@ pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()> // If the lockfile contents haven't changed so don't rewrite it. This is // helpful on read-only filesystems. if let Ok(orig) = orig { - if has_crlf_line_endings(&orig) { - out = out.replace("\n", "\r\n"); - } - if out == orig { + if are_equal_lockfiles(orig, &out, ws.config().lock_update_allowed()) { return Ok(()) } } @@ -97,6 +91,23 @@ pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()> }) } +fn are_equal_lockfiles(mut orig: String, current: &str, lock_update_allowed: bool) -> bool { + if has_crlf_line_endings(&orig) { + orig = orig.replace("\r\n", "\n"); + } + + // Old lockfiles have unused `[root]` section, + // just ignore it if we are in the `--frozen` mode. + if !lock_update_allowed && orig.starts_with("[root]") { + orig = orig.replacen("[root]", "[[package]]", 1); + match (orig.parse::(), current.parse::()) { + (Ok(ref a), Ok(ref b)) if a == b => return true, + _ => {} + } + } + current == orig +} + fn has_crlf_line_endings(s: &str) -> bool { // Only check the first line. if let Some(lf) = s.find('\n') { diff --git a/tests/lockfile-compat.rs b/tests/lockfile-compat.rs index f532e7dfbcd..3f887c9818e 100644 --- a/tests/lockfile-compat.rs +++ b/tests/lockfile-compat.rs @@ -37,8 +37,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "[..]" "#; - let old_lockfile = r#" -[root] + let old_lockfile = +r#"[root] name = "bar" version = "0.0.1" dependencies = [ @@ -62,9 +62,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" foo = "0.1.0" "#) .file("src/lib.rs", "") - .file("Cargo.lock", old_lockfile); - - let p = p.build(); + .file("Cargo.lock", old_lockfile) + .build(); assert_that(p.cargo(cargo_command), execs().with_status(0)); @@ -77,6 +76,54 @@ source = "registry+https://github.com/rust-lang/crates.io-index" assert_eq!(lock.lines().count(), expected_lockfile.lines().count()); } + +#[test] +fn frozen_flag_preserves_old_lockfile() { + Package::new("foo", "0.1.0").publish(); + + let old_lockfile = + r#"[root] +name = "bar" +version = "0.0.1" +dependencies = [ + "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "foo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f9e0a16bdf5c05435698fa27192d89e331b22a26a972c34984f560662544453b" +"#; + + let p = project("bar") + .file("Cargo.toml", r#" + [project] + name = "bar" + version = "0.0.1" + authors = [] + + [dependencies] + foo = "0.1.0" + "#) + .file("src/lib.rs", "") + .file("Cargo.lock", old_lockfile) + .build(); + + assert_that(p.cargo("build").arg("--locked"), + execs().with_status(0)); + + 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()); +} + + #[test] fn totally_wild_checksums_works() { Package::new("foo", "0.1.0").publish();