Skip to content

Commit 1c27185

Browse files
committed
Auto merge of #1931 - thirtythreeforty:printinfo, r=alexcrichton
Compare #1621. Like that pull request, this one solves #984. I have rewritten most of @pyfisch's logic to account for @alexcrichton's comments. Specifically, this code will correctly handle adding/removing multiple versions of one package, as well as several packages with different sources, but the same name. The output looks like this: ``` [georgev@desertvoice cargo]$ cargo update Updating registry `https://github.com/rust-lang/crates.io-index` Updating libc v0.1.8 -> v0.1.10 Updating memchr v0.1.3 -> v0.1.5 Updating num v0.1.26 -> v0.1.27 Updating rand v0.3.9 -> v0.3.10 Updating rustc-serialize v0.3.15 -> v0.3.16 ``` Comments welcome. r? @alexcrichton
2 parents fc66290 + 492b582 commit 1c27185

File tree

4 files changed

+119
-11
lines changed

4 files changed

+119
-11
lines changed

src/cargo/ops/cargo_generate_lockfile.rs

+71-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use std::collections::HashSet;
1+
use std::collections::{HashMap, HashSet};
22
use std::path::Path;
33

44
use core::PackageId;
55
use core::registry::PackageRegistry;
6-
use core::{Source, Resolve};
6+
use core::{Source, Resolve, SourceId};
77
use core::resolver::Method;
88
use ops;
99
use sources::{PathSource};
@@ -91,6 +91,33 @@ pub fn update_lockfile(manifest_path: &Path,
9191
Method::Everything,
9292
Some(&previous_resolve),
9393
Some(&to_avoid)));
94+
95+
// Summarize what is changing for the user.
96+
let print_change = |status: &str, msg: String| {
97+
opts.config.shell().status(status, msg)
98+
};
99+
for (removed, added) in compare_dependency_graphs(&previous_resolve, &resolve) {
100+
if removed.len() == 1 && added.len() == 1 {
101+
if removed[0].source_id().is_git() {
102+
try!(print_change("Updating", format!("{} -> #{}",
103+
removed[0],
104+
&added[0].source_id().precise().unwrap()[..8])));
105+
} else {
106+
try!(print_change("Updating", format!("{} -> v{}",
107+
removed[0],
108+
added[0].version())));
109+
}
110+
}
111+
else {
112+
for package in removed.iter() {
113+
try!(print_change("Removing", format!("{}", package)));
114+
}
115+
for package in added.iter() {
116+
try!(print_change("Adding", format!("{}", package)));
117+
}
118+
}
119+
}
120+
94121
try!(ops::write_pkg_lockfile(&package, &resolve));
95122
return Ok(());
96123

@@ -108,4 +135,46 @@ pub fn update_lockfile(manifest_path: &Path,
108135
None => {}
109136
}
110137
}
138+
139+
fn compare_dependency_graphs<'a>(previous_resolve: &'a Resolve,
140+
resolve: &'a Resolve) ->
141+
Vec<(Vec<&'a PackageId>, Vec<&'a PackageId>)> {
142+
// Map (package name, package source) to (removed versions, added versions).
143+
fn changes_key<'a>(dep: &'a PackageId) -> (&'a str, &'a SourceId) {
144+
(dep.name(), dep.source_id())
145+
}
146+
147+
fn vec_subtract<T>(a: &[T], b: &[T]) -> Vec<T>
148+
where T: Ord + Clone {
149+
let mut result = a.to_owned();
150+
let mut b = b.to_owned();
151+
b.sort();
152+
result.retain(|x| b.binary_search(x).is_err());
153+
result
154+
}
155+
156+
let mut changes = HashMap::new();
157+
158+
for dep in previous_resolve.iter() {
159+
changes.insert(changes_key(dep), (vec![dep], vec![]));
160+
}
161+
for dep in resolve.iter() {
162+
let (_, ref mut added) = *changes.entry(changes_key(dep))
163+
.or_insert_with(|| (vec![], vec![]));
164+
added.push(dep);
165+
}
166+
167+
for (_, v) in changes.iter_mut() {
168+
let (ref mut old, ref mut new) = *v;
169+
let removed = vec_subtract(old, new);
170+
let added = vec_subtract(new, old);
171+
*old = removed;
172+
*new = added;
173+
}
174+
175+
// Sort the packages by their names.
176+
let mut packages: Vec<_> = changes.keys().map(|x| *x).collect();
177+
packages.sort();
178+
packages.iter().map(|k| changes[k].clone()).collect()
179+
}
111180
}

tests/support/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,8 @@ pub static RUNNING: &'static str = " Running";
522522
pub static COMPILING: &'static str = " Compiling";
523523
pub static FRESH: &'static str = " Fresh";
524524
pub static UPDATING: &'static str = " Updating";
525+
pub static ADDING: &'static str = " Adding";
526+
pub static REMOVING: &'static str = " Removing";
525527
pub static DOCTEST: &'static str = " Doc-tests";
526528
pub static PACKAGING: &'static str = " Packaging";
527529
pub static DOWNLOADING: &'static str = " Downloading";

tests/test_cargo_compile_git_deps.rs

