mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-25 11:14:46 +00:00
Thread the shell through more of the system
This commit is contained in:
parent
687035657d
commit
19bea0ad0c
@ -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<Option<()>> {
|
||||
fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
|
||||
debug!("executing; cmd=cargo-compile; args={}", os::args());
|
||||
|
||||
let root = match options.manifest_path {
|
||||
@ -42,7 +43,7 @@ fn execute(options: Options) -> CliResult<Option<()>> {
|
||||
}))
|
||||
};
|
||||
|
||||
ops::compile(&root).map(|_| None).map_err(|err| {
|
||||
ops::compile(&root, shell).map(|_| None).map_err(|err| {
|
||||
CliError::from_boxed(err, 101)
|
||||
})
|
||||
}
|
||||
|
@ -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<Option<()>> {
|
||||
fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
|
||||
let Options { url, reference, .. } = options;
|
||||
|
||||
let url: Url = try!(from_str(url.as_slice())
|
||||
@ -36,8 +37,8 @@ fn execute(options: Options) -> CliResult<Option<()>> {
|
||||
|
||||
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)
|
||||
|
@ -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<Option<Package>> {
|
||||
fn execute(options: Options, _: &mut MultiShell) -> CliResult<Option<Package>> {
|
||||
let path = Path::new(options.manifest_path.as_slice());
|
||||
let source_id = SourceId::for_path(&path);
|
||||
let mut source = PathSource::new(&source_id);
|
||||
|
@ -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<Option<ConfigOut>> {
|
||||
fn config_for_key(args: ConfigForKeyFlags, _: &mut MultiShell) -> CliResult<Option<ConfigOut>> {
|
||||
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<Option<ConfigOut>> {
|
||||
fn config_list(args: ConfigListFlags, _: &mut MultiShell) -> CliResult<Option<ConfigOut>> {
|
||||
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<Option<ConfigOut>> {
|
||||
}
|
||||
}
|
||||
|
||||
fn locate_project(_: NoFlags) -> CliResult<Option<ProjectLocation>> {
|
||||
fn locate_project(_: NoFlags, _: &mut MultiShell) -> CliResult<Option<ProjectLocation>> {
|
||||
let root = try!(find_project(os::getcwd(), "Cargo.toml").map_err(|e| {
|
||||
CliError::from_boxed(e, 1)
|
||||
}));
|
||||
|
@ -32,6 +32,7 @@ pub use self::summary::{
|
||||
|
||||
pub use self::shell::{
|
||||
Shell,
|
||||
MultiShell,
|
||||
ShellConfig
|
||||
};
|
||||
|
||||
|
@ -118,7 +118,7 @@ impl Package {
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn get_fingerprint(&self, config: &Config) -> CargoResult<String> {
|
||||
pub fn get_fingerprint(&self, config: &mut Config) -> CargoResult<String> {
|
||||
let mut sources = self.get_source_ids();
|
||||
// Sort the sources just to make sure we have a consistent fingerprint.
|
||||
sources.sort_by(|a, b| {
|
||||
|
@ -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<Summary> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PackageRegistry {
|
||||
pub struct PackageRegistry<'a> {
|
||||
sources: Vec<Box<Source>>,
|
||||
overrides: Vec<Summary>,
|
||||
summaries: Vec<Summary>,
|
||||
searched: Vec<SourceId>
|
||||
searched: Vec<SourceId>,
|
||||
shell: &'a mut MultiShell
|
||||
}
|
||||
|
||||
impl PackageRegistry {
|
||||
pub fn new(source_ids: Vec<SourceId>,
|
||||
override_ids: Vec<SourceId>) -> CargoResult<PackageRegistry> {
|
||||
let mut reg = PackageRegistry::empty();
|
||||
impl<'a> PackageRegistry<'a> {
|
||||
pub fn new<'a>(source_ids: Vec<SourceId>,
|
||||
override_ids: Vec<SourceId>,
|
||||
shell: &'a mut MultiShell) -> CargoResult<PackageRegistry<'a>> {
|
||||
|
||||
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<Vec<Summary>> {
|
||||
let overrides = try!(self.overrides.query(dep)); // this can never fail in practice
|
||||
|
||||
|
@ -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<T: ToStr>(&mut self, message: T, color: Color) -> IoResult<()> {
|
||||
self.out().say(message, color)
|
||||
}
|
||||
|
||||
pub fn status<T: Show, U: Show>(&mut self, status: T, message: U) -> IoResult<()> {
|
||||
self.out().say_status(status, message, GREEN)
|
||||
}
|
||||
|
||||
pub fn error<T: ToStr>(&mut self, message: T) -> IoResult<()> {
|
||||
self.err().say(message, RED)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl Shell {
|
||||
pub fn create(out: Box<Writer>, config: ShellConfig) -> Shell {
|
||||
if config.tty && config.color {
|
||||
@ -52,6 +86,17 @@ impl Shell {
|
||||
try!(self.flush());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn say_status<T: Show, U: Show>(&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<Box<Writer>> for Shell {
|
||||
|
@ -115,7 +115,7 @@ impl SourceId {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(&self, config: &Config) -> Box<Source> {
|
||||
pub fn load(&self, config: &mut Config) -> Box<Source> {
|
||||
match self.kind {
|
||||
GitKind(..) => {
|
||||
box GitSource::new(self, config) as Box<Source>
|
||||
|
@ -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<json::Encoder<'a>, io::IoError>>(
|
||||
exec: fn(T, U) -> CliResult<Option<V>>)
|
||||
exec: fn(T, U, &mut MultiShell) -> CliResult<Option<V>>)
|
||||
{
|
||||
fn call<'a,
|
||||
T: RepresentsFlags,
|
||||
U: RepresentsJSON,
|
||||
V: Encodable<json::Encoder<'a>, io::IoError>>(
|
||||
exec: fn(T, U) -> CliResult<Option<V>>,
|
||||
exec: fn(T, U, &mut MultiShell) -> CliResult<Option<V>>,
|
||||
shell: &mut MultiShell,
|
||||
args: &[String])
|
||||
-> CliResult<Option<V>>
|
||||
{
|
||||
let flags = try!(flags_from_args::<T>(args));
|
||||
let json = try!(json_from_stdin::<U>());
|
||||
|
||||
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::<T, V>(|rest, shell| call(exec, shell, rest));
|
||||
}
|
||||
|
||||
pub fn execute_main_without_stdin<'a,
|
||||
T: RepresentsFlags,
|
||||
V: Encodable<json::Encoder<'a>, io::IoError>>(
|
||||
exec: fn(T) -> CliResult<Option<V>>)
|
||||
exec: fn(T, &mut MultiShell) -> CliResult<Option<V>>)
|
||||
{
|
||||
fn call<'a,
|
||||
T: RepresentsFlags,
|
||||
V: Encodable<json::Encoder<'a>, io::IoError>>(
|
||||
exec: fn(T) -> CliResult<Option<V>>,
|
||||
exec: fn(T, &mut MultiShell) -> CliResult<Option<V>>,
|
||||
shell: &mut MultiShell,
|
||||
args: &[String])
|
||||
-> CliResult<Option<V>>
|
||||
{
|
||||
let flags = try!(flags_from_args::<T>(args));
|
||||
|
||||
exec(flags)
|
||||
exec(flags, shell)
|
||||
}
|
||||
|
||||
process::<T, V>(|rest, shell| call(exec, shell, rest));
|
||||
}
|
||||
|
||||
fn process<'a,
|
||||
T: RepresentsFlags,
|
||||
V: Encodable<json::Encoder<'a>, io::IoError>>(
|
||||
callback: |&[String], &mut MultiShell| -> CliResult<Option<V>>) {
|
||||
|
||||
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::<T>(true);
|
||||
@ -153,7 +161,7 @@ pub fn execute_main_without_stdin<'a,
|
||||
let (_, options) = hammer::usage::<GlobalFlags>(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<json::Encoder<'a>, io::IoError>>(
|
||||
result: CliResult<Option<T>>,
|
||||
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<Writer>;
|
||||
|
||||
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<Writer>;
|
||||
|
||||
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));
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
@ -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<Config> {
|
||||
impl<'a> Config<'a> {
|
||||
pub fn new<'a>(shell: &'a mut MultiShell) -> CargoResult<Config<'a>> {
|
||||
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)]
|
||||
|
@ -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();
|
||||
|
@ -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(""));
|
||||
})
|
||||
|
@ -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())));
|
||||
})
|
||||
|
@ -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())));
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user