Generate the same lock always in a workspace

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
This commit is contained in:
Alex Crichton 2016-07-07 23:11:22 -07:00
parent d2636907a8
commit c33dddd505
4 changed files with 76 additions and 11 deletions

View 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 encodable = ids.iter().filter_map(|&id| {
if self.root == *id { return None; }
let root = self.ws.members().max_by_key(|member| {
member.name()
}).unwrap().package_id();
Some(encodable_resolve_node(id, self))
let encodable = ids.iter().filter_map(|&id| {
if root == id {
return None
}
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)
}
}

View 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(())

View 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();

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