+21-8
Original file line numberDiff line numberDiff line change
@@ -539,9 +539,12 @@ test!(recompilation {
539539

540540
// Update the dependency and carry on!
541541
assert_that(p.cargo("update"),
542-
execs().with_stdout(&format!("{} git repository `{}`",
542+
execs().with_stdout(&format!("{} git repository `{}`\n\
543+
{} bar v0.5.0 ([..]) -> #[..]\n\
544+
",
543545
UPDATING,
544-
git_project.url())));
546+
git_project.url(),
547+
UPDATING)));
545548
println!("going for the last compile");
546549
assert_that(p.cargo("build"),
547550
execs().with_stdout(&format!("{} bar v0.5.0 ({}#[..])\n\
@@ -657,9 +660,12 @@ test!(update_with_shared_deps {
657660
assert_that(p.cargo("update")
658661
.arg("-p").arg("dep1")
659662
.arg("--aggressive"),
660-
execs().with_stdout(&format!("{} git repository `{}`",
663+
execs().with_stdout(&format!("{} git repository `{}`\n\
664+
{} bar v0.5.0 ([..]) -> #[..]\n\
665+
",
661666
UPDATING,
662-
git_project.url())));
667+
git_project.url(),
668+
UPDATING)));
663669

664670
// Make sure we still only compile one version of the git repo
665671
println!("build");
@@ -782,8 +788,12 @@ test!(two_deps_only_update_one {
782788
assert_that(project.cargo("update")
783789
.arg("-p").arg("dep1"),
784790
execs()
785-
.with_stdout(&format!("{} git repository `{}`\n",
786-
UPDATING, git1.url()))
791+
.with_stdout(&format!("{} git repository `{}`\n\
792+
{} dep1 v0.5.0 ([..]) -> #[..]\n\
793+
",
794+
UPDATING,
795+
git1.url(),
796+
UPDATING))
787797
.with_stderr(""));
788798
});
789799

@@ -941,9 +951,12 @@ test!(dep_with_changed_submodule {
941951
assert_that(project.cargo("update").arg("-v"),
942952
execs()
943953
.with_stderr("")
944-
.with_stdout(&format!("{} git repository `{}`",
954+
.with_stdout(&format!("{} git repository `{}`\n\
955+
{} dep1 v0.5.0 ([..]) -> #[..]\n\
956+
",
945957
UPDATING,
946-
git_project.url())));
958+
git_project.url(),
959+
UPDATING)));
947960

948961
println!("last run");
949962
assert_that(project.cargo("run"), execs()

tests/test_cargo_registry.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::io::prelude::*;
33
use cargo::util::process;
44

55
use support::{project, execs, cargo_dir};
6-
use support::{UPDATING, DOWNLOADING, COMPILING, PACKAGING, VERIFYING};
6+
use support::{UPDATING, DOWNLOADING, COMPILING, PACKAGING, VERIFYING, ADDING, REMOVING};
77
use support::paths::{self, CargoPathExt};
88
use support::registry as r;
99
use support::git;
@@ -476,6 +476,7 @@ test!(update_lockfile {
476476
.arg("-p").arg("bar").arg("--precise").arg("0.0.2"),
477477
execs().with_status(0).with_stdout(&format!("\
478478
{updating} registry `[..]`
479+
{updating} bar v0.0.1 (registry file://[..]) -> v0.0.2
479480
", updating = UPDATING)));
480481

481482
println!("0.0.2 build");
@@ -492,6 +493,7 @@ test!(update_lockfile {
492493
.arg("-p").arg("bar"),
493494
execs().with_status(0).with_stdout(&format!("\
494495
{updating} registry `[..]`
496+
{updating} bar v0.0.2 (registry file://[..]) -> v0.0.3
495497
", updating = UPDATING)));
496498

497499
println!("0.0.3 build");
@@ -502,6 +504,27 @@ test!(update_lockfile {
502504
{compiling} foo v0.0.1 ({dir})
503505
", downloading = DOWNLOADING, compiling = COMPILING,
504506
dir = p.url())));
507+
508+
println!("new dependencies update");
509+
r::mock_pkg("bar", "0.0.4", &[("spam", "0.2.5", "")]);
510+
r::mock_pkg("spam", "0.2.5", &[]);
511+
assert_that(p.cargo("update")
512+
.arg("-p").arg("bar"),
513+
execs().with_status(0).with_stdout(&format!("\
514+
{updating} registry `[..]`
515+
{updating} bar v0.0.3 (registry file://[..]) -> v0.0.4
516+
{adding} spam v0.2.5 (registry file://[..])
517+
", updating = UPDATING, adding = ADDING)));
518+
519+
println!("new dependencies update");
520+
r::mock_pkg("bar", "0.0.5", &[]);
521+
assert_that(p.cargo("update")
522+
.arg("-p").arg("bar"),
523+
execs().with_status(0).with_stdout(&format!("\
524+
{updating} registry `[..]`
525+
{updating} bar v0.0.4 (registry file://[..]) -> v0.0.5
526+
{removing} spam v0.2.5 (registry file://[..])
527+
", updating = UPDATING, removing = REMOVING)));
505528
});
506529

507530
test!(dev_dependency_not_used {
@@ -760,6 +783,7 @@ test!(update_transitive_dependency {
760783
execs().with_status(0)
761784
.with_stdout(format!("\
762785
{updating} registry `[..]`
786+
{updating} b v0.1.0 (registry [..]) -> v0.1.1
763787
", updating = UPDATING)));
764788

765789
assert_that(p.cargo("build"),

0 commit comments

Comments
 (0)