]> git.proxmox.com Git - cargo.git/commitdiff
Generate the same lock always in a workspace
authorAlex Crichton <alex@alexcrichton.com>
Fri, 8 Jul 2016 06:11:22 +0000 (23:11 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Fri, 8 Jul 2016 17:23:41 +0000 (10:23 -0700)
Previously the "root" of a lock file would erroneously change over time, so
instead just ensure that the root of a lock file is always the root of the
workspace. Otherwise the contents should always be the same.

Closes #2837

src/cargo/core/resolver/encode.rs
src/cargo/core/resolver/mod.rs
src/cargo/ops/lockfile.rs
tests/workspaces.rs

index fb786bc184597b3dd0ec59abb5c7b4625ab53e6d..256e7a49c0c2f530ed5375a06dcd68462a81e88f 100644 (file)
@@ -200,21 +200,32 @@ impl Decodable for EncodablePackageId {
     }
 }
 
-impl Encodable for Resolve {
+pub struct WorkspaceResolve<'a, 'cfg: 'a> {
+    pub ws: &'a Workspace<'cfg>,
+    pub resolve: &'a Resolve,
+}
+
+impl<'a, 'cfg> Encodable for WorkspaceResolve<'a, 'cfg> {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        let mut ids: Vec<&PackageId> = self.graph.iter().collect();
+        let mut ids: Vec<&PackageId> = self.resolve.graph.iter().collect();
         ids.sort();
 
+        let root = self.ws.members().max_by_key(|member| {
+            member.name()
+        }).unwrap().package_id();
+
         let encodable = ids.iter().filter_map(|&id| {
-            if self.root == *id { return None; }
+            if root == id {
+                return None
+            }
 
-            Some(encodable_resolve_node(id, self))
+            Some(encodable_resolve_node(id, self.resolve))
         }).collect::<Vec<EncodableDependency>>();
 
         EncodableResolve {
             package: Some(encodable),
-            root: encodable_resolve_node(&self.root, self),
-            metadata: self.metadata.clone(),
+            root: encodable_resolve_node(&root, self.resolve),
+            metadata: self.resolve.metadata.clone(),
         }.encode(s)
     }
 }
index 6d992a067ec06529a49d5373e261162b1afb02c9..58cf94e0a1192cd35cda57ced1db6d6c738553f0 100644 (file)
@@ -61,7 +61,7 @@ use util::ChainError;
 use util::graph::{Nodes, Edges};
 
 pub use self::encode::{EncodableResolve, EncodableDependency, EncodablePackageId};
-pub use self::encode::Metadata;
+pub use self::encode::{Metadata, WorkspaceResolve};
 
 mod encode;
 
@@ -674,7 +674,7 @@ fn build_features(s: &Summary, method: &Method)
         match s.features().get(feat) {
             Some(wanted_features) => {
                 for entry in wanted_features {
-                    // If the entry is of the form `foo/bar`, then we just lookup package 
+                    // If the entry is of the form `foo/bar`, then we just lookup package
                     // `foo` and enable its feature `bar`. We also add `foo` to the used
                     // set because `foo` might have been an optional dependency.
                     //
@@ -703,7 +703,7 @@ fn build_features(s: &Summary, method: &Method)
                 deps.entry(feat.to_string()).or_insert(Vec::new());
             }
         }
-        
+
         visited.remove(&feat.to_string());
 
         Ok(())
index 1c3a1f1087fec827acf26a9a60c48b0a2a4243d8..f0a1f72c31253728fb91eea7947434c05c9de950 100644 (file)
@@ -4,6 +4,7 @@ use rustc_serialize::{Encodable, Decodable};
 use toml::{self, Encoder, Value};
 
 use core::{Resolve, resolver, Workspace};
+use core::resolver::WorkspaceResolve;
 use util::{CargoResult, ChainError, human, Filesystem};
 use util::toml as cargo_toml;
 
@@ -33,7 +34,10 @@ pub fn load_pkg_lockfile(ws: &Workspace) -> CargoResult<Option<Resolve>> {
 
 pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()> {
     let mut e = Encoder::new();
-    resolve.encode(&mut e).unwrap();
+    WorkspaceResolve {
+        ws: ws,
+        resolve: resolve,
+    }.encode(&mut e).unwrap();
 
     let mut out = String::new();
 
index c25809cbbf68e300a0214e38d2991976b7e85fd8..3e980547a2a910435956aff2fd35bff8441f42d5 100644 (file)
@@ -1,6 +1,10 @@
+#[macro_use]
 extern crate cargotest;
 extern crate hamcrest;
 
+use std::io::Read;
+use std::fs::File;
+
 use cargotest::support::{project, execs};
 use cargotest::support::registry::Package;
 use hamcrest::{assert_that, existing_file, existing_dir, is_not};
@@ -774,3 +778,49 @@ this may be fixable by ensuring that this crate is depended on by the workspace
 root: [..]
 "));
 }
+
+#[test]
+fn lock_doesnt_change_depending_on_crate() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [project]
+            name = "foo"
+            version = "0.1.0"
+            authors = []
+
+            [workspace]
+            members = ['baz']
+
+            [dependencies]
+            foo = "*"
+        "#)
+        .file("src/lib.rs", "")
+        .file("baz/Cargo.toml", r#"
+            [project]
+            name = "baz"
+            version = "0.1.0"
+            authors = []
+
+            [dependencies]
+            bar = "*"
+        "#)
+        .file("baz/src/lib.rs", "");
+    p.build();
+
+    Package::new("foo", "1.0.0").publish();
+    Package::new("bar", "1.0.0").publish();
+
+    assert_that(p.cargo("build"),
+                execs().with_status(0));
+
+    let mut lockfile = String::new();
+    t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lockfile));
+
+    assert_that(p.cargo("build").cwd(p.root().join("baz")),
+                execs().with_status(0));
+
+    let mut lockfile2 = String::new();
+    t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lockfile2));
+
+    assert_eq!(lockfile, lockfile2);
+}