diff --git a/src/bin/cargo-compile.rs b/src/bin/cargo-compile.rs index d410131e1..818d52ec1 100644 --- a/src/bin/cargo-compile.rs +++ b/src/bin/cargo-compile.rs @@ -14,6 +14,7 @@ extern crate serialize; use std::os; use cargo::{execute_main_without_stdin}; use cargo::ops; +use cargo::core::MultiShell; use cargo::util::{CliResult, CliError}; use cargo::util::important_paths::find_project; @@ -28,7 +29,7 @@ fn main() { execute_main_without_stdin(execute); } -fn execute(options: Options) -> CliResult> { +fn execute(options: Options, shell: &mut MultiShell) -> CliResult> { debug!("executing; cmd=cargo-compile; args={}", os::args()); let root = match options.manifest_path { @@ -42,7 +43,7 @@ fn execute(options: Options) -> CliResult> { })) }; - ops::compile(&root).map(|_| None).map_err(|err| { + ops::compile(&root, shell).map(|_| None).map_err(|err| { CliError::from_boxed(err, 101) }) } diff --git a/src/bin/cargo-git-checkout.rs b/src/bin/cargo-git-checkout.rs index a9a769874..64fefed8c 100644 --- a/src/bin/cargo-git-checkout.rs +++ b/src/bin/cargo-git-checkout.rs @@ -9,6 +9,7 @@ extern crate url; extern crate hammer; use cargo::{execute_main_without_stdin}; +use cargo::core::MultiShell; use cargo::core::source::{Source,SourceId}; use cargo::sources::git::{GitSource}; use cargo::util::{Config, CliResult, CliError, Require, human}; @@ -26,7 +27,7 @@ fn main() { execute_main_without_stdin(execute); } -fn execute(options: Options) -> CliResult> { +fn execute(options: Options, shell: &mut MultiShell) -> CliResult> { let Options { url, reference, .. } = options; let url: Url = try!(from_str(url.as_slice()) @@ -36,8 +37,8 @@ fn execute(options: Options) -> CliResult> { let source_id = SourceId::for_git(&url, reference.as_slice()); - let config = try!(Config::new().map_err(|e| CliError::from_boxed(e, 1))); - let mut source = GitSource::new(&source_id, &config); + let mut config = try!(Config::new(shell).map_err(|e| CliError::from_boxed(e, 1))); + let mut source = GitSource::new(&source_id, &mut config); try!(source.update().map_err(|e| { CliError::new(format!("Couldn't update {}: {}", source, e), 1) diff --git a/src/bin/cargo-read-manifest.rs b/src/bin/cargo-read-manifest.rs index 9772a1275..e77e9cb90 100644 --- a/src/bin/cargo-read-manifest.rs +++ b/src/bin/cargo-read-manifest.rs @@ -8,7 +8,7 @@ extern crate serialize; extern crate hammer; use cargo::{execute_main_without_stdin}; -use cargo::core::{Package, Source, SourceId}; +use cargo::core::{MultiShell, Package, Source, SourceId}; use cargo::util::{CliResult, CliError}; use cargo::sources::{PathSource}; @@ -23,7 +23,7 @@ fn main() { execute_main_without_stdin(execute); } -fn execute(options: Options) -> CliResult> { +fn execute(options: Options, _: &mut MultiShell) -> CliResult> { let path = Path::new(options.manifest_path.as_slice()); let source_id = SourceId::for_path(&path); let mut source = PathSource::new(&source_id); diff --git a/src/bin/cargo.rs b/src/bin/cargo.rs index ffe3f454a..562164e34 100644 --- a/src/bin/cargo.rs +++ b/src/bin/cargo.rs @@ -11,7 +11,8 @@ use hammer::{FlagConfig,FlagConfiguration}; use std::os; use std::io::process::{Command,InheritFd,ExitStatus,ExitSignal}; use serialize::Encodable; -use cargo::{GlobalFlags, NoFlags, execute_main_without_stdin, handle_error}; +use cargo::{GlobalFlags, NoFlags, execute_main_without_stdin, handle_error, shell}; +use cargo::core::MultiShell; use cargo::util::important_paths::find_project; use cargo::util::{CliError, CliResult, Require, config, human}; @@ -34,7 +35,7 @@ fn execute() { let (cmd, args) = match process(os::args()) { Ok((cmd, args)) => (cmd, args), - Err(err) => return handle_error(err, false) + Err(err) => return handle_error(err, &mut shell(), false) }; match cmd.as_slice() { @@ -68,9 +69,9 @@ fn execute() { match command { Ok(ExitStatus(0)) => (), Ok(ExitStatus(i)) | Ok(ExitSignal(i)) => { - handle_error(CliError::new("", i as uint), false) + handle_error(CliError::new("", i as uint), &mut shell(), false) } - Err(_) => handle_error(CliError::new("No such subcommand", 127), false) + Err(_) => handle_error(CliError::new("No such subcommand", 127), &mut shell(), false) } } } @@ -104,7 +105,7 @@ impl FlagConfig for ConfigForKeyFlags { } } -fn config_for_key(args: ConfigForKeyFlags) -> CliResult> { +fn config_for_key(args: ConfigForKeyFlags, _: &mut MultiShell) -> CliResult> { let value = try!(config::get_config(os::getcwd(), args.key.as_slice()).map_err(|_| { CliError::new("Couldn't load configuration", 1) @@ -132,7 +133,7 @@ impl FlagConfig for ConfigListFlags { } } -fn config_list(args: ConfigListFlags) -> CliResult> { +fn config_list(args: ConfigListFlags, _: &mut MultiShell) -> CliResult> { let configs = try!(config::all_configs(os::getcwd()).map_err(|_| CliError::new("Couldn't load configuration", 1))); @@ -146,7 +147,7 @@ fn config_list(args: ConfigListFlags) -> CliResult> { } } -fn locate_project(_: NoFlags) -> CliResult> { +fn locate_project(_: NoFlags, _: &mut MultiShell) -> CliResult> { let root = try!(find_project(os::getcwd(), "Cargo.toml").map_err(|e| { CliError::from_boxed(e, 1) })); diff --git a/src/cargo/core/mod.rs b/src/cargo/core/mod.rs index fd6ff3211..b14bbd6e2 100644 --- a/src/cargo/core/mod.rs +++ b/src/cargo/core/mod.rs @@ -32,6 +32,7 @@ pub use self::summary::{ pub use self::shell::{ Shell, + MultiShell, ShellConfig }; diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 4fe1a7652..1bf19fab6 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -118,7 +118,7 @@ impl Package { ret } - pub fn get_fingerprint(&self, config: &Config) -> CargoResult { + pub fn get_fingerprint(&self, config: &mut Config) -> CargoResult { let mut sources = self.get_source_ids(); // Sort the sources just to make sure we have a consistent fingerprint. sources.sort_by(|a, b| { diff --git a/src/cargo/core/registry.rs b/src/cargo/core/registry.rs index b43d91499..169137df5 100644 --- a/src/cargo/core/registry.rs +++ b/src/cargo/core/registry.rs @@ -1,5 +1,5 @@ use std::vec::Vec; -use core::{Source, SourceId, Summary, Dependency, PackageId, Package}; +use core::{MultiShell, Source, SourceId, Summary, Dependency, PackageId, Package}; use util::{CargoResult, ChainError, Config, human}; pub trait Registry { @@ -15,17 +15,20 @@ impl Registry for Vec { } } -pub struct PackageRegistry { +pub struct PackageRegistry<'a> { sources: Vec>, overrides: Vec, summaries: Vec, - searched: Vec + searched: Vec, + shell: &'a mut MultiShell } -impl PackageRegistry { - pub fn new(source_ids: Vec, - override_ids: Vec) -> CargoResult { - let mut reg = PackageRegistry::empty(); +impl<'a> PackageRegistry<'a> { + pub fn new<'a>(source_ids: Vec, + override_ids: Vec, + shell: &'a mut MultiShell) -> CargoResult> { + + let mut reg = PackageRegistry::empty(shell); for id in source_ids.iter() { try!(reg.load(id, false)); @@ -38,12 +41,13 @@ impl PackageRegistry { Ok(reg) } - fn empty() -> PackageRegistry { + fn empty<'a>(shell: &'a mut MultiShell) -> PackageRegistry<'a> { PackageRegistry { sources: vec!(), overrides: vec!(), summaries: vec!(), - searched: vec!() + searched: vec!(), + shell: shell } } @@ -75,11 +79,10 @@ impl PackageRegistry { Ok(()) } - fn load(&mut self, namespace: &SourceId, - override: bool) -> CargoResult<()> { + fn load(&mut self, namespace: &SourceId, override: bool) -> CargoResult<()> { (|| { - let mut source = namespace.load(&try!(Config::new())); + let mut source = namespace.load(&mut try!(Config::new(self.shell))); let dst = if override {&mut self.overrides} else {&mut self.summaries}; // Ensure the source has fetched all necessary remote data. @@ -103,7 +106,7 @@ impl PackageRegistry { } } -impl Registry for PackageRegistry { +impl<'a> Registry for PackageRegistry<'a> { fn query(&mut self, dep: &Dependency) -> CargoResult> { let overrides = try!(self.overrides.query(dep)); // this can never fail in practice diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs index 32d0f8ed0..8eaeb0332 100644 --- a/src/cargo/core/shell.rs +++ b/src/cargo/core/shell.rs @@ -1,8 +1,9 @@ use term; use term::{Terminal,color}; -use term::color::{Color, BLACK}; -use term::attr::Attr; +use term::color::{Color, BLACK, RED, GREEN}; +use term::attr::{Attr, Bold}; use std::io::{IoResult, stderr}; +use std::fmt::Show; pub struct ShellConfig { pub color: bool, @@ -20,6 +21,39 @@ pub struct Shell { config: ShellConfig } +pub struct MultiShell { + out: Shell, + err: Shell +} + +impl MultiShell { + pub fn new(out: Shell, err: Shell) -> MultiShell { + MultiShell { out: out, err: err } + } + + pub fn out<'a>(&'a mut self) -> &'a mut Shell { + &mut self.out + } + + pub fn err<'a>(&'a mut self) -> &'a mut Shell { + &mut self.err + } + + pub fn say(&mut self, message: T, color: Color) -> IoResult<()> { + self.out().say(message, color) + } + + pub fn status(&mut self, status: T, message: U) -> IoResult<()> { + self.out().say_status(status, message, GREEN) + } + + pub fn error(&mut self, message: T) -> IoResult<()> { + self.err().say(message, RED) + } +} + + + impl Shell { pub fn create(out: Box, config: ShellConfig) -> Shell { if config.tty && config.color { @@ -52,6 +86,17 @@ impl Shell { try!(self.flush()); Ok(()) } + + pub fn say_status(&mut self, status: T, message: U, color: Color) -> IoResult<()> { + try!(self.reset()); + if color != BLACK { try!(self.fg(color)); } + if self.supports_attr(Bold) { try!(self.attr(Bold)); } + try!(self.write_str(format!("{:>12}", status).as_slice())); + try!(self.reset()); + try!(self.write_line(format!(" {}", message).as_slice())); + try!(self.flush()); + Ok(()) + } } impl Terminal> for Shell { diff --git a/src/cargo/core/source.rs b/src/cargo/core/source.rs index ef209186c..31b380473 100644 --- a/src/cargo/core/source.rs +++ b/src/cargo/core/source.rs @@ -115,7 +115,7 @@ impl SourceId { } } - pub fn load(&self, config: &Config) -> Box { + pub fn load(&self, config: &mut Config) -> Box { match self.kind { GitKind(..) => { box GitSource::new(self, config) as Box diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index 694543808..8879bd70f 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -21,12 +21,12 @@ extern crate hamcrest; use serialize::{Decoder, Encoder, Decodable, Encodable, json}; use std::io; -use std::io::stderr; -use std::io::stdio::stderr_raw; +use std::io::{stdout, stderr}; +use std::io::stdio::{stdout_raw, stderr_raw}; use hammer::{FlagDecoder, FlagConfig, UsageDecoder, HammerError}; -use core::{Shell, ShellConfig}; -use term::color::{RED, BLACK}; +use core::{Shell, MultiShell, ShellConfig}; +use term::color::{BLACK}; pub use util::{CargoError, CliError, CliResult, human}; @@ -99,47 +99,55 @@ pub fn execute_main<'a, T: RepresentsFlags, U: RepresentsJSON, V: Encodable, io::IoError>>( - exec: fn(T, U) -> CliResult>) + exec: fn(T, U, &mut MultiShell) -> CliResult>) { fn call<'a, T: RepresentsFlags, U: RepresentsJSON, V: Encodable, io::IoError>>( - exec: fn(T, U) -> CliResult>, + exec: fn(T, U, &mut MultiShell) -> CliResult>, + shell: &mut MultiShell, args: &[String]) -> CliResult> { let flags = try!(flags_from_args::(args)); let json = try!(json_from_stdin::()); - exec(flags, json) + exec(flags, json, shell) } - match global_flags() { - Err(e) => handle_error(e, true), - Ok(val) => process_executed(call(exec, val.rest.as_slice()), val) - } + process::(|rest, shell| call(exec, shell, rest)); } pub fn execute_main_without_stdin<'a, T: RepresentsFlags, V: Encodable, io::IoError>>( - exec: fn(T) -> CliResult>) + exec: fn(T, &mut MultiShell) -> CliResult>) { fn call<'a, T: RepresentsFlags, V: Encodable, io::IoError>>( - exec: fn(T) -> CliResult>, + exec: fn(T, &mut MultiShell) -> CliResult>, + shell: &mut MultiShell, args: &[String]) -> CliResult> { let flags = try!(flags_from_args::(args)); - - exec(flags) + exec(flags, shell) } + process::(|rest, shell| call(exec, shell, rest)); +} + +fn process<'a, + T: RepresentsFlags, + V: Encodable, io::IoError>>( + callback: |&[String], &mut MultiShell| -> CliResult>) { + + let mut shell = shell(); + match global_flags() { - Err(e) => handle_error(e, true), + Err(e) => handle_error(e, &mut shell, true), Ok(val) => { if val.help { let (desc, options) = hammer::usage::(true); @@ -153,7 +161,7 @@ pub fn execute_main_without_stdin<'a, let (_, options) = hammer::usage::(false); print!("{}", options); } else { - process_executed(call(exec, val.rest.as_slice()), val) + process_executed(callback(val.rest.as_slice(), &mut shell), val, &mut shell) } } } @@ -162,10 +170,10 @@ pub fn execute_main_without_stdin<'a, pub fn process_executed<'a, T: Encodable, io::IoError>>( result: CliResult>, - flags: GlobalFlags) + flags: GlobalFlags, shell: &mut MultiShell) { match result { - Err(e) => handle_error(e, flags.verbose), + Err(e) => handle_error(e, shell, flags.verbose), Ok(encodable) => { encodable.map(|encodable| { let encoded = json::Encoder::str_encode(&encodable); @@ -175,38 +183,47 @@ pub fn process_executed<'a, } } -pub fn handle_error(err: CliError, verbose: bool) { - log!(4, "handle_error; err={}", err); - - - let CliError { error, exit_code, unknown, .. } = err; - +pub fn shell() -> MultiShell { let tty = stderr_raw().isatty(); let stderr = box stderr() as Box; let config = ShellConfig { color: true, verbose: false, tty: tty }; - let mut shell = Shell::create(stderr, config); + let err = Shell::create(stderr, config); + + let tty = stdout_raw().isatty(); + let stdout = box stdout() as Box; + + let config = ShellConfig { color: true, verbose: false, tty: tty }; + let out = Shell::create(stdout, config); + + MultiShell::new(out, err) +} + +pub fn handle_error(err: CliError, shell: &mut MultiShell, verbose: bool) { + log!(4, "handle_error; err={}", err); + + let CliError { error, exit_code, unknown, .. } = err; if unknown { - let _ = shell.say("An unknown error occurred", RED); + let _ = shell.error("An unknown error occurred"); } else { - let _ = shell.say(error.to_str(), RED); + let _ = shell.error(error.to_str()); } if unknown && !verbose { - let _ = shell.say("\nTo learn more, run the command again with --verbose.", BLACK); + let _ = shell.err().say("\nTo learn more, run the command again with --verbose.", BLACK); } if verbose { - handle_cause(error, &mut shell); + handle_cause(error, shell); } std::os::set_exit_status(exit_code as int); } -fn handle_cause(err: &CargoError, shell: &mut Shell) { - let _ = shell.say("\nCaused by:", BLACK); - let _ = shell.say(format!(" {}", err.description()), BLACK); +fn handle_cause(err: &CargoError, shell: &mut MultiShell) { + let _ = shell.err().say("\nCaused by:", BLACK); + let _ = shell.err().say(format!(" {}", err.description()), BLACK); err.cause().map(|e| handle_cause(e, shell)); } diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 35b1392f0..416961bfe 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -24,13 +24,13 @@ use std::os; use util::config::{ConfigValue}; -use core::{Source,SourceId,PackageSet,resolver}; +use core::{MultiShell, Source, SourceId, PackageSet, resolver}; use core::registry::PackageRegistry; use ops; use sources::{PathSource}; use util::{CargoResult, Wrap, config, internal, human}; -pub fn compile(manifest_path: &Path) -> CargoResult<()> { +pub fn compile(manifest_path: &Path, shell: &mut MultiShell) -> CargoResult<()> { log!(4, "compile; manifest-path={}", manifest_path.display()); let id = SourceId::for_path(&manifest_path.dir_path()); @@ -45,19 +45,21 @@ pub fn compile(manifest_path: &Path) -> CargoResult<()> { let override_ids = try!(source_ids_from_config()); let source_ids = package.get_source_ids(); - let mut registry = try!(PackageRegistry::new(source_ids, override_ids)); - let resolved = try!(resolver::resolve(package.get_dependencies(), - &mut registry).wrap({ - human("unable to resolve dependencies") - })); + let packages = { + let mut registry = try!(PackageRegistry::new(source_ids, override_ids, shell)); + let resolved = try!(resolver::resolve(package.get_dependencies(), + &mut registry).wrap({ + human("unable to resolve dependencies") + })); - let packages = try!(registry.get(resolved.as_slice()).wrap({ - human("unable to get packages from source") - })); + try!(registry.get(resolved.as_slice()).wrap({ + human("unable to get packages from source") + })) + }; debug!("packages={}", packages); - try!(ops::compile_packages(&package, &PackageSet::new(packages.as_slice()))); + try!(ops::compile_packages(&package, &PackageSet::new(packages.as_slice()), shell)); Ok(()) } diff --git a/src/cargo/ops/cargo_rustc.rs b/src/cargo/ops/cargo_rustc.rs index 334467c3a..804c21e8c 100644 --- a/src/cargo/ops/cargo_rustc.rs +++ b/src/cargo/ops/cargo_rustc.rs @@ -3,7 +3,7 @@ use std::io; use std::io::{File, IoError}; use std::str; -use core::{Package, PackageSet, Target}; +use core::{MultiShell, Package, PackageSet, Target}; use util; use util::{CargoResult, ChainError, ProcessBuilder, internal, human, CargoError}; use util::{Config}; @@ -16,13 +16,13 @@ struct Context<'a> { primary: bool, rustc_version: &'a str, compiled_anything: bool, - config: &'a Config, + config: &'a mut Config<'a> } -pub fn compile_packages(pkg: &Package, deps: &PackageSet) -> CargoResult<()> { +pub fn compile_packages(pkg: &Package, deps: &PackageSet, shell: &mut MultiShell) -> CargoResult<()> { debug!("compile_packages; pkg={}; deps={}", pkg, deps); - let config = try!(Config::new()); + let mut config = try!(Config::new(shell)); let target_dir = pkg.get_absolute_target_dir(); let deps_target_dir = target_dir.join("deps"); @@ -46,7 +46,7 @@ pub fn compile_packages(pkg: &Package, deps: &PackageSet) -> CargoResult<()> { primary: false, rustc_version: rustc_version.as_slice(), compiled_anything: false, - config: &config, + config: &mut config }; // Traverse the dependencies in topological order @@ -78,14 +78,14 @@ fn compile_pkg(pkg: &Package, cx: &mut Context) -> CargoResult<()> { pkg.get_name())); let (is_fresh, fingerprint) = try!(is_fresh(pkg, &fingerprint_loc, cx)); if !cx.compiled_anything && is_fresh { - println!("Skipping fresh {}", pkg); + try!(cx.config.shell().status("Fresh", pkg)); return Ok(()) } // Alright, so this package is not fresh and we need to compile it. Start // off by printing a nice helpful message and then run the custom build // command if one is present. - println!("Compiling {}", pkg); + try!(cx.config.shell().status("Compiling", pkg)); match pkg.get_manifest().get_build() { Some(cmd) => try!(compile_custom(pkg, cmd, cx)), @@ -110,7 +110,7 @@ fn compile_pkg(pkg: &Package, cx: &mut Context) -> CargoResult<()> { } fn is_fresh(dep: &Package, loc: &Path, - cx: &Context) -> CargoResult<(bool, String)> { + cx: &mut Context) -> CargoResult<(bool, String)> { let new_fingerprint = format!("{}{}", cx.rustc_version, try!(dep.get_fingerprint(cx.config))); let mut file = match File::open(loc) { diff --git a/src/cargo/sources/git/source.rs b/src/cargo/sources/git/source.rs index e7949eceb..724be4f41 100644 --- a/src/cargo/sources/git/source.rs +++ b/src/cargo/sources/git/source.rs @@ -15,16 +15,17 @@ use sources::git::utils::{GitReference,GitRemote,Master,Other}; /* TODO: Refactor GitSource to delegate to a PathSource */ -pub struct GitSource { +pub struct GitSource<'a, 'b> { id: SourceId, remote: GitRemote, reference: GitReference, db_path: Path, - checkout_path: Path + checkout_path: Path, + config: &'a mut Config<'b> } -impl GitSource { - pub fn new(source_id: &SourceId, config: &Config) -> GitSource { +impl<'a, 'b> GitSource<'a, 'b> { + pub fn new<'a, 'b>(source_id: &SourceId, config: &'a mut Config<'b>) -> GitSource<'a, 'b> { assert!(source_id.is_git(), "id is not git, id={}", source_id); let reference = match source_id.kind { @@ -46,7 +47,8 @@ impl GitSource { remote: remote, reference: GitReference::for_str(reference.as_slice()), db_path: db_path, - checkout_path: checkout_path + checkout_path: checkout_path, + config: config } } @@ -79,7 +81,7 @@ fn to_hex(num: u64) -> String { writer.get_ref().to_hex() } -impl Show for GitSource { +impl<'a, 'b> Show for GitSource<'a, 'b> { fn fmt(&self, f: &mut Formatter) -> fmt::Result { try!(write!(f, "git repo at {}", self.remote.get_url())); @@ -90,9 +92,11 @@ impl Show for GitSource { } } -impl Source for GitSource { +impl<'a, 'b> Source for GitSource<'a, 'b> { fn update(&mut self) -> CargoResult<()> { - println!("Updating git repository `{}`", self.remote.get_url()); + try!(self.config.shell().status("Updating", + format!("git repository `{}`", self.remote.get_url()))); + log!(5, "updating git source `{}`", self.remote); let repo = try!(self.remote.checkout(&self.db_path)); try!(repo.copy_to(self.reference.as_slice(), &self.checkout_path)); diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs index 4604ec9c5..24fb603e6 100644 --- a/src/cargo/util/config.rs +++ b/src/cargo/util/config.rs @@ -2,19 +2,22 @@ use std::{io,fmt,os}; use std::collections::HashMap; use serialize::{Encodable,Encoder}; use toml; +use core::MultiShell; use util::{CargoResult, CargoError, ChainError, Require, internal, human}; -pub struct Config { - home_path: Path +pub struct Config<'a> { + home_path: Path, + shell: &'a mut MultiShell } -impl Config { - pub fn new() -> CargoResult { +impl<'a> Config<'a> { + pub fn new<'a>(shell: &'a mut MultiShell) -> CargoResult> { Ok(Config { home_path: try!(os::homedir().require(|| { human("Cargo couldn't find your home directory. \ This probably means that $HOME was not set.") - })) + })), + shell: shell }) } @@ -25,6 +28,10 @@ impl Config { pub fn git_checkout_path(&self) -> Path { self.home_path.join(".cargo").join("git").join("checkouts") } + + pub fn shell<'a>(&'a mut self) -> &'a mut MultiShell { + &mut *self.shell + } } #[deriving(Eq,PartialEq,Clone,Encodable,Decodable)] diff --git a/tests/support/mod.rs b/tests/support/mod.rs index b1bc4c0ba..8cac9db37 100644 --- a/tests/support/mod.rs +++ b/tests/support/mod.rs @@ -9,7 +9,6 @@ use std::str; use std::vec::Vec; use std::fmt::Show; use ham = hamcrest; -use cargo::core::shell; use cargo::util::{process,ProcessBuilder}; use cargo::util::ProcessError; @@ -305,8 +304,6 @@ impl<'a> ham::Matcher<&'a [u8]> for ShellWrites { fn matches(&self, actual: &[u8]) -> ham::MatchResult { - use term::Terminal; - println!("{}", actual); let actual = std::str::from_utf8_lossy(actual); let actual = actual.to_str(); diff --git a/tests/test_cargo_compile.rs b/tests/test_cargo_compile.rs index f3a03a3c8..89a0c400c 100644 --- a/tests/test_cargo_compile.rs +++ b/tests/test_cargo_compile.rs @@ -9,6 +9,8 @@ use cargo::util::{process,realpath}; fn setup() { } +static COMPILING: &'static str = " Compiling"; + fn basic_bin_manifest(name: &str) -> String { format!(r#" [project] @@ -143,9 +145,10 @@ test!(cargo_compile_with_warnings_in_a_dep_package { assert_that(p.cargo_process("cargo-compile"), execs() - .with_stdout(format!("Compiling bar v0.5.0 (file:{})\n\ - Compiling foo v0.5.0 (file:{})\n", - bar.display(), main.display())) + .with_stdout(format!("{} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + COMPILING, bar.display(), + COMPILING, main.display())) .with_stderr("")); assert_that(&p.root().join("target/foo"), existing_file()); @@ -343,7 +346,7 @@ test!(custom_build { "#); assert_that(p.cargo_process("cargo-compile"), execs().with_status(0) - .with_stdout(format!("Compiling foo v0.5.0 (file:{})\n", + .with_stdout(format!(" Compiling foo v0.5.0 (file:{})\n", p.root().display())) .with_stderr("")); }) diff --git a/tests/test_cargo_compile_git_deps.rs b/tests/test_cargo_compile_git_deps.rs index 68c105373..48907e5f8 100644 --- a/tests/test_cargo_compile_git_deps.rs +++ b/tests/test_cargo_compile_git_deps.rs @@ -5,6 +5,10 @@ use hamcrest::{assert_that,existing_file}; use cargo; use cargo::util::{ProcessError, process}; +static COMPILING: &'static str = " Compiling"; +static FRESH: &'static str = " Fresh"; +static UPDATING: &'static str = " Updating"; + fn setup() { } @@ -83,11 +87,12 @@ test!(cargo_compile_simple_git_dep { assert_that(project.cargo_process("cargo-compile"), execs() - .with_stdout(format!("Updating git repository `file:{}`\n\ - Compiling dep1 v0.5.0 (file:{})\n\ - Compiling foo v0.5.0 (file:{})\n", - git_root.display(), git_root.display(), - root.display())) + .with_stdout(format!("{} git repository `file:{}`\n\ + {} dep1 v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + UPDATING, git_root.display(), + COMPILING, git_root.display(), + COMPILING, root.display())) .with_stderr("")); assert_that(&project.root().join("target/foo"), existing_file()); @@ -211,31 +216,31 @@ test!(recompilation { // First time around we should compile both foo and bar assert_that(p.cargo_process("cargo-compile"), - execs().with_stdout(format!("Updating git repository `file:{}`\n\ - Compiling bar v0.5.0 (file:{})\n\ - Compiling foo v0.5.0 (file:{})\n", - git_project.root().display(), - git_project.root().display(), - p.root().display()))); + execs().with_stdout(format!("{} git repository `file:{}`\n\ + {} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + UPDATING, git_project.root().display(), + COMPILING, git_project.root().display(), + COMPILING, p.root().display()))); // Don't recompile the second time assert_that(p.process("cargo-compile"), - execs().with_stdout(format!("Updating git repository `file:{}`\n\ - Skipping fresh bar v0.5.0 (file:{})\n\ - Skipping fresh foo v0.5.0 (file:{})\n", - git_project.root().display(), - git_project.root().display(), - p.root().display()))); + execs().with_stdout(format!("{} git repository `file:{}`\n\ + {} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + UPDATING, git_project.root().display(), + FRESH, git_project.root().display(), + FRESH, p.root().display()))); // Modify a file manually, shouldn't trigger a recompile File::create(&git_project.root().join("src/bar.rs")).write_str(r#" pub fn bar() { println!("hello!"); } "#).assert(); assert_that(p.process("cargo-compile"), - execs().with_stdout(format!("Updating git repository `file:{}`\n\ - Skipping fresh bar v0.5.0 (file:{})\n\ - Skipping fresh foo v0.5.0 (file:{})\n", - git_project.root().display(), - git_project.root().display(), - p.root().display()))); + execs().with_stdout(format!("{} git repository `file:{}`\n\ + {} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + UPDATING, git_project.root().display(), + FRESH, git_project.root().display(), + FRESH, p.root().display()))); // Commit the changes and make sure we trigger a recompile File::create(&git_project.root().join("src/bar.rs")).write_str(r#" pub fn bar() { println!("hello!"); } @@ -244,10 +249,10 @@ test!(recompilation { git_project.process("git").args(["commit", "-m", "test"]).exec_with_output() .assert(); assert_that(p.process("cargo-compile"), - execs().with_stdout(format!("Updating git repository `file:{}`\n\ - Compiling bar v0.5.0 (file:{})\n\ - Compiling foo v0.5.0 (file:{})\n", - git_project.root().display(), - git_project.root().display(), - p.root().display()))); + execs().with_stdout(format!("{} git repository `file:{}`\n\ + {} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + UPDATING, git_project.root().display(), + COMPILING, git_project.root().display(), + COMPILING, p.root().display()))); }) diff --git a/tests/test_cargo_compile_path_deps.rs b/tests/test_cargo_compile_path_deps.rs index eabf8276e..c8072a261 100644 --- a/tests/test_cargo_compile_path_deps.rs +++ b/tests/test_cargo_compile_path_deps.rs @@ -9,6 +9,9 @@ use cargo::util::{process}; fn setup() { } +static COMPILING: &'static str = " Compiling"; +static FRESH: &'static str = " Fresh"; + test!(cargo_compile_with_nested_deps_shorthand { let p = project("foo") .file("Cargo.toml", r#" @@ -115,23 +118,23 @@ test!(no_rebuild_dependency { "#); // First time around we should compile both foo and bar assert_that(p.cargo_process("cargo-compile"), - execs().with_stdout(format!("Compiling bar v0.5.0 (file:{})\n\ - Compiling foo v0.5.0 (file:{})\n", - bar.display(), - p.root().display()))); + execs().with_stdout(format!("{} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + COMPILING, bar.display(), + COMPILING, p.root().display()))); // This time we shouldn't compile bar assert_that(p.process("cargo-compile"), - execs().with_stdout(format!("Skipping fresh bar v0.5.0 (file:{})\n\ - Skipping fresh foo v0.5.0 (file:{})\n", - bar.display(), - p.root().display()))); + execs().with_stdout(format!("{} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + FRESH, bar.display(), + FRESH, p.root().display()))); p.build(); // rebuild the files (rewriting them in the process) assert_that(p.process("cargo-compile"), - execs().with_stdout(format!("Compiling bar v0.5.0 (file:{})\n\ - Compiling foo v0.5.0 (file:{})\n", - bar.display(), - p.root().display()))); + execs().with_stdout(format!("{} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + COMPILING, bar.display(), + COMPILING, p.root().display()))); }) test!(deep_dependencies_trigger_rebuild { @@ -183,19 +186,19 @@ test!(deep_dependencies_trigger_rebuild { pub fn baz() {} "#); assert_that(p.cargo_process("cargo-compile"), - execs().with_stdout(format!("Compiling baz v0.5.0 (file:{})\n\ - Compiling bar v0.5.0 (file:{})\n\ - Compiling foo v0.5.0 (file:{})\n", - baz.display(), - bar.display(), - p.root().display()))); + execs().with_stdout(format!("{} baz v0.5.0 (file:{})\n\ + {} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + COMPILING, baz.display(), + COMPILING, bar.display(), + COMPILING, p.root().display()))); assert_that(p.process("cargo-compile"), - execs().with_stdout(format!("Skipping fresh baz v0.5.0 (file:{})\n\ - Skipping fresh bar v0.5.0 (file:{})\n\ - Skipping fresh foo v0.5.0 (file:{})\n", - baz.display(), - bar.display(), - p.root().display()))); + execs().with_stdout(format!("{} baz v0.5.0 (file:{})\n\ + {} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + FRESH, baz.display(), + FRESH, bar.display(), + FRESH, p.root().display()))); // Make sure an update to baz triggers a rebuild of bar // @@ -206,12 +209,12 @@ test!(deep_dependencies_trigger_rebuild { pub fn baz() { println!("hello!"); } "#).assert(); assert_that(p.process("cargo-compile"), - execs().with_stdout(format!("Compiling baz v0.5.0 (file:{})\n\ - Compiling bar v0.5.0 (file:{})\n\ - Compiling foo v0.5.0 (file:{})\n", - baz.display(), - bar.display(), - p.root().display()))); + execs().with_stdout(format!("{} baz v0.5.0 (file:{})\n\ + {} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + COMPILING, baz.display(), + COMPILING, bar.display(), + COMPILING, p.root().display()))); // Make sure an update to bar doesn't trigger baz File::create(&p.root().join("bar/src/bar.rs")).write_str(r#" @@ -219,12 +222,13 @@ test!(deep_dependencies_trigger_rebuild { pub fn bar() { println!("hello!"); baz::baz(); } "#).assert(); assert_that(p.process("cargo-compile"), - execs().with_stdout(format!("Skipping fresh baz v0.5.0 (file:{})\n\ - Compiling bar v0.5.0 (file:{})\n\ - Compiling foo v0.5.0 (file:{})\n", + execs().with_stdout(format!("{} baz v0.5.0 (file:{})\n\ + {} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + FRESH, baz.display(), - bar.display(), - p.root().display()))); + COMPILING, bar.display(), + COMPILING, p.root().display()))); }) test!(no_rebuild_two_deps { @@ -276,17 +280,17 @@ test!(no_rebuild_two_deps { pub fn baz() {} "#); assert_that(p.cargo_process("cargo-compile"), - execs().with_stdout(format!("Compiling baz v0.5.0 (file:{})\n\ - Compiling bar v0.5.0 (file:{})\n\ - Compiling foo v0.5.0 (file:{})\n", - baz.display(), - bar.display(), - p.root().display()))); + execs().with_stdout(format!("{} baz v0.5.0 (file:{})\n\ + {} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + COMPILING, baz.display(), + COMPILING, bar.display(), + COMPILING, p.root().display()))); assert_that(p.process("cargo-compile"), - execs().with_stdout(format!("Skipping fresh baz v0.5.0 (file:{})\n\ - Skipping fresh bar v0.5.0 (file:{})\n\ - Skipping fresh foo v0.5.0 (file:{})\n", - baz.display(), - bar.display(), - p.root().display()))); + execs().with_stdout(format!("{} baz v0.5.0 (file:{})\n\ + {} bar v0.5.0 (file:{})\n\ + {} foo v0.5.0 (file:{})\n", + FRESH, baz.display(), + FRESH, bar.display(), + FRESH, p.root().display()))); })