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
This commit is contained in:
Alex Crichton 2014-10-13 09:54:08 -07:00
parent 0881adf3ee
commit c2e9996011
2 changed files with 51 additions and 7 deletions

View file

@ -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 => {}

View file

@ -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())));
})