From c2e999601161673f738302e727adbc7a06c1539a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 13 Oct 2014 09:54:08 -0700 Subject: [PATCH] Fix updating sources with more than one crate When a source has multiple crates inside of it, `cargo update -p foo` would previously not actually update anything because the extra crates were continuing to lock the source to the same revision. This change updates the "avoid me" logic to avoid *sources*, not *packages*. Closes #697 --- src/cargo/ops/cargo_generate_lockfile.rs | 18 ++++++----- tests/test_cargo_compile_git_deps.rs | 40 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/cargo/ops/cargo_generate_lockfile.rs b/src/cargo/ops/cargo_generate_lockfile.rs index 10095a69dbd..533caed5c9d 100644 --- a/src/cargo/ops/cargo_generate_lockfile.rs +++ b/src/cargo/ops/cargo_generate_lockfile.rs @@ -66,9 +66,10 @@ pub fn update_lockfile(manifest_path: &Path, let mut to_avoid = HashSet::new(); let dep = try!(resolve.query(name)); if opts.aggressive { - fill_with_deps(&resolve, dep, &mut to_avoid); + let mut visited = HashSet::new(); + fill_with_deps(&resolve, dep, &mut to_avoid, &mut visited); } else { - to_avoid.insert(dep); + to_avoid.insert(dep.get_source_id()); match opts.precise { Some(precise) => { sources.push(dep.get_source_id().clone() @@ -78,8 +79,9 @@ pub fn update_lockfile(manifest_path: &Path, } } sources.extend(resolve.iter() - .filter(|p| !to_avoid.contains(p)) - .map(|p| p.get_source_id().clone())); + .map(|p| p.get_source_id()) + .filter(|s| !to_avoid.contains(s)) + .map(|s| s.clone())); } None => sources.extend(package.get_source_ids().into_iter()), } @@ -93,12 +95,14 @@ pub fn update_lockfile(manifest_path: &Path, return Ok(()); fn fill_with_deps<'a>(resolve: &'a Resolve, dep: &'a PackageId, - set: &mut HashSet<&'a PackageId>) { - if !set.insert(dep) { return } + set: &mut HashSet<&'a SourceId>, + visited: &mut HashSet<&'a PackageId>) { + if !visited.insert(dep) { return } + set.insert(dep.get_source_id()); match resolve.deps(dep) { Some(mut deps) => { for dep in deps { - fill_with_deps(resolve, dep, set); + fill_with_deps(resolve, dep, set, visited); } } None => {} diff --git a/tests/test_cargo_compile_git_deps.rs b/tests/test_cargo_compile_git_deps.rs index 05d41377425..8b4da434cd2 100644 --- a/tests/test_cargo_compile_git_deps.rs +++ b/tests/test_cargo_compile_git_deps.rs @@ -1387,3 +1387,43 @@ following: foo:0.[..].0 ")); }) + +test!(update_one_dep_in_repo_with_many_deps { + let foo = git_repo("foo", |project| { + project.file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + "#) + .file("src/lib.rs", "") + .file("a/Cargo.toml", r#" + [package] + name = "a" + version = "0.5.0" + authors = ["wycats@example.com"] + "#) + .file("a/src/lib.rs", "") + }).assert(); + + let p = project("project") + .file("Cargo.toml", format!(r#" + [project] + name = "project" + version = "0.5.0" + authors = [] + [dependencies.foo] + git = '{}' + [dependencies.a] + git = '{}' + "#, foo.url(), foo.url()).as_slice()) + .file("src/main.rs", "fn main() {}"); + + assert_that(p.cargo_process("generate-lockfile"), execs().with_status(0)); + assert_that(p.process(cargo_dir().join("cargo")).arg("update") + .arg("-p").arg("foo"), + execs().with_status(0) + .with_stdout(format!("\ +Updating git repository `{}` +", foo.url()))); +})