diff --git a/src/cargo/ops/cargo_generate_lockfile.rs b/src/cargo/ops/cargo_generate_lockfile.rs index c9a61266a09..741974e3b35 100644 --- a/src/cargo/ops/cargo_generate_lockfile.rs +++ b/src/cargo/ops/cargo_generate_lockfile.rs @@ -69,7 +69,7 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions) -> CargoResult<()> // seems like a pretty hokey reason to single out // the registry as well. let precise = if dep.source_id().is_registry() { - format!("{}={}", dep.name(), precise) + format!("{}={}->{}", dep.name(), dep.version(), precise) } else { precise.to_string() }; diff --git a/src/cargo/sources/registry/index.rs b/src/cargo/sources/registry/index.rs index 857ed9bc616..55da376129c 100644 --- a/src/cargo/sources/registry/index.rs +++ b/src/cargo/sources/registry/index.rs @@ -182,13 +182,20 @@ impl<'cfg> RegistryIndex<'cfg> { .map(|s| s.0.clone()); // Handle `cargo update --precise` here. If specified, our own source - // will have a precise version listed of the form `=` where - // `` is the name of a crate on this source and `` is the + // will have a precise version listed of the form + // `=o->` where `` is the name of a crate on + // this source, `` is the version installed and ` is the // version requested (argument to `--precise`). let summaries = summaries.filter(|s| match source_id.precise() { Some(p) if p.starts_with(&*dep.name()) && p[dep.name().len()..].starts_with('=') => { - let vers = &p[dep.name().len() + 1..]; - s.version().to_string() == vers + let mut vers = p[dep.name().len() + 1..].splitn(2, "->"); + if dep.version_req() + .matches(&Version::parse(vers.next().unwrap()).unwrap()) + { + vers.next().unwrap() == s.version().to_string() + } else { + true + } } _ => true, }); diff --git a/tests/testsuite/update.rs b/tests/testsuite/update.rs index fd106ca0166..053f0888df7 100644 --- a/tests/testsuite/update.rs +++ b/tests/testsuite/update.rs @@ -358,3 +358,58 @@ fn change_package_version() { assert_that(p.cargo("build"), execs().with_status(0)); } + +#[test] +fn update_precise() { + Package::new("log", "0.1.0").publish(); + Package::new("serde", "0.1.0").publish(); + Package::new("serde", "0.2.1").publish(); + + let p = project("foo") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + authors = [] + + [dependencies] + serde = "0.2" + foo = { path = "foo" } + "#, + ) + .file("src/lib.rs", "") + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + serde = "0.1" + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + + assert_that(p.cargo("build"), execs().with_status(0)); + + Package::new("serde", "0.2.0").publish(); + + assert_that( + p.cargo("update") + .arg("-p") + .arg("serde:0.2.1") + .arg("--precise") + .arg("0.2.0"), + execs().with_status(0).with_stderr( + "\ +[UPDATING] registry `[..]` +[UPDATING] serde v0.2.1 -> v0.2.0 +", + ), + ); +}