Clean up Cargo's util::errors module

This commit cleans up cargo's error module to reduce the duplication of
`CargoError` and the standard library's `Error` trait. The `CargoError` trait
remains, but only has one methods, `is_human`.

A number of other modifications were made:

* ChainError was altered to work over unboxed closures
* Wrap and Require were removed as they're duplicates of the ChainError
  functionality.
* Many public error types are now private from util::errors as they're only
  returned as boxed trait objects.
* The `concrete` was removed, all calls to `make_human` are now done through a
  newtype `Human` wrapper.
* Cargo's custom `try!` macro was removed.
This commit is contained in:
Alex Crichton 2014-12-21 15:19:44 -08:00
parent bc2ddbb912
commit 9ed3a6ea1d
39 changed files with 459 additions and 496 deletions

View file

@ -2,7 +2,7 @@ use std::io::process::ExitStatus;
use cargo::ops;
use cargo::core::MultiShell;
use cargo::util::{CliResult, CliError, CargoError};
use cargo::util::{CliResult, CliError, Human};
use cargo::util::important_paths::{find_root_manifest_for_cwd};
#[deriving(RustcDecodable)]
@ -76,7 +76,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
Some(err) => {
Err(match err.exit {
Some(ExitStatus(i)) => CliError::new("", i as uint),
_ => CliError::from_boxed(err.concrete().mark_human(), 101)
_ => CliError::from_boxed(box Human(err), 101)
})
}
}

View file

@ -1,5 +1,5 @@
use cargo::core::MultiShell;
use cargo::util::{CliResult, CliError, human, Require};
use cargo::util::{CliResult, CliError, human, ChainError};
use cargo::util::important_paths::{find_root_manifest_for_cwd};
#[deriving(RustcDecodable)]
@ -26,8 +26,9 @@ pub fn execute(flags: LocateProjectFlags,
let root = try!(find_root_manifest_for_cwd(flags.flag_manifest_path));
let string = try!(root.as_str()
.require(|| human("Your project path contains characters \
not representable in Unicode"))
.chain_error(|| human("Your project path contains \
characters not representable in \
Unicode"))
.map_err(|e| CliError::from_boxed(e, 1)));
Ok(Some(ProjectLocation { root: string.to_string() }))

View file

@ -2,7 +2,7 @@ use std::io::process::ExitStatus;
use cargo::ops;
use cargo::core::MultiShell;
use cargo::util::{CliResult, CliError, CargoError};
use cargo::util::{CliResult, CliError, Human};
use cargo::util::important_paths::{find_root_manifest_for_cwd};
#[deriving(RustcDecodable)]
@ -78,7 +78,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
Some(err) => {
Err(match err.exit {
Some(ExitStatus(i)) => CliError::new("", i as uint),
_ => CliError::from_boxed(err.concrete().mark_human(), 101)
_ => CliError::from_boxed(box Human(err), 101)
})
}
}

View file

