diff --git a/src/cargo/ops/cargo_generate_lockfile.rs b/src/cargo/ops/cargo_generate_lockfile.rs index 2c97a3dd36b..e15fdca4c39 100644 --- a/src/cargo/ops/cargo_generate_lockfile.rs +++ b/src/cargo/ops/cargo_generate_lockfile.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::path::Path; use core::PackageId; @@ -89,6 +89,18 @@ pub fn update_lockfile(manifest_path: &Path, Method::Everything, Some(&previous_resolve), Some(&to_avoid))); + for dep in compare_dependency_graphs(&previous_resolve, &resolve) { + let (status, msg) = match dep { + (None, Some(pkg)) => ("Adding", format!("{} v{}", pkg.name(), pkg.version())), + (Some(pkg), None) => ("Removing", format!("{} v{}", pkg.name(), pkg.version())), + (Some(pkg1), Some(pkg2)) => { + if pkg1.version() == pkg2.version() { continue } + ("Updating", format!("{} v{} -> v{}", pkg1.name(), pkg1.version(), pkg2.version())) + } + (None, None) => continue, + }; + try!(opts.config.shell().status(status, msg)); + } try!(ops::write_pkg_lockfile(&package, &resolve)); return Ok(()); @@ -106,4 +118,23 @@ pub fn update_lockfile(manifest_path: &Path, None => {} } } + + fn compare_dependency_graphs<'a>(previous_resolve: &'a Resolve, + resolve: &'a Resolve) -> + Vec<(Option<&'a PackageId>, Option<&'a PackageId>)> { + let mut changes = HashMap::new(); + for dep in previous_resolve.iter() { + changes.insert(dep.name(), (Some(dep), None)); + } + for dep in resolve.iter() { + if !changes.contains_key(dep.name()) { + changes.insert(dep.name(), (None, None)); + } + let value = changes.get_mut(dep.name()).unwrap(); + value.1 = Some(dep); + } + let mut package_names: Vec<&str> = changes.keys().map(|x| *x).collect(); + package_names.sort(); + package_names.iter().map(|name| changes[name]).collect() + } } diff --git a/tests/support/mod.rs b/tests/support/mod.rs index fa004f25478..d3353008d57 100644 --- a/tests/support/mod.rs +++ b/tests/support/mod.rs @@ -518,6 +518,8 @@ pub static RUNNING: &'static str = " Running"; pub static COMPILING: &'static str = " Compiling"; pub static FRESH: &'static str = " Fresh"; pub static UPDATING: &'static str = " Updating"; +pub static ADDING: &'static str = " Adding"; +pub static REMOVING: &'static str = " Removing"; pub static DOCTEST: &'static str = " Doc-tests"; pub static PACKAGING: &'static str = " Packaging"; pub static DOWNLOADING: &'static str = " Downloading"; diff --git a/tests/test_cargo_registry.rs b/tests/test_cargo_registry.rs index 4dc750a9981..af82a0e3984 100644 --- a/tests/test_cargo_registry.rs +++ b/tests/test_cargo_registry.rs @@ -3,7 +3,7 @@ use std::io::prelude::*; use cargo::util::process; use support::{project, execs, cargo_dir}; -use support::{UPDATING, DOWNLOADING, COMPILING, PACKAGING, VERIFYING}; +use support::{UPDATING, DOWNLOADING, COMPILING, PACKAGING, VERIFYING, ADDING, REMOVING}; use support::paths::{self, CargoPathExt}; use support::registry as r; use support::git; @@ -476,6 +476,7 @@ test!(update_lockfile { .arg("-p").arg("bar").arg("--precise").arg("0.0.2"), execs().with_status(0).with_stdout(&format!("\ {updating} registry `[..]` +{updating} bar v0.0.1 -> v0.0.2 ", updating = UPDATING))); println!("0.0.2 build"); @@ -492,6 +493,7 @@ test!(update_lockfile { .arg("-p").arg("bar"), execs().with_status(0).with_stdout(&format!("\ {updating} registry `[..]` +{updating} bar v0.0.2 -> v0.0.3 ", updating = UPDATING))); println!("0.0.3 build"); @@ -502,6 +504,27 @@ test!(update_lockfile { {compiling} foo v0.0.1 ({dir}) ", downloading = DOWNLOADING, compiling = COMPILING, dir = p.url()))); + + println!("new dependencies update"); + r::mock_pkg("bar", "0.0.4", &[("spam", "0.2.5", "")]); + r::mock_pkg("spam", "0.2.5", &[]); + assert_that(p.cargo("update") + .arg("-p").arg("bar"), + execs().with_status(0).with_stdout(&format!("\ +{updating} registry `[..]` +{updating} bar v0.0.3 -> v0.0.4 +{adding} spam v0.2.5 +", updating = UPDATING, adding = ADDING))); + + println!("new dependencies update"); + r::mock_pkg("bar", "0.0.5", &[]); + assert_that(p.cargo("update") + .arg("-p").arg("bar"), + execs().with_status(0).with_stdout(&format!("\ +{updating} registry `[..]` +{updating} bar v0.0.4 -> v0.0.5 +{removing} spam v0.2.5 +", updating = UPDATING, removing = REMOVING))); }); test!(dev_dependency_not_used { @@ -760,6 +783,7 @@ test!(update_transitive_dependency { execs().with_status(0) .with_stdout(format!("\ {updating} registry `[..]` +{updating} b v0.1.0 -> v0.1.1 ", updating = UPDATING))); assert_that(p.cargo("build"),