Do not update semantically equivalent lockfiles with --frozen/--locked.
authorMark Simulacrum <mark.simulacrum@gmail.com>
Sun, 12 Nov 2017 17:57:05 +0000 (10:57 -0700)
committerMark Simulacrum <mark.simulacrum@gmail.com>
Sun, 12 Nov 2017 18:35:40 +0000 (11:35 -0700)
A previous patch in #4684 attempted to fix this, but didn't work for the
case where the [root] crate wasn't the first crate in the sorted package
array.

src/cargo/core/resolver/mod.rs
src/cargo/ops/lockfile.rs
tests/lockfile-compat.rs

index f7f31b6a88f65d394082ac7a8dee89036f0d0fa5..bc299f33386848bc57e0e8d9b5f586522416d003 100644 (file)
@@ -74,6 +74,7 @@ mod encode;
 ///
 /// Each instance of `Resolve` also understands the full set of features used
 /// for each package.
+#[derive(PartialEq)]
 pub struct Resolve {
     graph: Graph<PackageId>,
     replacements: HashMap<PackageId, PackageId>,
index 0a7aef5a95690cf2f571962aa1b4915c9a3ab426..7368bbf8ade8e641e250e5a4509762027450af03 100644 (file)
@@ -69,7 +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 are_equal_lockfiles(orig, &out, ws.config().lock_update_allowed()) {
+        if are_equal_lockfiles(orig, &out, ws) {
             return Ok(())
         }
     }
@@ -91,20 +91,25 @@ pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()>
     })
 }
 
-fn are_equal_lockfiles(mut orig: String, current: &str, lock_update_allowed: bool) -> bool {
+fn are_equal_lockfiles(mut orig: String, current: &str, ws: &Workspace) -> 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::<toml::Value>(), current.parse::<toml::Value>()) {
-            (Ok(ref a), Ok(ref b)) if a == b => return true,
-            _ => {}
+    // If we want to try and avoid updating the lockfile, parse both and
+    // compare them; since this is somewhat expensive, don't do it in the
+    // common case where we can update lockfiles.
+    if !ws.config().lock_update_allowed() {
+        let res: CargoResult<bool> = (|| {
+            let old: resolver::EncodableResolve = toml::from_str(&orig)?;
+            let new: resolver::EncodableResolve = toml::from_str(current)?;
+            Ok(old.into_resolve(ws)? == new.into_resolve(ws)?)
+        })();
+        if let Ok(true) = res {
+            return true;
         }
     }
+
     current == orig
 }
 
index 3f887c9818eb136a6b88067c37de7fba2cda76bc..0c90fd417ad43be4000cd30f7c16a65aa91a9211 100644 (file)
@@ -22,24 +22,24 @@ fn oldest_lockfile_still_works_with_command(cargo_command: &str) {
 
     let expected_lockfile =
 r#"[[package]]
-name = "bar"
+name = "foo"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "zzz"
 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)" = "[..]"
 "#;
 
     let old_lockfile =
 r#"[root]
-name = "bar"
+name = "zzz"
 version = "0.0.1"
 dependencies = [
  "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -54,7 +54,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
     let p = project("bar")
         .file("Cargo.toml", r#"
             [project]
-            name = "bar"
+            name = "zzz"
             version = "0.0.1"
             authors = []
 
@@ -83,7 +83,7 @@ fn frozen_flag_preserves_old_lockfile() {
 
     let old_lockfile =
         r#"[root]
-name = "bar"
+name = "zzz"
 version = "0.0.1"
 dependencies = [
  "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -101,7 +101,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
     let p = project("bar")
         .file("Cargo.toml", r#"
             [project]
-            name = "bar"
+            name = "zzz"
             version = "0.0.1"
             authors = []