@ -1,4 +1,5 @@
use semver;
use std::error::{Error, FromError};
use std::hash::Hash;
use std::sync::Arc;
use std::fmt::{mod, Show, Formatter};
@ -34,7 +35,7 @@ impl<E, S: Encoder<E>> Encodable<S, E> for PackageId {
impl<E, D: Decoder<E>> Decodable<D, E> for PackageId {
fn decode(d: &mut D) -> Result<PackageId, E> {
let string: String = raw_try!(Decodable::decode(d));
let string: String = try!(Decodable::decode(d));
let regex = Regex::new(r"^([^ ]+) ([^ ]+) \(([^\)]+)\)$").unwrap();
let captures = regex.captures(string.as_slice()).expect("invalid serialized PackageId");
@ -85,20 +86,28 @@ pub enum PackageIdError {
InvalidNamespace(String)
}
impl CargoError for PackageIdError {
fn description(&self) -> String {
match *self {
impl Error for PackageIdError {
fn description(&self) -> &str { "failed to parse package id" }
fn detail(&self) -> Option<String> {
Some(match *self {
PackageIdError::InvalidVersion(ref v) => {
format!("invalid version: {}", *v)
}
PackageIdError::InvalidNamespace(ref ns) => {
format!("invalid namespace: {}", *ns)
}
}
})
}
}
impl CargoError for PackageIdError {
fn is_human(&self) -> bool { true }
}
impl FromError<PackageIdError> for Box<CargoError> {
fn from_error(t: PackageIdError) -> Box<CargoError> { box t }
}
#[deriving(PartialEq, Hash, Clone, RustcEncodable)]
pub struct Metadata {
pub metadata: String,

View file

@ -3,7 +3,7 @@ use semver::Version;
use url::{mod, Url, UrlParser};
use core::PackageId;
use util::{CargoResult, ToUrl, Require, human, ToSemver};
use util::{CargoResult, ToUrl, human, ToSemver, ChainError};
#[deriving(Clone, PartialEq, Eq)]
pub struct PackageIdSpec {
@ -60,10 +60,10 @@ impl PackageIdSpec {
}
let frag = url.fragment.take();
let (name, version) = {
let path = try!(url.path().require(|| {
let path = try!(url.path().chain_error(|| {
human(format!("pkgid urls must have a path: {}", url))
}));
let path_name = try!(path.last().require(|| {
let path_name = try!(path.last().chain_error(|| {
human(format!("pkgid urls must have at least one path \
component: {}", url))
}));

View file

@ -164,7 +164,7 @@ impl<'a> PackageRegistry<'a> {
}
fn load(&mut self, source_id: &SourceId, kind: Kind) -> CargoResult<()> {
(|| {
(|:| {
let mut source = source_id.load(self.config);
// Ensure the source has fetched all necessary remote data.

View file

@ -112,7 +112,7 @@ impl<E, S: Encoder<E>> Encodable<S, E> for EncodablePackageId {
impl<E, D: Decoder<E>> Decodable<D, E> for EncodablePackageId {
fn decode(d: &mut D) -> Result<EncodablePackageId, E> {
let string: String = raw_try!(Decodable::decode(d));
let string: String = try!(Decodable::decode(d));
let regex = Regex::new(r"^([^ ]+) ([^ ]+)(?: \(([^\)]+)\))?$").unwrap();
let captures = regex.captures(string.as_slice())
.expect("invalid serialized PackageId");

View file

@ -27,7 +27,7 @@ extern crate url;
extern crate registry;
use std::os;
use std::error;
use std::error::Error;
use std::io::stdio::{stdout_raw, stderr_raw};
use std::io::{mod, stdout, stderr};
use rustc_serialize::{Decoder, Encoder, Decodable, Encodable};
@ -56,26 +56,6 @@ mod cargo {
pub use super::util;
}
#[macro_export]
macro_rules! try {
($expr:expr) => ({
use std::error::FromError;
match $expr.map_err(FromError::from_error) {
Ok(val) => val,
Err(err) => return Err(err)
}
})
}
macro_rules! raw_try {
($expr:expr) => ({
match $expr {
Ok(val) => val,
Err(err) => return Err(err)
}
})
}
pub mod core;
pub mod ops;
pub mod sources;
@ -233,12 +213,15 @@ pub fn handle_error(err: CliError, shell: &mut MultiShell) {
std::os::set_exit_status(exit_code as int);
}
fn handle_cause(err: &CargoError, shell: &mut MultiShell) {
let _ = shell.err().say("\nCaused by:", BLACK);
let _ = shell.err().say(format!(" {}", err.description()), BLACK);
fn handle_cause(mut err: &Error, shell: &mut MultiShell) {
loop {
let _ = shell.err().say("\nCaused by:", BLACK);
let _ = shell.err().say(format!(" {}", err.description()), BLACK);
if let Some(e) = err.cause() {
handle_cause(e, shell)
match err.cause() {
Some(e) => err = e,
None => break,
}
}
}
@ -256,6 +239,30 @@ pub fn version() -> String {
fn flags_from_args<'a, T>(usage: &str, args: &[String],
options_first: bool) -> CliResult<T>
where T: Decodable<docopt::Decoder, docopt::Error> {
struct CargoDocoptError { err: docopt::Error }
impl Error for CargoDocoptError {
fn description(&self) -> &str {
match self.err {
docopt::Error::WithProgramUsage(..) => "",
ref e if e.fatal() => self.err.description(),
_ => "",
}
}
fn detail(&self) -> Option<String> {
match self.err {
docopt::Error::WithProgramUsage(_, ref usage) => {
Some(usage.clone())
}
ref e if e.fatal() => None,
ref e => Some(e.to_string())
}
}
}
impl CargoError for CargoDocoptError {
fn is_human(&self) -> bool { true }
}
let docopt = Docopt::new(usage).unwrap()
.options_first(options_first)
.argv(args.iter().map(|s| s.as_slice()))
@ -263,7 +270,7 @@ fn flags_from_args<'a, T>(usage: &str, args: &[String],
.version(Some(version()));
docopt.decode().map_err(|e| {
let code = if e.fatal() {1} else {0};
CliError::from_error(e, code)
CliError::from_error(CargoDocoptError { err: e }, code)
})
}

View file

@ -32,7 +32,7 @@ use core::resolver::Method;
use ops::{mod, BuildOutput};
use sources::{PathSource};
use util::config::{Config, ConfigValue};
use util::{CargoResult, Wrap, config, internal, human, ChainError, profile};
use util::{CargoResult, config, internal, human, ChainError, profile};
/// Contains informations about how a package should be compiled.
pub struct CompileOptions<'a> {
@ -113,7 +113,7 @@ pub fn compile_pkg(package: &Package, options: &mut CompileOptions)
let req: Vec<PackageId> = resolved_with_overrides.iter().map(|r| {
r.clone()
}).collect();
let packages = try!(registry.get(req.as_slice()).wrap({
let packages = try!(registry.get(req.as_slice()).chain_error(|| {
human("Unable to get packages from source")
}));

View file

@ -9,7 +9,7 @@ use flate2::reader::GzDecoder;
use core::source::{Source, SourceId};
use core::{Package, MultiShell};
use sources::PathSource;
use util::{CargoResult, human, internal, ChainError, Require};
use util::{CargoResult, human, internal, ChainError};
use ops;
struct Bomb { path: Option<Path> }
@ -123,7 +123,7 @@ fn tar(pkg: &Package, src: &PathSource, shell: &mut MultiShell,
for file in try!(src.list_files(pkg)).iter() {
if file == dst { continue }
let relative = file.path_relative_from(&root).unwrap();
let relative = try!(relative.as_str().require(|| {
let relative = try!(relative.as_str().chain_error(|| {
human(format!("non-utf8 path in source directory: {}",
relative.display()))
}));

View file

@ -1,7 +1,7 @@
use std::os;
use ops;
use util::{CargoResult, human, process, ProcessError, Require};
use util::{CargoResult, human, process, ProcessError, ChainError};
use core::manifest::TargetKind;
use core::source::Source;
use sources::PathSource;
@ -25,7 +25,7 @@ pub fn run(manifest_path: &Path,
matches_kind && matches_name && a.get_profile().get_env() == env &&
!a.get_profile().is_custom_build()
});
let bin = try!(bins.next().require(|| {
let bin = try!(bins.next().chain_error(|| {
human("a bin target must be available for `cargo run`")
}));
match bins.next() {

View file

@ -6,7 +6,7 @@ use std::str;
use std::sync::Mutex;
use core::{Package, Target, PackageId, PackageSet};
use util::{CargoResult, CargoError, human};
use util::{CargoResult, human, Human};
use util::{internal, ChainError};
use super::job::Work;
@ -137,9 +137,9 @@ pub fn prepare(pkg: &Package, target: &Target, req: Platform,
// And now finally, run the build command itself!
desc_tx.send_opt(p.to_string()).ok();
let output = try!(p.exec_with_output().map_err(|mut e| {
e.msg = format!("Failed to run custom build command for `{}`\n{}",
pkg_name, e.msg);
e.concrete().mark_human()
e.desc = format!("failed to run custom build command for `{}`\n{}",
pkg_name, e.desc);
Human(e)
}));
// After the build command has finished running, we need to be sure to
@ -149,7 +149,7 @@ pub fn prepare(pkg: &Package, target: &Target, req: Platform,
// This is also the location where we provide feedback into the build
// state informing what variables were discovered via our script as
// well.
let output = raw_try!(str::from_utf8(output.output.as_slice()).map_err(|_| {
let output = try!(str::from_utf8(output.output.as_slice()).chain_error(|| {
human("build script output was not valid utf-8")
}));
let parsed_output = try!(BuildOutput::parse(output, pkg_name.as_slice()));

View file

@ -6,7 +6,7 @@ use std::io::fs::PathExtensions;
use core::{Package, Target};
use util;
use util::{CargoResult, Fresh, Dirty, Freshness, internal, Require, profile};
use util::{CargoResult, Fresh, Dirty, Freshness, internal, profile, ChainError};
use super::Kind;
use super::job::Work;
@ -233,7 +233,7 @@ fn calculate_target_fresh(pkg: &Package, dep_info: &Path) -> CargoResult<bool> {
};
let line = line.as_slice();
let mtime = try!(fs::stat(dep_info)).modified;
let pos = try!(line.find_str(": ").require(|| {
let pos = try!(line.find_str(": ").chain_error(|| {
internal(format!("dep-info not in an understood format: {}",
dep_info.display()))
}));

View file

@ -4,8 +4,8 @@ use std::io::{fs, USER_RWX};
use std::io::fs::PathExtensions;
use core::{SourceMap, Package, PackageId, PackageSet, Target, Resolve};
use util::{mod, CargoResult, ProcessBuilder, CargoError, human, caused_human};
use util::{Require, Config, internal, ChainError, Fresh, profile, join_paths};
use util::{mod, CargoResult, ProcessBuilder, human, caused_human};
use util::{Config, internal, ChainError, Fresh, profile, join_paths, Human};
use self::job::{Job, Work};
use self::job_queue::{JobQueue, Stage};
@ -61,7 +61,7 @@ pub fn rustc_old_version() -> CargoResult<(String, String)> {
let triple = output.as_slice().lines().filter(|l| {
l.starts_with("host: ")
}).map(|l| l.slice_from(6)).next();
let triple = try!(triple.require(|| {
let triple = try!(triple.chain_error(|| {
internal("rustc -v didn't have a line for `host:`")
}));
triple.to_string()
@ -80,7 +80,7 @@ pub fn rustc_new_version() -> CargoResult<(String, String)> {
let triple = output.as_slice().lines().filter(|l| {
l.starts_with("host: ")
}).map(|l| l.slice_from(6)).next();
let triple = try!(triple.require(|| {
let triple = try!(triple.chain_error(|| {
internal("rustc -v didn't have a line for `host:`")
}));
triple.to_string()
@ -408,9 +408,9 @@ fn compile_custom_old(pkg: &Package, cmd: &str,
}))
}
try!(p.exec_with_output().map(|_| ()).map_err(|mut e| {
e.msg = format!("Failed to run custom build command for `{}`\n{}",
pkg, e.msg);
e.concrete().mark_human()
e.desc = format!("Failed to run custom build command for `{}`\n{}",
pkg, e.desc);
Human(e)
}));
Ok(())
}))
@ -581,10 +581,10 @@ fn rustdoc(package: &Package, target: &Target,
}))
} else {
try!(rustdoc.exec_with_output().and(Ok(())).map_err(|err| {
match err.output() {
Some(output) => {
caused_human(format!("Could not document `{}`.\n{}",
name, output), err)
match err.exit {
Some(..) => {
caused_human(format!("Could not document `{}`.",
name), err)
}
None => {
caused_human("Failed to run rustdoc", err)

View file

@ -6,7 +6,7 @@ use url::Url;
use git2;
use core::GitReference;
use util::{CargoResult, ChainError, human, ToUrl, internal, Require};
use util::{CargoResult, ChainError, human, ToUrl, internal};
#[deriving(PartialEq, Clone)]
#[allow(missing_copy_implementations)]
@ -182,7 +182,7 @@ impl GitDatabase {
pub fn rev_for(&self, reference: &GitReference) -> CargoResult<GitRevision> {
let id = match *reference {
GitReference::Tag(ref s) => {
try!((|| {
try!((|:| {
let refname = format!("refs/tags/{}", s);
let id = try!(self.repo.refname_to_id(refname.as_slice()));
let tag = try!(self.repo.find_tag(id));
@ -193,10 +193,10 @@ impl GitDatabase {
}))
}
GitReference::Branch(ref s) => {
try!((|| {
try!((|:| {
let b = try!(self.repo.find_branch(s.as_slice(),
git2::BranchType::Local));
b.get().target().require(|| {
b.get().target().chain_error(|| {
human(format!("branch `{}` did not have a target", s))
})
}).chain_error(|| {
@ -294,7 +294,7 @@ impl<'a> GitCheckout<'a> {
for mut child in try!(repo.submodules()).into_iter() {
try!(child.init(false));
let url = try!(child.url().require(|| {
let url = try!(child.url().chain_error(|| {
internal("non-utf8 url for submodule")
}));

View file

@ -174,7 +174,7 @@ use core::{Source, SourceId, PackageId, Package, Summary, Registry};
use core::dependency::{Dependency, Kind};
use sources::{PathSource, git};
use util::{CargoResult, Config, internal, ChainError, ToUrl, human};
use util::{hex, Require, Sha256};
use util::{hex, Sha256};
use ops;
static DEFAULT: &'static str = "https://github.com/rust-lang/crates.io-index";
@ -320,7 +320,7 @@ impl<'a, 'b> RegistrySource<'a, 'b> {
// Verify what we just downloaded
let expected = self.hashes.get(&(pkg.get_name().to_string(),
pkg.get_version().to_string()));
let expected = try!(expected.require(|| {
let expected = try!(expected.chain_error(|| {
internal(format!("no hash listed for {}", pkg))
}));
let actual = {

View file

@ -10,7 +10,7 @@ use rustc_serialize::{Encodable,Encoder};
use toml;
use core::MultiShell;
use ops;
use util::{CargoResult, ChainError, Require, internal, human};
use util::{CargoResult, ChainError, internal, human};
use util::toml as cargo_toml;
@ -37,7 +37,7 @@ impl<'a> Config<'a> {
let (rustc_version, rustc_host) = try!(ops::rustc_version());
Ok(Config {
home_path: try!(homedir().require(|| {
home_path: try!(homedir().chain_error(|| {
human("Cargo couldn't find your home directory. \
This probably means that $HOME was not set.")
})),
@ -159,7 +159,7 @@ impl ConfigValue {
}
toml::Value::Table(val) => {
Ok(CV::Table(try!(val.into_iter().map(|(key, value)| {
let value = raw_try!(CV::from_toml(path, value));
let value = try!(CV::from_toml(path, value));
Ok((key, value))
}).collect::<CargoResult<_>>())))
}
@ -320,7 +320,7 @@ fn walk_tree(pwd: &Path,
// Once we're done, also be sure to walk the home directory even if it's not
// in our history to be sure we pick up that standard location for
// information.
let home = try!(homedir().require(|| {
let home = try!(homedir().chain_error(|| {
human("Cargo couldn't find your home directory. \
This probably means that $HOME was not set.")
}));
@ -338,7 +338,7 @@ fn walk_tree(pwd: &Path,
fn extract_config(mut file: File, key: &str) -> CargoResult<ConfigValue> {
let contents = try!(file.read_to_string());
let mut toml = try!(cargo_toml::parse(contents.as_slice(), file.path()));
let val = try!(toml.remove(&key.to_string()).require(|| internal("")));
let val = try!(toml.remove(&key.to_string()).chain_error(|| internal("")));
CV::from_toml(file.path(), val)
}

View file

@ -1,206 +1,167 @@
use std::io::process::{ProcessOutput, ProcessExit, ExitStatus, ExitSignal};
use std::error::{FromError, Error};
use std::fmt::{mod, Show};
use std::io::IoError;
use std::fmt::{mod, Show, Formatter};
use std::io::process::{ProcessOutput, ProcessExit, ExitStatus, ExitSignal};
use std::str;
use rustc_serialize::json;
use semver;
use std::error::FromError;
use rustc_serialize::json;
use curl;
use docopt;
use toml::Error as TomlError;
use url;
use git2;
pub trait CargoError: Send {
fn description(&self) -> String;
fn detail(&self) -> Option<String> { None }
fn cause(&self) -> Option<&CargoError> { None }
fn is_human(&self) -> bool { false }
pub type CargoResult<T> = Result<T, Box<CargoError>>;
fn concrete(&self) -> ConcreteCargoError {
ConcreteCargoError {
description: self.description(),
detail: self.detail(),
cause: self.cause().map(|c| box c.concrete() as Box<CargoError>),
is_human: self.is_human()
}
}
// =============================================================================
// CargoError trait
pub trait CargoError: Error {
fn is_human(&self) -> bool { false }
}
impl Show for Box<CargoError> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{}", self.description()));
Ok(())
}
}
impl CargoError for Box<CargoError> {
fn description(&self) -> String { (**self).description() }
impl Error for Box<CargoError> {
fn description(&self) -> &str { (**self).description() }
fn detail(&self) -> Option<String> { (**self).detail() }
fn cause(&self) -> Option<&CargoError> { (**self).cause() }
fn cause(&self) -> Option<&Error> { (**self).cause() }
}
impl CargoError for Box<CargoError> {
fn is_human(&self) -> bool { (**self).is_human() }
}
impl CargoError for semver::ReqParseError {
fn description(&self) -> String {
self.to_string()
}
}
pub type CargoResult<T> = Result<T, Box<CargoError>>;
pub trait BoxError<T> {
fn box_error(self) -> CargoResult<T>;
}
// =============================================================================
// Chaining errors
pub trait ChainError<T> {
fn chain_error<E: CargoError>(self, callback: || -> E) -> CargoResult<T> ;
fn chain_error<E, F>(self, callback: F) -> CargoResult<T>
where E: CargoError, F: FnOnce() -> E;
}
impl<'a, T> ChainError<T> for ||:'a -> CargoResult<T> {
fn chain_error<E: CargoError>(self, callback: || -> E) -> CargoResult<T> {
self().map_err(|err| callback().concrete().with_cause(err))
struct ChainedError<E> {
error: E,
cause: Box<Error>,
}
impl<'a, T, F> ChainError<T> for F where F: FnOnce() -> CargoResult<T> {
fn chain_error<E, C>(self, callback: C) -> CargoResult<T>
where E: CargoError, C: FnOnce() -> E {
self().chain_error(callback)
}
}
impl<T, E: CargoError> BoxError<T> for Result<T, E> {
fn box_error(self) -> CargoResult<T> {
self.map_err(|err| box err as Box<CargoError>)
impl<T, E: Error> ChainError<T> for Result<T, E> {
fn chain_error<E2, C>(self, callback: C) -> CargoResult<T>
where E2: CargoError, C: FnOnce() -> E2 {
self.map_err(move |err| {
box ChainedError {
error: callback(),
cause: box err,
} as Box<CargoError>
})
}
}
impl<T, E: CargoError> ChainError<T> for Result<T, E> {
fn chain_error<E: CargoError>(self, callback: || -> E) -> CargoResult<T> {
self.map_err(|err| callback().concrete().with_cause(err))
impl<T> ChainError<T> for Option<T> {
fn chain_error<E, C>(self, callback: C) -> CargoResult<T>
where E: CargoError, C: FnOnce() -> E {
match self {
Some(t) => Ok(t),
None => Err(box callback() as Box<CargoError>),
}
}
}
impl CargoError for IoError {
fn description(&self) -> String { self.to_string() }
impl<E: Error> Error for ChainedError<E> {
fn description(&self) -> &str { self.error.description() }
fn detail(&self) -> Option<String> { self.error.detail() }
fn cause(&self) -> Option<&Error> { Some(&*self.cause) }
}
impl CargoError for TomlError {
fn description(&self) -> String { self.to_string() }
impl<E: CargoError> CargoError for ChainedError<E> {
fn is_human(&self) -> bool { self.error.is_human() }
}
impl CargoError for fmt::Error {
fn description(&self) -> String {
"formatting failed".to_string()
}
}
impl CargoError for curl::ErrCode {
fn description(&self) -> String { self.to_string() }
}
impl CargoError for json::DecoderError {
fn description(&self) -> String { self.to_string() }
}
// =============================================================================
// Process errors
pub struct ProcessError {
pub msg: String,
pub desc: String,
pub exit: Option<ProcessExit>,
pub output: Option<ProcessOutput>,
pub detail: Option<String>,
pub cause: Option<Box<CargoError>>
cause: Option<IoError>,
}
impl Show for ProcessError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let exit = match self.exit {
Some(ExitStatus(i)) | Some(ExitSignal(i)) => i.to_string(),
None => "never executed".to_string()
};
try!(write!(f, "{} (status={})", self.msg, exit));
if let Some(out) = self.output() {
try!(write!(f, "{}", out));
}
Ok(())
impl Error for ProcessError {
fn description(&self) -> &str { self.desc.as_slice() }
fn detail(&self) -> Option<String> { None }
fn cause(&self) -> Option<&Error> {
self.cause.as_ref().map(|s| s as &Error)
}
}
impl ProcessError {
pub fn output(&self) -> Option<String> {
match self.output {
Some(ref out) => {
let mut string = String::new();
match str::from_utf8(out.output.as_slice()) {
Ok(s) if s.trim().len() > 0 => {
string.push_str("\n--- stdout\n");
string.push_str(s);
}
Ok(..) | Err(..) => {}
}
match str::from_utf8(out.error.as_slice()) {
Ok(s) if s.trim().len() > 0 => {
string.push_str("\n--- stderr\n");
string.push_str(s);
}
Ok(..) | Err(..) => {}
}
Some(string)
},
None => None
}
impl fmt::Show for ProcessError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.desc.fmt(f)
}
}
impl CargoError for ProcessError {
fn description(&self) -> String { self.to_string() }
// =============================================================================
// Concrete errors
fn detail(&self) -> Option<String> {
self.detail.clone()
}
fn cause(&self) -> Option<&CargoError> {
self.cause.as_ref().map(|c| { let err: &CargoError = &**c; err })
}
}
pub struct ConcreteCargoError {
struct ConcreteCargoError {
description: String,
detail: Option<String>,
cause: Option<Box<CargoError>>,
is_human: bool
cause: Option<Box<Error>>,
is_human: bool,
}
impl ConcreteCargoError {
pub fn with_cause<E: CargoError>(mut self, err: E) -> Box<CargoError> {
self.cause = Some(box err as Box<CargoError>);
box self as Box<CargoError>
}
pub fn mark_human(mut self) -> Box<CargoError> {
self.is_human = true;
box self as Box<CargoError>
}
}
impl Show for ConcreteCargoError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
impl fmt::Show for ConcreteCargoError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.description)
}
}
impl Error for ConcreteCargoError {
fn description(&self) -> &str { self.description.as_slice() }
fn detail(&self) -> Option<String> { self.detail.clone() }
fn cause(&self) -> Option<&Error> {
self.cause.as_ref().map(|c| &**c)
}
}
impl CargoError for ConcreteCargoError {
fn description(&self) -> String {
self.description.clone()
}
fn detail(&self) -> Option<String> {
self.detail.clone()
}
fn cause(&self) -> Option<&CargoError> {
self.cause.as_ref().map(|c| { let err: &CargoError = &**c; err })
}
fn is_human(&self) -> bool {
self.is_human
}
}
// =============================================================================
// Human errors
pub struct Human<E>(pub E);
impl<E: Error> Error for Human<E> {
fn description(&self) -> &str { self.0.description() }
fn detail(&self) -> Option<String> { self.0.detail() }
fn cause(&self) -> Option<&Error> { self.0.cause() }
}
impl<E: Error> CargoError for Human<E> {
fn is_human(&self) -> bool { true }
}
// =============================================================================
// CLI errors
pub type CliResult<T> = Result<T, CliError>;
#[deriving(Show)]
@ -210,38 +171,10 @@ pub struct CliError {
pub exit_code: uint
}
impl CargoError for CliError {
fn description(&self) -> String {
self.error.to_string()
}
}
impl CargoError for docopt::Error {
fn description(&self) -> String {
match *self {
docopt::Error::WithProgramUsage(ref other, _) => other.description(),
ref e if e.fatal() => self.to_string(),
_ => "".to_string(),
}
}
fn detail(&self) -> Option<String> {
match *self {
docopt::Error::WithProgramUsage(_, ref usage) => Some(usage.clone()),
ref e if e.fatal() => None,
ref e => Some(e.to_string()),
}
}
fn is_human(&self) -> bool { true }
}
impl CargoError for url::ParseError {
fn description(&self) -> String { self.to_string() }
}
impl CargoError for git2::Error {
fn description(&self) -> String { self.to_string() }
impl Error for CliError {
fn description(&self) -> &str { self.error.description() }
fn detail(&self) -> Option<String> { self.error.detail() }
fn cause(&self) -> Option<&Error> { self.error.cause() }
}
impl CliError {
@ -261,16 +194,78 @@ impl CliError {
}
}
// =============================================================================
// various impls
macro_rules! from_error {
($($p:ty,)*) => (
$(impl FromError<$p> for Box<CargoError> {
fn from_error(t: $p) -> Box<CargoError> { box t }
})*
)
}
from_error! {
semver::ReqParseError,
IoError,
ProcessError,
git2::Error,
json::DecoderError,
curl::ErrCode,
CliError,
TomlError,
url::ParseError,
}
impl<E: Error> FromError<Human<E>> for Box<CargoError> {
fn from_error(t: Human<E>) -> Box<CargoError> { box t }
}
impl CargoError for semver::ReqParseError {}
impl CargoError for IoError {}
impl CargoError for git2::Error {}
impl CargoError for json::DecoderError {}
impl CargoError for curl::ErrCode {}
impl CargoError for ProcessError {}
impl CargoError for CliError {}
impl CargoError for TomlError {}
impl CargoError for url::ParseError {}
// =============================================================================
// Construction helpers
pub fn process_error<S: Str>(msg: S,
cause: Option<IoError>,
status: Option<&ProcessExit>,
output: Option<&ProcessOutput>) -> ProcessError {
let exit = match status {
Some(&ExitStatus(i)) | Some(&ExitSignal(i)) => i.to_string(),
None => "never executed".to_string(),
};
let mut desc = format!("{} (status={})", msg.as_slice(), exit);
if let Some(out) = output {
match str::from_utf8(out.output.as_slice()) {
Ok(s) if s.trim().len() > 0 => {
desc.push_str("\n--- stdout\n");
desc.push_str(s);
}
Ok(..) | Err(..) => {}
}
match str::from_utf8(out.error.as_slice()) {
Ok(s) if s.trim().len() > 0 => {
desc.push_str("\n--- stderr\n");
desc.push_str(s);
}
Ok(..) | Err(..) => {}
}
}
ProcessError {
msg: msg.as_slice().to_string(),
exit: status.map(|o| o.clone()),
output: output.map(|o| o.clone()),
detail: None,
cause: cause.map(|c| box c as Box<CargoError>)
desc: desc,
exit: status.map(|a| a.clone()),
output: output.map(|a| a.clone()),
cause: cause,
}
}
@ -281,7 +276,7 @@ pub fn internal_error<S1: Str, S2: Str>(error: S1,
detail: Some(detail.as_slice().to_string()),
cause: None,
is_human: false
} as Box<CargoError>
}
}
pub fn internal<S: Show>(error: S) -> Box<CargoError> {
@ -290,7 +285,7 @@ pub fn internal<S: Show>(error: S) -> Box<CargoError> {
detail: None,
cause: None,
is_human: false
} as Box<CargoError>
}
}
pub fn human<S: Show>(error: S) -> Box<CargoError> {
@ -299,14 +294,14 @@ pub fn human<S: Show>(error: S) -> Box<CargoError> {
detail: None,
cause: None,
is_human: true
} as Box<CargoError>
}
}
pub fn caused_human<S: Show, E: CargoError>(error: S, cause: E) -> Box<CargoError> {
pub fn caused_human<S: Show, E: Error>(error: S, cause: E) -> Box<CargoError> {
box ConcreteCargoError {
description: error.to_string(),
detail: None,
cause: Some(box cause as Box<CargoError>),
cause: Some(box cause as Box<Error>),
is_human: true
} as Box<CargoError>
}
}

View file

@ -1,9 +1,9 @@
pub use self::config::Config;
pub use self::process_builder::{process, ProcessBuilder};
pub use self::result::{Wrap, Require};
pub use self::errors::{CargoResult, CargoError, BoxError, ChainError, CliResult};
pub use self::errors::{CargoResult, CargoError, ChainError, CliResult};
pub use self::errors::{CliError, ProcessError};
pub use self::errors::{process_error, internal_error, internal, human, caused_human};
pub use self::errors::{process_error, internal_error, internal, human};
pub use self::errors::{Human, caused_human};
pub use self::paths::{realpath, join_paths};
pub use self::lev_distance::{lev_distance};
pub use self::hex::{to_hex, short_hash};
@ -23,7 +23,6 @@ pub mod important_paths;
pub mod paths;
pub mod process_builder;
pub mod profile;
pub mod result;
pub mod to_semver;
pub mod to_url;
pub mod toml;

View file

@ -78,7 +78,7 @@ impl ProcessBuilder {
let output = try!(command.output().map_err(|e| {
process_error(format!("Could not execute process `{}`",
self.debug_string()),
self.debug_string()),
Some(e), None, None)
}));

View file

@ -1,27 +0,0 @@
use util::errors::{CargoResult, CargoError};
pub trait Wrap {
fn wrap<E: CargoError>(self, error: E) -> Self;
}
impl<T> Wrap for Result<T, Box<CargoError>> {
fn wrap<E: CargoError>(self, error: E) -> CargoResult<T> {
match self {
Ok(x) => Ok(x),
Err(e) => Err(error.concrete().with_cause(e))
}
}
}
pub trait Require<T> {
fn require<E: CargoError>(self, err: || -> E) -> CargoResult<T>;
}
impl<T> Require<T> for Option<T> {
fn require<E: CargoError>(self, err: || -> E) -> CargoResult<T> {
match self {
Some(x) => Ok(x),
None => Err(box err().concrete() as Box<CargoError>)
}
}
}

View file

@ -15,7 +15,7 @@ use core::{Summary, Manifest, Target, Dependency, PackageId, GitReference};
use core::dependency::Kind;
use core::manifest::{LibKind, Profile, ManifestMetadata};
use core::package_id::Metadata;
use util::{CargoResult, Require, human, ToUrl, ToSemver};
use util::{CargoResult, human, ToUrl, ToSemver, ChainError};
/// Representation of the projects file layout.
///
@ -98,7 +98,7 @@ pub fn to_manifest(contents: &[u8],
Some(path) => path,
None => manifest,
};
let contents = raw_try!(str::from_utf8(contents).map_err(|_| {
let contents = try!(str::from_utf8(contents).chain_error(|| {
human(format!("{} is not valid UTF-8", manifest.display()))
}));
let root = try!(parse(contents, &manifest));
@ -286,7 +286,7 @@ pub struct TomlVersion {
impl<E, D: Decoder<E>> Decodable<D, E> for TomlVersion {
fn decode(d: &mut D) -> Result<TomlVersion, E> {
let s = raw_try!(d.read_str());
let s = try!(d.read_str());
match s.as_slice().to_semver() {
Ok(s) => Ok(TomlVersion { version: s }),
Err(e) => Err(d.error(e.as_slice())),
@ -384,7 +384,7 @@ impl TomlManifest {
let mut nested_paths = vec!();
let project = self.project.as_ref().or_else(|| self.package.as_ref());
let project = try!(project.require(|| {
let project = try!(project.chain_error(|| {
human("No `package` or `project` section found.")
}));

View file

@ -1,3 +1,4 @@
use std::error::Error;
use std::fmt::{mod, Show};
use std::io::fs::{mod, PathExtensions};
use std::io::process::{ProcessOutput};
@ -5,7 +6,7 @@ use std::io;
use std::os;
use std::path::{Path,BytesContainer};
use std::str::{mod, Str};
use std::vec::Vec;
use url::Url;
use hamcrest as ham;
use cargo::util::{process,ProcessBuilder};
@ -398,9 +399,9 @@ impl ham::Matcher<ProcessBuilder> for Execs {
}
Err(e) => {
let mut s = format!("could not exec process {}: {}", process, e);
match e.cause {
match e.cause() {
Some(cause) => s.push_str(format!("\ncaused by: {}",
cause).as_slice()),
cause.description()).as_slice()),
None => {}
}
Err(s)
@ -443,28 +444,6 @@ pub fn shell_writes<T: Show>(string: T) -> ShellWrites {
ShellWrites { expected: string.to_string() }
}
pub trait ResultTest<T,E> {
fn assert(self) -> T;
}
impl<T,E: Show> ResultTest<T,E> for Result<T,E> {
fn assert(self) -> T {
match self {
Ok(val) => val,
Err(err) => panic!("Result was error: {}", err)
}
}
}
impl<T> ResultTest<T,()> for Option<T> {
fn assert(self) -> T {
match self {
Some(val) => val,
None => panic!("Option was None")
}
}
}
pub trait Tap {
fn tap(mut self, callback: |&mut Self|) -> Self;
}

View file

@ -7,7 +7,7 @@ use serialize::hex::ToHex;
use tar::Archive;
use url::Url;
use support::{ResultTest, project};
use support::project;
use support::paths;
use support::git::repo;
use cargo::util::Sha256;
@ -19,12 +19,12 @@ pub fn dl_url() -> Url { Url::from_file_path(&dl_path()).unwrap() }
pub fn init() {
let config = paths::home().join(".cargo/config");
fs::mkdir_recursive(&config.dir_path(), io::USER_DIR).assert();
fs::mkdir_recursive(&config.dir_path(), io::USER_DIR).unwrap();
File::create(&config).write_str(format!(r#"
[registry]
index = "{reg}"
token = "api-token"
"#, reg = registry()).as_slice()).assert();
"#, reg = registry()).as_slice()).unwrap();
// Init a new registry
repo(&registry_path())
@ -57,7 +57,7 @@ pub fn mock_archive(name: &str, version: &str, deps: &[(&str, &str, &str)]) {
p.build();
let dst = mock_archive_dst(name, version);
fs::mkdir_recursive(&dst.dir_path(), io::USER_DIR).assert();
fs::mkdir_recursive(&dst.dir_path(), io::USER_DIR).unwrap();
let f = File::create(&dst).unwrap();
let a = Archive::new(GzEncoder::new(f, Default));
a.append(format!("{}-{}/Cargo.toml", name, version).as_slice(),

View file

@ -6,7 +6,7 @@ use std::str;
use cargo::util::process;
use support::paths;
use support::{execs, project, cargo_dir, mkdir_recursive, ProjectBuilder, ResultTest};
use support::{execs, project, cargo_dir, mkdir_recursive, ProjectBuilder};
use hamcrest::{assert_that};
fn setup() {
@ -16,10 +16,10 @@ fn setup() {
/// TODO: move this to `ProjectBuilder` if other cases using this emerge.
fn fake_executable(proj: ProjectBuilder, dir: &Path, name: &str) -> ProjectBuilder {
let path = proj.root().join(dir).join(format!("{}{}", name, os::consts::EXE_SUFFIX));
mkdir_recursive(&Path::new(path.dirname())).assert();
fs::File::create(&path).assert();
let io::FileStat{perm, ..} = fs::stat(&path).assert();
fs::chmod(&path, io::OTHER_EXECUTE | perm).assert();
mkdir_recursive(&Path::new(path.dirname())).unwrap();
fs::File::create(&path).unwrap();
let io::FileStat{perm, ..} = fs::stat(&path).unwrap();
fs::chmod(&path, io::OTHER_EXECUTE | perm).unwrap();
proj
}
@ -44,8 +44,8 @@ test!(list_commands_looks_at_path {
path.push(proj.root().join("path-test"));
let path = os::join_paths(path.as_slice()).unwrap();
let output = pr.arg("-v").arg("--list").env("PATH", Some(path.as_slice()));
let output = output.exec_with_output().assert();
let output = str::from_utf8(output.output.as_slice()).assert();
let output = output.exec_with_output().unwrap();
let output = str::from_utf8(output.output.as_slice()).unwrap();
assert!(output.contains("\n 1\n"), "missing 1: {}", output);
});
@ -78,14 +78,14 @@ test!(find_closest_dont_correct_nonsense {
test!(override_cargo_home {
let root = paths::root();
let my_home = root.join("my_home");
fs::mkdir(&my_home, USER_RWX).assert();
fs::mkdir(&my_home.join(".cargo"), USER_RWX).assert();
fs::mkdir(&my_home, USER_RWX).unwrap();
fs::mkdir(&my_home.join(".cargo"), USER_RWX).unwrap();
File::create(&my_home.join(".cargo/config")).write_str(r#"
[cargo-new]
name = "foo"
email = "bar"
git = false
"#).assert();
"#).unwrap();
assert_that(process(cargo_dir().join("cargo")).unwrap()
.arg("new").arg("foo")
@ -96,6 +96,6 @@ test!(override_cargo_home {
execs().with_status(0));
let toml = paths::root().join("foo/Cargo.toml");
let toml = File::open(&toml).read_to_string().assert();
let toml = File::open(&toml).read_to_string().unwrap();
assert!(toml.as_slice().contains(r#"authors = ["foo <bar>"]"#));
});

View file

@ -2,7 +2,7 @@ use std::path;
use std::str;
use support::{project, execs, basic_bin_manifest, basic_lib_manifest};
use support::{COMPILING, cargo_dir, ResultTest, FRESH, RUNNING};
use support::{COMPILING, cargo_dir, FRESH, RUNNING};
use support::paths::PathExt;
use hamcrest::{assert_that, existing_file};
use cargo::util::process;
@ -140,8 +140,8 @@ test!(many_similar_names {
#[bench] fn bench_bench(_b: &mut test::Bencher) { foo::foo() }
"#);
let output = p.cargo_process("bench").exec_with_output().assert();
let output = str::from_utf8(output.output.as_slice()).assert();
let output = p.cargo_process("bench").exec_with_output().unwrap();
let output = str::from_utf8(output.output.as_slice()).unwrap();
assert!(output.contains("test bin_bench"), "bin_bench missing\n{}", output);
assert!(output.contains("test lib_bench"), "lib_bench missing\n{}", output);
assert!(output.contains("test bench_bench"), "bench_bench missing\n{}", output);
@ -636,8 +636,8 @@ test!(bin_there_for_integration {
}
"#);
let output = p.cargo_process("bench").exec_with_output().assert();
let output = str::from_utf8(output.output.as_slice()).assert();
let output = p.cargo_process("bench").exec_with_output().unwrap();
let output = str::from_utf8(output.output.as_slice()).unwrap();
assert!(output.contains("main_bench ... bench: 0 ns/iter (+/- 0)"),
"no main_bench\n{}",
output);
@ -717,7 +717,7 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
",
compiling = COMPILING, running = RUNNING,
dir = p.url()).as_slice()));
p.root().move_into_the_past().assert();
p.root().move_into_the_past().unwrap();
assert_that(p.process(cargo_dir().join("cargo")).arg("bench").arg("-v"),
execs().with_status(0)
.with_stdout(format!("\

View file

@ -4,7 +4,7 @@ use std::io::{TcpListener, Listener, Acceptor, BufferedStream};
use std::thread::Thread;
use git2;
use support::{project, execs, ResultTest, UPDATING};
use support::{project, execs, UPDATING};
use support::paths;
use hamcrest::assert_that;
@ -21,8 +21,8 @@ impl Drop for Closer {
// Test that HTTP auth is offered from `credential.helper`
test!(http_auth_offered {
let mut listener = TcpListener::bind("127.0.0.1:0").assert();
let addr = listener.socket_name().assert();
let mut listener = TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.socket_name().unwrap();
let mut a = listener.listen().unwrap();
let a2 = a.clone();
let _c = Closer { a: a2 };
@ -116,7 +116,7 @@ Caused by:
failed to clone into: [..]
Caused by:
[12] [..] status code: 401
[..] status code: 401
",
addr = addr)));
@ -125,8 +125,8 @@ Caused by:
// Boy, sure would be nice to have a TLS implementation in rust!
test!(https_something_happens {
let mut listener = TcpListener::bind("127.0.0.1:0").assert();
let addr = listener.socket_name().assert();
let mut listener = TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.socket_name().unwrap();
let mut a = listener.listen().unwrap();
let a2 = a.clone();
let _c = Closer { a: a2 };
@ -160,7 +160,7 @@ Caused by:
failed to clone into: [..]
Caused by:
[[..]] {errmsg}
{errmsg}
",
addr = addr,
errmsg = if cfg!(windows) {
@ -175,8 +175,8 @@ Caused by:
// Boy, sure would be nice to have an SSH implementation in rust!
test!(ssh_something_happens {
let mut listener = TcpListener::bind("127.0.0.1:0").assert();
let addr = listener.socket_name().assert();
let mut listener = TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.socket_name().unwrap();
let mut a = listener.listen().unwrap();
let a2 = a.clone();
let _c = Closer { a: a2 };
@ -210,7 +210,7 @@ Caused by:
failed to clone into: [..]
Caused by:
[23] Failed to start SSH session: Failed getting banner
Failed to start SSH session: Failed getting banner
",
addr = addr)));
t.join().ok().unwrap();

View file

@ -2,7 +2,7 @@ use std::io::{mod, fs, TempDir, File};
use std::os;
use std::path;
use support::{ResultTest, project, execs, main_file, basic_bin_manifest};
use support::{project, execs, main_file, basic_bin_manifest};
use support::{COMPILING, RUNNING, cargo_dir, ProjectBuilder};
use hamcrest::{assert_that, existing_file};
use support::paths::PathExt;
@ -274,7 +274,7 @@ test!(cargo_compile_with_nested_deps_inferred {
p.cargo_process("build")
.exec_with_output()
.assert();
.unwrap();
assert_that(&p.bin("foo"), existing_file());
@ -332,7 +332,7 @@ test!(cargo_compile_with_nested_deps_correct_bin {
p.cargo_process("build")
.exec_with_output()
.assert();
.unwrap();
assert_that(&p.bin("foo"), existing_file());
@ -399,7 +399,7 @@ test!(cargo_compile_with_nested_deps_shorthand {
p.cargo_process("build")
.exec_with_output()
.assert();
.unwrap();
assert_that(&p.bin("foo"), existing_file());
@ -577,7 +577,7 @@ test!(many_crate_types_old_style_lib_location {
assert_that(p.cargo_process("build"),
execs().with_status(0));
let files = fs::readdir(&p.root().join("target")).assert();
let files = fs::readdir(&p.root().join("target")).unwrap();
let mut files: Vec<String> = files.iter().filter_map(|f| {
match f.filename_str().unwrap() {
"build" | "examples" | "deps" => None,
@ -615,7 +615,7 @@ test!(many_crate_types_correct {
assert_that(p.cargo_process("build"),
execs().with_status(0));
let files = fs::readdir(&p.root().join("target")).assert();
let files = fs::readdir(&p.root().join("target")).unwrap();
let mut files: Vec<String> = files.iter().filter_map(|f| {
match f.filename_str().unwrap() {
"build" | "examples" | "deps" => None,
@ -1196,7 +1196,7 @@ test!(freshness_ignores_excluded {
"#)
.file("src/lib.rs", "pub fn bar() -> int { 1 }");
foo.build();
foo.root().move_into_the_past().assert();
foo.root().move_into_the_past().unwrap();
assert_that(foo.process(cargo_dir().join("cargo")).arg("build"),
execs().with_status(0)
@ -1212,7 +1212,7 @@ test!(freshness_ignores_excluded {
// Modify an ignored file and make sure we don't rebuild
println!("second pass");
File::create(&foo.root().join("src/bar.rs")).assert();
File::create(&foo.root().join("src/bar.rs")).unwrap();
assert_that(foo.process(cargo_dir().join("cargo")).arg("build"),
execs().with_status(0)
.with_stdout(""));
@ -1252,7 +1252,7 @@ test!(rebuild_preserves_out_dir {
"#, build.bin("builder").display()).as_slice())
.file("src/lib.rs", "pub fn bar() -> int { 1 }");
foo.build();
foo.root().move_into_the_past().assert();
foo.root().move_into_the_past().unwrap();
assert_that(foo.process(cargo_dir().join("cargo")).arg("build")
.env("FIRST", Some("1")),
@ -1261,7 +1261,7 @@ test!(rebuild_preserves_out_dir {
{compiling} foo v0.0.0 ({url})
", compiling = COMPILING, url = foo.url())));
File::create(&foo.root().join("src/bar.rs")).assert();
File::create(&foo.root().join("src/bar.rs")).unwrap();
assert_that(foo.process(cargo_dir().join("cargo")).arg("build"),
execs().with_status(0)
.with_stdout(format!("\
@ -1308,7 +1308,7 @@ test!(recompile_space_in_name {
"#)
.file("src/my lib.rs", "");
assert_that(foo.cargo_process("build"), execs().with_status(0));
foo.root().move_into_the_past().assert();
foo.root().move_into_the_past().unwrap();
assert_that(foo.process(cargo_dir().join("cargo")).arg("build"),
execs().with_status(0).with_stdout(""));
});
@ -1387,7 +1387,7 @@ test!(cargo_platform_specific_dependency {
p.cargo_process("build")
.exec_with_output()
.assert();
.unwrap();
assert_that(&p.bin("foo"), existing_file());
@ -1460,7 +1460,7 @@ test!(cargo_platform_specific_dependency_wrong_platform {
p.cargo_process("build")
.exec_with_output()
.assert();
.unwrap();
assert_that(&p.bin("foo"), existing_file());
@ -1469,7 +1469,7 @@ test!(cargo_platform_specific_dependency_wrong_platform {
execs());
let lockfile = p.root().join("Cargo.lock");
let lockfile = File::open(&lockfile).read_to_string().assert();
let lockfile = File::open(&lockfile).read_to_string().unwrap();
assert!(lockfile.as_slice().contains("bar"))
});
@ -1486,14 +1486,14 @@ test!(example_bin_same_name {
p.cargo_process("test").arg("--no-run")
.exec_with_output()
.assert();
.unwrap();
assert_that(&p.bin("foo"), existing_file());
assert_that(&p.bin("examples/foo"), existing_file());
p.process(cargo_dir().join("cargo")).arg("test").arg("--no-run")
.exec_with_output()
.assert();
.unwrap();
assert_that(&p.bin("foo"), existing_file());
assert_that(&p.bin("examples/foo"), existing_file());

View file

@ -35,7 +35,7 @@ test!(custom_build_script_failed {
",
url = p.url(), compiling = COMPILING, running = RUNNING))
.with_stderr(format!("\
Failed to run custom build command for `foo v0.5.0 ({})`
failed to run custom build command for `foo v0.5.0 ({})`
Process didn't exit successfully: `[..]build[..]build-script-build[..]` (status=101)",
p.url())));
});

View file

@ -3,7 +3,7 @@ use std::io::{timer, File};
use std::time::Duration;
use git2;
use support::{ProjectBuilder, ResultTest, project, execs, main_file};
use support::{ProjectBuilder, project, execs, main_file};
use support::{cargo_dir, path2url};
use support::{COMPILING, UPDATING, RUNNING};
use support::paths::PathExt;
@ -94,7 +94,7 @@ test!(cargo_compile_simple_git_dep {
"hello world"
}
"#)
}).assert();
}).unwrap();
let project = project
.file("Cargo.toml", format!(r#"
@ -154,7 +154,7 @@ test!(cargo_compile_git_dep_branch {
"hello world"
}
"#)
}).assert();
}).unwrap();
// Make a new branch based on the current HEAD commit
let repo = git2::Repository::open(&git_project.root()).unwrap();
@ -221,7 +221,7 @@ test!(cargo_compile_git_dep_tag {
"hello world"
}
"#)
}).assert();
}).unwrap();
// Make a tag correponding to the current HEAD
let repo = git2::Repository::open(&git_project.root()).unwrap();
@ -314,7 +314,7 @@ test!(cargo_compile_with_nested_paths {
"hello world"
}
"#)
}).assert();
}).unwrap();
let p = project("parent")
.file("Cargo.toml", format!(r#"
@ -338,7 +338,7 @@ test!(cargo_compile_with_nested_paths {
p.cargo_process("build")
.exec_with_output()
.assert();
.unwrap();
assert_that(&p.bin("parent"), existing_file());
@ -382,7 +382,7 @@ test!(cargo_compile_with_meta_package {
"this is dep2"
}
"#)
}).assert();
}).unwrap();
let p = project("parent")
.file("Cargo.toml", format!(r#"
@ -411,7 +411,7 @@ test!(cargo_compile_with_meta_package {
p.cargo_process("build")
.exec_with_output()
.assert();
.unwrap();
assert_that(&p.bin("parent"), existing_file());
@ -457,7 +457,7 @@ test!(two_revs_same_deps {
authors = []
"#)
.file("src/lib.rs", "pub fn bar() -> int { 1 }")
}).assert();
}).unwrap();
let repo = git2::Repository::open(&bar.root()).unwrap();
let rev1 = repo.revparse_single("HEAD").unwrap().id();
@ -465,7 +465,7 @@ test!(two_revs_same_deps {
// Commit the changes and make sure we trigger a recompile
File::create(&bar.root().join("src/lib.rs")).write_str(r#"
pub fn bar() -> int { 2 }
"#).assert();
"#).unwrap();
add(&repo);
let rev2 = commit(&repo);
@ -533,7 +533,7 @@ test!(recompilation {
.file("src/bar.rs", r#"
pub fn bar() {}
"#)
}).assert();
}).unwrap();
let p = project("foo")
.file("Cargo.toml", format!(r#"
@ -571,7 +571,7 @@ test!(recompilation {
// 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();
"#).unwrap();
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
execs().with_stdout(""));
@ -593,7 +593,7 @@ test!(recompilation {
println!("compile after commit");
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
execs().with_stdout(""));
p.root().move_into_the_past().assert();
p.root().move_into_the_past().unwrap();
// Update the dependency and carry on!
assert_that(p.process(cargo_dir().join("cargo")).arg("update"),
@ -632,7 +632,7 @@ test!(update_with_shared_deps {
.file("src/bar.rs", r#"
pub fn bar() {}
"#)
}).assert();
}).unwrap();
let p = project("foo")
.file("Cargo.toml", r#"
@ -688,7 +688,7 @@ test!(update_with_shared_deps {
// Modify a file manually, and commit it
File::create(&git_project.root().join("src/bar.rs")).write_str(r#"
pub fn bar() { println!("hello!"); }
"#).assert();
"#).unwrap();
let repo = git2::Repository::open(&git_project.root()).unwrap();
let old_head = repo.head().unwrap().target().unwrap();
add(&repo);
@ -744,11 +744,11 @@ test!(dep_with_submodule {
version = "0.5.0"
authors = ["carlhuda@example.com"]
"#)
}).assert();
}).unwrap();
let git_project2 = git_repo("dep2", |project| {
project
.file("lib.rs", "pub fn dep() {}")
}).assert();
}).unwrap();
let repo = git2::Repository::open(&git_project.root()).unwrap();
let url = path2url(git_project2.root()).to_string();
@ -787,7 +787,7 @@ test!(two_deps_only_update_one {
authors = ["carlhuda@example.com"]
"#)
.file("src/lib.rs", "")
}).assert();
}).unwrap();
let git2 = git_repo("dep2", |project| {
project
.file("Cargo.toml", r#"
@ -797,7 +797,7 @@ test!(two_deps_only_update_one {
authors = ["carlhuda@example.com"]
"#)
.file("src/lib.rs", "")
}).assert();
}).unwrap();
let project = project
.file("Cargo.toml", format!(r#"
@ -830,7 +830,7 @@ test!(two_deps_only_update_one {
File::create(&git1.root().join("src/lib.rs")).write_str(r#"
pub fn foo() {}
"#).assert();
"#).unwrap();
let repo = git2::Repository::open(&git1.root()).unwrap();
add(&repo);
commit(&repo);
@ -852,7 +852,7 @@ test!(stale_cached_version {
authors = []
"#)
.file("src/lib.rs", "pub fn bar() -> int { 1 }")
}).assert();
}).unwrap();
// Update the git database in the cache with the current state of the git
// repo
@ -879,7 +879,7 @@ test!(stale_cached_version {
// us pulling it down.
File::create(&bar.root().join("src/lib.rs")).write_str(r#"
pub fn bar() -> int { 1 + 0 }
"#).assert();
"#).unwrap();
let repo = git2::Repository::open(&bar.root()).unwrap();
add(&repo);
commit(&repo);
@ -900,7 +900,7 @@ test!(stale_cached_version {
name = "bar"
version = "0.0.0"
source = 'git+{url}#{hash}'
"#, url = bar.url(), hash = rev).as_slice()).assert();
"#, url = bar.url(), hash = rev).as_slice()).unwrap();
// Now build!
assert_that(foo.process(cargo_dir().join("cargo")).arg("build"),
@ -923,17 +923,17 @@ test!(dep_with_changed_submodule {
version = "0.5.0"
authors = ["carlhuda@example.com"]
"#)
}).assert();
}).unwrap();
let git_project2 = git_repo("dep2", |project| {
project
.file("lib.rs", "pub fn dep() -> &'static str { \"project2\" }")
}).assert();
}).unwrap();
let git_project3 = git_repo("dep3", |project| {
project
.file("lib.rs", "pub fn dep() -> &'static str { \"project3\" }")
}).assert();
}).unwrap();
let repo = git2::Repository::open(&git_project.root()).unwrap();
let mut sub = add_submodule(&repo, git_project2.url().to_string().as_slice(),
@ -971,7 +971,7 @@ test!(dep_with_changed_submodule {
let mut file = File::create(&git_project.root().join(".gitmodules"));
file.write_str(format!("[submodule \"src\"]\n\tpath = src\n\turl={}",
git_project3.url()).as_slice()).assert();
git_project3.url()).as_slice()).unwrap();
// Sync the submodule and reset it to the new remote.
sub.sync().unwrap();
@ -1023,7 +1023,7 @@ test!(dev_deps_with_testing {
.file("src/lib.rs", r#"
pub fn gimme() -> &'static str { "zoidberg" }
"#)
}).assert();
}).unwrap();
let p = project("foo")
.file("Cargo.toml", format!(r#"
@ -1084,8 +1084,8 @@ test!(git_build_cmd_freshness {
.file(".gitignore", "
src/bar.rs
")
}).assert();
foo.root().move_into_the_past().assert();
}).unwrap();
foo.root().move_into_the_past().unwrap();
timer::sleep(Duration::milliseconds(1000));
@ -1103,7 +1103,7 @@ test!(git_build_cmd_freshness {
// Modify an ignored file and make sure we don't rebuild
println!("second pass");
File::create(&foo.root().join("src/bar.rs")).assert();
File::create(&foo.root().join("src/bar.rs")).unwrap();
assert_that(foo.process(cargo_dir().join("cargo")).arg("build"),
execs().with_status(0)
.with_stdout(""));
@ -1120,7 +1120,7 @@ test!(git_name_not_always_needed {
.file("src/lib.rs", r#"
pub fn gimme() -> &'static str { "zoidberg" }
"#)
}).assert();
}).unwrap();
let repo = git2::Repository::open(&p2.root()).unwrap();
let mut cfg = repo.config().unwrap();
@ -1157,7 +1157,7 @@ test!(git_repo_changing_no_rebuild {
authors = ["wycats@example.com"]
"#)
.file("src/lib.rs", "pub fn bar() -> int { 1 }")
}).assert();
}).unwrap();
// Lock p1 to the first rev in the git repo
let p1 = project("p1")
@ -1172,7 +1172,7 @@ test!(git_repo_changing_no_rebuild {
"#, bar.url()).as_slice())
.file("src/main.rs", "fn main() {}");
p1.build();
p1.root().move_into_the_past().assert();
p1.root().move_into_the_past().unwrap();
assert_that(p1.process(cargo_dir().join("cargo")).arg("build"),
execs().with_stdout(format!("\
{updating} git repository `{bar}`
@ -1183,7 +1183,7 @@ test!(git_repo_changing_no_rebuild {
// Make a commit to lock p2 to a different rev
File::create(&bar.root().join("src/lib.rs")).write_str(r#"
pub fn bar() -> int { 2 }
"#).assert();
"#).unwrap();
let repo = git2::Repository::open(&bar.root()).unwrap();
add(&repo);
commit(&repo);
@ -1247,9 +1247,9 @@ test!(git_dep_build_cmd {
.file("bar/src/bar.rs.in", r#"
pub fn gimme() -> int { 0 }
"#)
}).assert();
}).unwrap();
p.root().join("bar").move_into_the_past().assert();
p.root().join("bar").move_into_the_past().unwrap();
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
execs().with_status(0));
@ -1259,8 +1259,8 @@ test!(git_dep_build_cmd {
execs().with_stdout("0\n"));
// Touching bar.rs.in should cause the `build` command to run again.
let mut file = fs::File::create(&p.root().join("bar/src/bar.rs.in")).assert();
file.write_str(r#"pub fn gimme() -> int { 1 }"#).assert();
let mut file = fs::File::create(&p.root().join("bar/src/bar.rs.in")).unwrap();
file.write_str(r#"pub fn gimme() -> int { 1 }"#).unwrap();
drop(file);
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
@ -1280,7 +1280,7 @@ test!(fetch_downloads {
authors = ["wycats@example.com"]
"#)
.file("src/lib.rs", "pub fn bar() -> int { 1 }")
}).assert();
}).unwrap();
let p = project("p1")
.file("Cargo.toml", format!(r#"
@ -1310,7 +1310,7 @@ test!(warnings_in_git_dep {
authors = ["wycats@example.com"]
"#)
.file("src/lib.rs", "fn unused() {}")
}).assert();
}).unwrap();
let p = project("foo")
.file("Cargo.toml", format!(r#"
@ -1343,7 +1343,7 @@ test!(update_ambiguous {
authors = ["wycats@example.com"]
"#)
.file("src/lib.rs", "")
}).assert();
}).unwrap();
let foo2 = git_repo("foo2", |project| {
project.file("Cargo.toml", r#"
[package]
@ -1352,7 +1352,7 @@ test!(update_ambiguous {
authors = ["wycats@example.com"]
"#)
.file("src/lib.rs", "")
}).assert();
}).unwrap();
let bar = git_repo("bar", |project| {
project.file("Cargo.toml", format!(r#"
[package]
@ -1364,7 +1364,7 @@ test!(update_ambiguous {
git = '{}'
"#, foo2.url()).as_slice())
.file("src/lib.rs", "")
}).assert();
}).unwrap();
let p = project("project")
.file("Cargo.toml", format!(r#"
@ -1409,7 +1409,7 @@ test!(update_one_dep_in_repo_with_many_deps {
authors = ["wycats@example.com"]
"#)
.file("a/src/lib.rs", "")
}).assert();
}).unwrap();
let p = project("project")
.file("Cargo.toml", format!(r#"
@ -1442,7 +1442,7 @@ test!(switch_deps_does_not_update_transitive {
authors = ["wycats@example.com"]
"#)
.file("src/lib.rs", "")
}).assert();
}).unwrap();
let dep1 = git_repo("dep1", |project| {
project.file("Cargo.toml", format!(r#"
[package]
@ -1454,7 +1454,7 @@ test!(switch_deps_does_not_update_transitive {
git = '{}'
"#, transitive.url()).as_slice())
.file("src/lib.rs", "")
}).assert();
}).unwrap();
let dep2 = git_repo("dep2", |project| {
project.file("Cargo.toml", format!(r#"
[package]
@ -1466,7 +1466,7 @@ test!(switch_deps_does_not_update_transitive {
git = '{}'
"#, transitive.url()).as_slice())
.file("src/lib.rs", "")
}).assert();
}).unwrap();
let p = project("project")
.file("Cargo.toml", format!(r#"
@ -1529,7 +1529,7 @@ test!(update_one_source_updates_all_packages_in_that_git_source {
authors = []
"#)
.file("a/src/lib.rs", "")
}).assert();
}).unwrap();
let p = project("project")
.file("Cargo.toml", format!(r#"
@ -1552,7 +1552,7 @@ test!(update_one_source_updates_all_packages_in_that_git_source {
// Just be sure to change a file
File::create(&dep.root().join("src/lib.rs")).write_str(r#"
pub fn bar() -> int { 2 }
"#).assert();
"#).unwrap();
add(&repo);
commit(&repo);
@ -1574,7 +1574,7 @@ test!(switch_sources {
authors = []
"#)
.file("src/lib.rs", "")
}).assert();
}).unwrap();
let a2 = git_repo("a2", |project| {
project.file("Cargo.toml", r#"
[package]
@ -1583,7 +1583,7 @@ test!(switch_sources {
authors = []
"#)
.file("src/lib.rs", "")
}).assert();
}).unwrap();
let p = project("project")
.file("Cargo.toml", r#"

View file

@ -1,6 +1,6 @@
use std::io::{fs, File, USER_RWX};
use support::{ResultTest, project, execs, main_file, cargo_dir};
use support::{project, execs, main_file, cargo_dir};
use support::{COMPILING, RUNNING};
use support::paths::{mod, PathExt};
use hamcrest::{assert_that, existing_file};
@ -278,7 +278,7 @@ test!(no_rebuild_dependency {
// This time we shouldn't compile bar
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
execs().with_stdout(""));
p.root().move_into_the_past().assert();
p.root().move_into_the_past().unwrap();
p.build(); // rebuild the files (rewriting them in the process)
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
@ -350,10 +350,10 @@ test!(deep_dependencies_trigger_rebuild {
//
// We base recompilation off mtime, so sleep for at least a second to ensure
// that this write will change the mtime.
p.root().move_into_the_past().assert();
p.root().move_into_the_past().unwrap();
File::create(&p.root().join("baz/src/baz.rs")).write_str(r#"
pub fn baz() { println!("hello!"); }
"#).assert();
"#).unwrap();
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
execs().with_stdout(format!("{} baz v0.5.0 ({})\n\
{} bar v0.5.0 ({})\n\
@ -363,11 +363,11 @@ test!(deep_dependencies_trigger_rebuild {
COMPILING, p.url())));
// Make sure an update to bar doesn't trigger baz
p.root().move_into_the_past().assert();
p.root().move_into_the_past().unwrap();
File::create(&p.root().join("bar/src/bar.rs")).write_str(r#"
extern crate baz;
pub fn bar() { println!("hello!"); baz::baz(); }
"#).assert();
"#).unwrap();
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
execs().with_stdout(format!("{} bar v0.5.0 ({})\n\
{} foo v0.5.0 ({})\n",
@ -477,11 +477,11 @@ test!(nested_deps_recompile {
{} foo v0.5.0 ({})\n",
COMPILING, bar,
COMPILING, p.url())));
p.root().move_into_the_past().assert();
p.root().move_into_the_past().unwrap();
File::create(&p.root().join("src/foo.rs")).write_str(r#"
fn main() {}
"#).assert();
"#).unwrap();
// This shouldn't recompile `bar`
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
@ -527,10 +527,10 @@ test!(override_relative {
"#)
.file("src/lib.rs", "");
fs::mkdir(&paths::root().join(".cargo"), USER_RWX).assert();
fs::mkdir(&paths::root().join(".cargo"), USER_RWX).unwrap();
File::create(&paths::root().join(".cargo/config")).write_str(r#"
paths = ["bar"]
"#).assert();
"#).unwrap();
let p = project("foo")
.file("Cargo.toml", format!(r#"
@ -666,7 +666,7 @@ test!(path_dep_build_cmd {
"#);
p.build();
p.root().join("bar").move_into_the_past().assert();
p.root().join("bar").move_into_the_past().unwrap();
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
execs().with_stdout(format!("{} bar v0.5.0 ({})\n\
@ -682,8 +682,8 @@ test!(path_dep_build_cmd {
// Touching bar.rs.in should cause the `build` command to run again.
{
let mut file = fs::File::create(&p.root().join("bar/src/bar.rs.in")).assert();
file.write_str(r#"pub fn gimme() -> int { 1 }"#).assert();
let mut file = fs::File::create(&p.root().join("bar/src/bar.rs.in")).unwrap();
file.write_str(r#"pub fn gimme() -> int { 1 }"#).unwrap();
}
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),

View file

@ -1,7 +1,7 @@
use std::io::{fs, File};
use support::{project, execs, path2url};
use support::{COMPILING, cargo_dir, ResultTest};
use support::{COMPILING, cargo_dir};
use support::paths::PathExt;
use hamcrest::{assert_that, existing_file};
@ -27,15 +27,15 @@ test!(modifying_and_moving {
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
execs().with_status(0).with_stdout(""));
p.root().move_into_the_past().assert();
p.root().move_into_the_past().unwrap();
File::create(&p.root().join("src/a.rs")).write_str("fn main() {}").assert();
File::create(&p.root().join("src/a.rs")).write_str("fn main() {}").unwrap();
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
execs().with_status(0).with_stdout(format!("\
{compiling} foo v0.0.1 ({dir})
", compiling = COMPILING, dir = path2url(p.root()))));
fs::rename(&p.root().join("src/a.rs"), &p.root().join("src/b.rs")).assert();
fs::rename(&p.root().join("src/a.rs"), &p.root().join("src/b.rs")).unwrap();
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
execs().with_status(101));
});
@ -69,11 +69,11 @@ test!(modify_only_some_files {
let lib = p.root().join("src/lib.rs");
let bin = p.root().join("src/b.rs");
File::create(&lib).write_str("invalid rust code").assert();
lib.move_into_the_past().assert();
p.root().move_into_the_past().assert();
File::create(&lib).write_str("invalid rust code").unwrap();
lib.move_into_the_past().unwrap();
p.root().move_into_the_past().unwrap();
File::create(&bin).write_str("fn foo() {}").assert();
File::create(&bin).write_str("fn foo() {}").unwrap();
// Make sure the binary is rebuilt, not the lib
assert_that(p.process(cargo_dir().join("cargo")).arg("build")

View file

@ -1,6 +1,6 @@
use std::io::File;
use support::{project, execs, cargo_dir, ResultTest};
use support::{project, execs, cargo_dir};
use hamcrest::assert_that;
fn setup() {}
@ -23,9 +23,9 @@ test!(ignores_carriage_return {
let lockfile = p.root().join("Cargo.lock");
let lock = File::open(&lockfile).read_to_string();
let lock = lock.assert();
let lock = lock.unwrap();
let lock = lock.as_slice().replace("\n", "\r\n");
File::create(&lockfile).write_str(lock.as_slice()).assert();
File::create(&lockfile).write_str(lock.as_slice()).unwrap();
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
execs().with_status(0));
});
@ -52,7 +52,7 @@ test!(adding_and_removing_packages {
let lockfile = p.root().join("Cargo.lock");
let toml = p.root().join("Cargo.toml");
let lock1 = File::open(&lockfile).read_to_string().assert();
let lock1 = File::open(&lockfile).read_to_string().unwrap();
// add a dep
File::create(&toml).write_str(r#"
@ -63,10 +63,10 @@ test!(adding_and_removing_packages {
[dependencies.bar]
path = "bar"
"#).assert();
"#).unwrap();
assert_that(p.process(cargo_dir().join("cargo")).arg("generate-lockfile"),
execs().with_status(0));
let lock2 = File::open(&lockfile).read_to_string().assert();
let lock2 = File::open(&lockfile).read_to_string().unwrap();
assert!(lock1 != lock2);
// change the dep
@ -75,10 +75,10 @@ test!(adding_and_removing_packages {
name = "bar"
authors = []
version = "0.0.2"
"#).assert();
"#).unwrap();
assert_that(p.process(cargo_dir().join("cargo")).arg("generate-lockfile"),
execs().with_status(0));
let lock3 = File::open(&lockfile).read_to_string().assert();
let lock3 = File::open(&lockfile).read_to_string().unwrap();
assert!(lock1 != lock3);
assert!(lock2 != lock3);
@ -88,10 +88,10 @@ test!(adding_and_removing_packages {
name = "foo"
authors = []
version = "0.0.1"
"#).assert();
"#).unwrap();
assert_that(p.process(cargo_dir().join("cargo")).arg("generate-lockfile"),
execs().with_status(0));
let lock4 = File::open(&lockfile).read_to_string().assert();
let lock4 = File::open(&lockfile).read_to_string().unwrap();
assert_eq!(lock1, lock4);
});
@ -122,19 +122,19 @@ foo = "bar"
"#;
let lockfile = p.root().join("Cargo.lock");
{
let lock = File::open(&lockfile).read_to_string().assert();
File::create(&lockfile).write_str((lock + metadata).as_slice()).assert();
let lock = File::open(&lockfile).read_to_string().unwrap();
File::create(&lockfile).write_str((lock + metadata).as_slice()).unwrap();
}
// Build and make sure the metadata is still there
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
execs().with_status(0));
let lock = File::open(&lockfile).read_to_string().assert();
let lock = File::open(&lockfile).read_to_string().unwrap();
assert!(lock.as_slice().contains(metadata.trim()), "{}", lock);
// Update and make sure the metadata is still there
assert_that(p.process(cargo_dir().join("cargo")).arg("update"),
execs().with_status(0));
let lock = File::open(&lockfile).read_to_string().assert();
let lock = File::open(&lockfile).read_to_string().unwrap();
assert!(lock.as_slice().contains(metadata.trim()), "{}", lock);
});

View file

@ -2,7 +2,7 @@ use std::io::{fs, USER_RWX, File, TempDir};
use std::io::fs::PathExtensions;
use std::os;
use support::{execs, paths, cargo_dir, ResultTest};
use support::{execs, paths, cargo_dir};
use hamcrest::{assert_that, existing_file, existing_dir, is_not};
use cargo::util::{process, ProcessBuilder};
@ -85,7 +85,7 @@ test!(simple_travis {
test!(no_argument {
assert_that(cargo_process("new"),
execs().with_status(1)
.with_stderr("Invalid arguments.
.with_stderr("\
Usage:
cargo new [options] <path>
cargo new -h | --help
@ -94,7 +94,7 @@ Usage:
test!(existing {
let dst = paths::root().join("foo");
fs::mkdir(&dst, USER_RWX).assert();
fs::mkdir(&dst, USER_RWX).unwrap();
assert_that(cargo_process("new").arg("foo"),
execs().with_status(101)
.with_stderr(format!("Destination `{}` already exists\n",
@ -116,7 +116,7 @@ test!(finds_author_user {
execs().with_status(0));
let toml = td.path().join("foo/Cargo.toml");
let toml = File::open(&toml).read_to_string().assert();
let toml = File::open(&toml).read_to_string().unwrap();
assert!(toml.as_slice().contains(r#"authors = ["foo"]"#));
});
@ -131,42 +131,42 @@ test!(finds_author_username {
execs().with_status(0));
let toml = td.path().join("foo/Cargo.toml");
let toml = File::open(&toml).read_to_string().assert();
let toml = File::open(&toml).read_to_string().unwrap();
assert!(toml.as_slice().contains(r#"authors = ["foo"]"#));
});
test!(finds_author_git {
my_process("git").args(&["config", "--global", "user.name", "bar"])
.exec().assert();
.exec().unwrap();
my_process("git").args(&["config", "--global", "user.email", "baz"])
.exec().assert();
.exec().unwrap();
assert_that(cargo_process("new").arg("foo").env("USER", Some("foo")),
execs().with_status(0));
let toml = paths::root().join("foo/Cargo.toml");
let toml = File::open(&toml).read_to_string().assert();
let toml = File::open(&toml).read_to_string().unwrap();
assert!(toml.as_slice().contains(r#"authors = ["bar <baz>"]"#));
});
test!(author_prefers_cargo {
my_process("git").args(&["config", "--global", "user.name", "bar"])
.exec().assert();
.exec().unwrap();
my_process("git").args(&["config", "--global", "user.email", "baz"])
.exec().assert();
.exec().unwrap();
let root = paths::root();
fs::mkdir(&root.join(".cargo"), USER_RWX).assert();
fs::mkdir(&root.join(".cargo"), USER_RWX).unwrap();
File::create(&root.join(".cargo/config")).write_str(r#"
[cargo-new]
name = "new-foo"
email = "new-bar"
git = false
"#).assert();
"#).unwrap();
assert_that(cargo_process("new").arg("foo").env("USER", Some("foo")),
execs().with_status(0));
let toml = paths::root().join("foo/Cargo.toml");
let toml = File::open(&toml).read_to_string().assert();
let toml = File::open(&toml).read_to_string().unwrap();
assert!(toml.as_slice().contains(r#"authors = ["new-foo <new-bar>"]"#));
assert!(!root.join("foo/.gitignore").exists());
});
@ -174,13 +174,13 @@ test!(author_prefers_cargo {
test!(git_prefers_command_line {
let root = paths::root();
let td = TempDir::new("cargo").unwrap();
fs::mkdir(&root.join(".cargo"), USER_RWX).assert();
fs::mkdir(&root.join(".cargo"), USER_RWX).unwrap();
File::create(&root.join(".cargo/config")).write_str(r#"
[cargo-new]
git = false
name = "foo"
email = "bar"
"#).assert();
"#).unwrap();
assert_that(cargo_process("new").arg("foo").arg("--git").cwd(td.path().clone())
.env("USER", Some("foo")),
@ -193,7 +193,7 @@ test!(subpackage_no_git {
assert_that(cargo_process("new").arg("foo"), execs().with_status(0));
let subpackage = paths::root().join("foo").join("components");
fs::mkdir(&subpackage, USER_RWX).assert();
fs::mkdir(&subpackage, USER_RWX).unwrap();
assert_that(cargo_process("new").arg("foo/components/subcomponent"),
execs().with_status(0));

View file

@ -4,7 +4,7 @@ use tar::Archive;
use flate2::reader::GzDecoder;
use cargo::util::process;
use support::{project, execs, cargo_dir, ResultTest, paths, git};
use support::{project, execs, cargo_dir, paths, git};
use support::{PACKAGING, VERIFYING, COMPILING, ARCHIVING};
use hamcrest::{assert_that, existing_file};
@ -46,12 +46,12 @@ src[..]main.rs
assert_that(p.process(cargo_dir().join("cargo")).arg("package"),
execs().with_status(0).with_stdout(""));
let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).assert();
let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
let mut rdr = GzDecoder::new(f);
let contents = rdr.read_to_end().assert();
let contents = rdr.read_to_end().unwrap();
let ar = Archive::new(MemReader::new(contents));
for f in ar.files().assert() {
let f = f.assert();
for f in ar.files().unwrap() {
let f = f.unwrap();
let fname = f.filename_bytes();
assert!(fname == b"foo-0.0.1/Cargo.toml" ||
fname == b"foo-0.0.1/src/main.rs",

View file

@ -4,7 +4,7 @@ use flate2::reader::GzDecoder;
use tar::Archive;
use url::Url;
use support::{ResultTest, project, execs};
use support::{project, execs};
use support::{UPDATING, PACKAGING, UPLOADING};
use support::paths;
use support::git::repo;
@ -18,13 +18,13 @@ fn upload() -> Url { Url::from_file_path(&upload_path()).unwrap() }
fn setup() {
let config = paths::root().join(".cargo/config");
fs::mkdir_recursive(&config.dir_path(), io::USER_DIR).assert();
fs::mkdir_recursive(&config.dir_path(), io::USER_DIR).unwrap();
File::create(&config).write_str(format!(r#"
[registry]
index = "{reg}"
token = "api-token"
"#, reg = registry()).as_slice()).assert();
fs::mkdir_recursive(&upload_path().join("api/v1/crates"), io::USER_DIR).assert();
"#, reg = registry()).as_slice()).unwrap();
fs::mkdir_recursive(&upload_path().join("api/v1/crates"), io::USER_DIR).unwrap();
repo(&registry_path())
.file("config.json", format!(r#"{{

View file

@ -4,7 +4,7 @@ use url::Url;
use cargo::util::{process, ProcessBuilder};
use support::UPDATING;
use support::{ResultTest, execs, cargo_dir};
use support::{execs, cargo_dir};
use support::paths;
use support::git::repo;
@ -17,12 +17,12 @@ fn api() -> Url { Url::from_file_path(&api_path()).unwrap() }
fn setup() {
let config = paths::root().join(".cargo/config");
fs::mkdir_recursive(&config.dir_path(), io::USER_DIR).assert();
fs::mkdir_recursive(&config.dir_path(), io::USER_DIR).unwrap();
File::create(&config).write_str(format!(r#"
[registry]
index = "{reg}"
"#, reg = registry()).as_slice()).assert();
fs::mkdir_recursive(&api_path().join("api/v1"), io::USER_DIR).assert();
"#, reg = registry()).as_slice()).unwrap();
fs::mkdir_recursive(&api_path().join("api/v1"), io::USER_DIR).unwrap();
repo(&registry_path())
.file("config.json", format!(r#"{{

View file

@ -2,7 +2,7 @@ use std::path;
use std::str;
use support::{project, execs, basic_bin_manifest, basic_lib_manifest};
use support::{COMPILING, cargo_dir, ResultTest, RUNNING, DOCTEST};
use support::{COMPILING, cargo_dir, RUNNING, DOCTEST};
use support::paths::PathExt;
use hamcrest::{assert_that, existing_file};
use cargo::util::process;
@ -93,8 +93,8 @@ test!(many_similar_names {
#[test] fn test_test() { foo::foo() }
"#);
let output = p.cargo_process("test").exec_with_output().assert();
let output = str::from_utf8(output.output.as_slice()).assert();
let output = p.cargo_process("test").exec_with_output().unwrap();
let output = str::from_utf8(output.output.as_slice()).unwrap();
assert!(output.contains("test bin_test"), "bin_test missing\n{}", output);
assert!(output.contains("test lib_test"), "lib_test missing\n{}", output);
assert!(output.contains("test test_test"), "test_test missing\n{}", output);
@ -638,8 +638,8 @@ test!(bin_there_for_integration {
}
"#);
let output = p.cargo_process("test").exec_with_output().assert();
let output = str::from_utf8(output.output.as_slice()).assert();
let output = p.cargo_process("test").exec_with_output().unwrap();
let output = str::from_utf8(output.output.as_slice()).unwrap();
assert!(output.contains("main_test ... ok"), "no main_test\n{}", output);
assert!(output.contains("test_test ... ok"), "no test_test\n{}", output);
});
@ -716,7 +716,7 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
compiling = COMPILING, running = RUNNING,
doctest = DOCTEST,
dir = p.url()).as_slice()));
p.root().move_into_the_past().assert();
p.root().move_into_the_past().unwrap();
assert_that(p.process(cargo_dir().join("cargo")).arg("test"),
execs().with_status(0)
.with_stdout(format!("\

View file

@ -4,7 +4,7 @@ use hamcrest::{assert_that};
use cargo::core::shell::{Shell,ShellConfig};
use support::{ResultTest,Tap,shell_writes};
use support::{Tap, shell_writes};
fn setup() {
}
@ -19,7 +19,7 @@ test!(non_tty {
let (tx, mut rx) = pair();
Shell::create(box tx, config).tap(|shell| {
shell.say("Hey Alex", color::RED).assert();
shell.say("Hey Alex", color::RED).unwrap();
});
let buf = rx.read_to_end().unwrap();
@ -31,7 +31,7 @@ test!(color_explicitly_disabled {
let (tx, mut rx) = pair();
Shell::create(box tx, config).tap(|shell| {
shell.say("Hey Alex", color::RED).assert();
shell.say("Hey Alex", color::RED).unwrap();
});
let buf = rx.read_to_end().unwrap();
assert_that(buf.as_slice(), shell_writes("Hey Alex\n"));
@ -45,12 +45,12 @@ test!(colored_shell {
let (tx, mut rx) = pair();
Shell::create(box tx, config).tap(|shell| {
shell.say("Hey Alex", color::RED).assert();
shell.say("Hey Alex", color::RED).unwrap();
});
let buf = rx.read_to_end().unwrap();
assert_that(buf.as_slice(),
shell_writes(colored_output("Hey Alex\n",
color::RED).assert()));
color::RED).unwrap()));
});
fn colored_output<S: Str>(string: S, color: color::Color) -> IoResult<String> {