curl = "0.4.6"
docopt = "0.8.1"
env_logger = "0.4"
-error-chain = "0.11.0"
+failure = "0.1.1"
filetime = "0.1"
flate2 = "0.2"
fs2 = "0.4"
use cargo::core::Workspace;
use cargo::ops::{self, MessageFormat, Packages};
-use cargo::util::{CliResult, CliError, Config, CargoErrorKind};
+use cargo::util::{CliResult, CliError, Config};
use cargo::util::important_paths::{find_root_manifest_for_wd};
#[derive(Deserialize)]
None => Ok(()),
Some(err) => {
Err(match err.exit.as_ref().and_then(|e| e.code()) {
- Some(i) => CliError::new("bench failed".into(), i),
- None => CliError::new(CargoErrorKind::CargoTestErrorKind(err).into(), 101)
+ Some(i) => CliError::new(format_err!("bench failed"), i),
+ None => CliError::new(err.into(), 101)
})
}
}
extern crate cargo;
extern crate env_logger;
+#[macro_use]
+extern crate failure;
extern crate git2_curl;
extern crate toml;
#[macro_use]
use std::path::{Path, PathBuf};
use cargo::core::shell::{Shell, Verbosity};
-use cargo::util::{self, CliResult, lev_distance, Config, CargoResult, CargoError, CargoErrorKind};
-use cargo::util::CliError;
+use cargo::util::{self, CliResult, lev_distance, Config, CargoResult};
+use cargo::util::{CliError, ProcessError};
#[derive(Deserialize)]
pub struct Flags {
let args: Vec<_> = try!(env::args_os()
.map(|s| {
s.into_string().map_err(|s| {
- CargoError::from(format!("invalid unicode in argument: {:?}", s))
+ format_err!("invalid unicode in argument: {:?}", s)
})
})
.collect());
let command = match path {
Some(command) => command,
None => {
- return Err(CargoError::from(match find_closest(config, cmd) {
- Some(closest) => {
- format!("no such subcommand: `{}`\n\n\tDid you mean `{}`?\n",
+ let err = match find_closest(config, cmd) {
+ Some(closest) => {
+ format_err!("no such subcommand: `{}`\n\n\tDid you mean `{}`?\n",
cmd,
closest)
- }
- None => format!("no such subcommand: `{}`", cmd),
- })
- .into())
+ }
+ None => format_err!("no such subcommand: `{}`", cmd),
+ };
+ return Err(CliError::new(err, 101))
}
};
Err(e) => e,
};
- if let &CargoErrorKind::ProcessErrorKind(ref perr) = err.kind() {
+ if let Some(perr) = err.downcast_ref::<ProcessError>() {
if let Some(code) = perr.exit.as_ref().and_then(|c| c.code()) {
return Err(CliError::code(code));
}
Some("test") => true,
None => false,
Some(profile) => {
- let err = format!("unknown profile: `{}`, only `test` is currently supported",
- profile).into();
+ let err = format_err!("unknown profile: `{}`, only `test` is \
+ currently supported", profile);
return Err(CliError::new(err, 101))
}
};
// This is a dummy command just so that `cargo help help` works.
// The actual delegation of help flag to subcommands is handled by the
// cargo command.
- Err(CliError::new("help command should not be executed directly".into(), 101))
+ Err(CliError::new(format_err!("help command should not be executed directly"),
+ 101))
}
use cargo::ops;
use cargo::core::{SourceId, GitReference};
-use cargo::util::{CargoError, CliResult, Config, ToUrl};
+use cargo::util::{CliResult, Config, ToUrl};
#[derive(Deserialize)]
pub struct Options {
let krates = options.arg_crate.iter().map(|s| &s[..]).collect::<Vec<_>>();
let vers = match (&options.flag_vers, &options.flag_version) {
- (&Some(_), &Some(_)) => return Err(CargoError::from("Invalid arguments.").into()),
+ (&Some(_), &Some(_)) => return Err(format_err!("invalid arguments").into()),
(&Some(ref v), _) | (_, &Some(ref v)) => Some(v.as_ref()),
_ => None,
};
let root = find_root_manifest_for_wd(flags.flag_manifest_path, config.cwd())?;
let string = root.to_str()
- .ok_or_else(|| "Your project path contains \
- characters not representable in \
- Unicode".into())
+ .ok_or_else(|| format_err!("your project path contains \
+ characters not representable in \
+ Unicode"))
.map_err(|e| CliError::new(e, 1))?;
let location = ProjectLocation { root: string.to_string() };
use cargo::ops;
use cargo::core::{SourceId, Source};
use cargo::sources::RegistrySource;
-use cargo::util::{CargoError, CliResult, CargoResultExt, Config};
+use cargo::util::{CliResult, CargoResultExt, Config, CargoError};
#[derive(Deserialize)]
pub struct Options {
&options.flag_z)?;
if options.flag_registry.is_some() && !config.cli_unstable().unstable_options {
- return Err(CargoError::from("registry option is an unstable feature and requires -Zunstable-options to use.").into());
+ return Err(format_err!("registry option is an unstable feature and \
+ requires -Zunstable-options to use.").into());
}
let token = match options.arg_token {
None => {
let host = match options.flag_registry {
Some(ref _registry) => {
- return Err(CargoError::from("token must be provided when --registry is provided.").into());
+ return Err(format_err!("token must be provided when \
+ --registry is provided.").into())
}
None => {
let src = SourceId::crates_io(config)?;
let input = io::stdin();
input.lock().read_line(&mut line).chain_err(|| {
"failed to read stdin"
- })?;
+ }).map_err(CargoError::from)?;
line.trim().to_string()
}
};
use cargo::ops;
-use cargo::util::{CargoError, CliResult, Config};
+use cargo::util::{CliResult, Config};
#[derive(Deserialize)]
pub struct Options {
};
if opts.registry.is_some() && !config.cli_unstable().unstable_options {
- return Err(CargoError::from("registry option is an unstable feature and requires -Zunstable-options to use.").into());
+ return Err(format_err!("registry option is an unstable feature and \
+ requires -Zunstable-options to use.").into())
}
ops::modify_owners(config, &opts)?;
use cargo::core::Workspace;
use cargo::ops;
-use cargo::util::{CargoError, CliResult, Config};
+use cargo::util::{CliResult, Config};
use cargo::util::important_paths::find_root_manifest_for_wd;
#[derive(Deserialize)]
} = options;
if registry.is_some() && !config.cli_unstable().unstable_options {
- return Err(CargoError::from("registry option is an unstable feature and requires -Zunstable-options to use.").into());
+ return Err(format_err!("registry option is an unstable feature and \
+ requires -Zunstable-options to use.").into())
}
// TODO: Deprecated
use cargo::core::Workspace;
use cargo::ops::{self, MessageFormat, Packages};
-use cargo::util::{CliResult, CliError, Config, CargoErrorKind};
+use cargo::util::{CliResult, CliError, Config};
use cargo::util::important_paths::{find_root_manifest_for_wd};
#[derive(Deserialize)]
// bad and we always want to forward that up.
let exit = match err.exit {
Some(exit) => exit,
- None => return Err(
- CliError::new(CargoErrorKind::ProcessErrorKind(err).into(), 101)),
+ None => return Err(CliError::new(err.into(), 101)),
};
// If `-q` was passed then we suppress extra error information about
Err(if options.flag_quiet == Some(true) {
CliError::code(exit_code)
} else {
- CliError::new(CargoErrorKind::ProcessErrorKind(err).into(), exit_code)
+ CliError::new(err.into(), exit_code)
})
}
}
Some("bench") => CompileMode::Bench,
Some("check") => CompileMode::Check {test: false},
Some(mode) => {
- let err = format!("unknown profile: `{}`, use dev,
- test, or bench", mode).into();
+ let err = format_err!("unknown profile: `{}`, use dev,
+ test, or bench", mode);
return Err(CliError::new(err, 101))
}
};
use cargo::ops;
-use cargo::util::{CargoError, CliResult, Config};
+use cargo::util::{CliResult, Config};
use std::cmp;
} = options;
if registry.is_some() && !config.cli_unstable().unstable_options {
- return Err(CargoError::from("registry option is an unstable feature and requires -Zunstable-options to use.").into());
+ return Err(format_err!("registry option is an unstable feature and \
+ requires -Zunstable-options to use.").into())
}
// TODO: Depricated
use cargo::core::Workspace;
use cargo::ops::{self, MessageFormat, Packages};
-use cargo::util::{CliResult, CliError, Config, CargoErrorKind};
+use cargo::util::{CliResult, CliError, Config};
use cargo::util::important_paths::find_root_manifest_for_wd;
#[derive(Deserialize)]
None => Ok(()),
Some(err) => {
Err(match err.exit.as_ref().and_then(|e| e.code()) {
- Some(i) => CliError::new(err.hint().into(), i),
- None => CliError::new(CargoErrorKind::CargoTestErrorKind(err).into(), 101),
+ Some(i) => CliError::new(format_err!("{}", err.hint()), i),
+ None => CliError::new(err.into(), 101),
})
}
}
use cargo::ops;
-use cargo::util::{CargoError, CliResult, Config};
+use cargo::util::{CliResult, Config};
#[derive(Deserialize)]
pub struct Options {
&options.flag_z)?;
if options.flag_registry.is_some() && !config.cli_unstable().unstable_options {
- return Err(CargoError::from("registry option is an unstable feature and requires -Zunstable-options to use.").into());
+ return Err(format_err!("registry option is an unstable feature and \
+ requires -Zunstable-options to use.").into())
}
ops::yank(config,
fn from_str(s: &str) -> CargoResult<Platform> {
if s.starts_with("cfg(") && s.ends_with(')') {
let s = &s[4..s.len()-1];
- s.parse().map(Platform::Cfg).chain_err(|| {
- format!("failed to parse `{}` as a cfg expression", s)
- })
+ let p = s.parse().map(Platform::Cfg).chain_err(|| {
+ format_err!("failed to parse `{}` as a cfg expression", s)
+ })?;
+ Ok(p)
} else {
Ok(Platform::Name(s.to_string()))
}
pub fn feature_gate(&self) -> CargoResult<()> {
if self.im_a_teapot.is_some() {
self.features.require(Feature::test_dummy_unstable()).chain_err(|| {
- "the `im-a-teapot` manifest key is unstable and may not work \
- properly in England"
+ format_err!("the `im-a-teapot` manifest key is unstable and may \
+ not work properly in England")
})?;
}
internal(format!("couldn't find source for `{}`", id))
})?;
let pkg = source.download(id).chain_err(|| {
- "unable to get packages from source"
+ format_err!("unable to get packages from source")
})?;
assert!(slot.fill(pkg).is_ok());
Ok(slot.borrow().unwrap())
use core::PackageId;
use util::{ToUrl, ToSemver};
-use util::errors::{CargoError, CargoResult, CargoResultExt};
+use util::errors::{CargoResult, CargoResultExt};
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct PackageIdSpec {
where I: IntoIterator<Item=&'a PackageId>
{
let spec = PackageIdSpec::parse(spec).chain_err(|| {
- format!("invalid package id specification: `{}`", spec)
+ format_err!("invalid package id specification: `{}`", spec)
})?;
spec.query(i)
}
url.set_fragment(None);
let (name, version) = {
let mut path = url.path_segments().ok_or_else(|| {
- CargoError::from(format!("pkgid urls must have a path: {}", url))
+ format_err!("pkgid urls must have a path: {}", url)
})?;
let path_name = path.next_back().ok_or_else(|| {
- CargoError::from(format!("pkgid urls must have at least one path \
- component: {}", url))
+ format_err!("pkgid urls must have at least one path \
+ component: {}", url)
})?;
match frag {
Some(fragment) => {
let mut vec = vec![ret, other];
vec.extend(ids);
minimize(&mut msg, &vec, self);
- Err(msg.into())
+ Err(format_err!("{}", msg))
}
None => Ok(ret)
};
}
Ok(summary)
}).collect::<CargoResult<Vec<_>>>().chain_err(|| {
- format!("failed to resolve patches for `{}`", url)
+ format_err!("failed to resolve patches for `{}`", url)
})?;
self.patches.insert(url.clone(), deps);
// Ensure the source has fetched all necessary remote data.
let _p = profile::start(format!("updating: {}", source_id));
self.sources.get_mut(source_id).unwrap().update()
- })().chain_err(|| format!("Unable to update {}", source_id))
+ })().chain_err(|| format_err!("Unable to update {}", source_id))?;
+ Ok(())
}
fn query_overrides(&mut self, dep: &Dependency)
// Ensure the requested source_id is loaded
self.ensure_loaded(dep.source_id(), Kind::Normal).chain_err(|| {
- format!("failed to load source for a dependency \
- on `{}`", dep.name())
+ format_err!("failed to load source for a dependency \
+ on `{}`", dep.name())
})?;
let source = self.sources.get_mut(dep.source_id());
.collect::<Vec<_>>()
.join(", ")));
- return msg.into()
+ return format_err!("{}", msg)
}
// Once we're all the way down here, we're definitely lost in the
dep.version_req())
};
- msg.into()
+ format_err!("{}", msg)
}
// Returns if `a` and `b` are compatible in the semver sense. This is a
let mut summaries = registry.query_vec(dep)?.into_iter();
let s = summaries.next().ok_or_else(|| {
- format!("no matching package for override `{}` found\n\
- location searched: {}\n\
- version required: {}",
- spec, dep.source_id(), dep.version_req())
+ format_err!("no matching package for override `{}` found\n\
+ location searched: {}\n\
+ version required: {}",
+ spec, dep.source_id(), dep.version_req())
})?;
let summaries = summaries.collect::<Vec<_>>();
if !summaries.is_empty() {
pub fn from_url(string: &str) -> CargoResult<SourceId> {
let mut parts = string.splitn(2, '+');
let kind = parts.next().unwrap();
- let url = parts.next().ok_or_else(|| format!("invalid source `{}`", string))?;
+ let url = parts.next().ok_or_else(|| format_err!("invalid source `{}`", string))?;
match kind {
"git" => {
let url = url.to_url()?;
SourceId::new(Kind::Path, url)
}
- kind => Err(format!("unsupported source protocol: {}", kind).into())
+ kind => Err(format_err!("unsupported source protocol: {}", kind))
}
}
/// actually a "virtual Cargo.toml", in which case an error is returned
/// indicating that something else should be passed.
pub fn current(&self) -> CargoResult<&Package> {
- self.current_opt().ok_or_else(||
- format!("manifest path `{}` is a virtual manifest, but this \
- command requires running against an actual package in \
- this workspace", self.current_manifest.display()).into()
- )
+ let pkg = self.current_opt().ok_or_else(|| {
+ format_err!("manifest path `{}` is a virtual manifest, but this \
+ command requires running against an actual package in \
+ this workspace", self.current_manifest.display())
+ })?;
+ Ok(pkg)
}
pub fn current_opt(&self) -> Option<&Package> {
None => return Ok(Vec::new()),
};
let res = glob(path).chain_err(|| {
- format!("could not parse pattern `{}`", &path)
+ format_err!("could not parse pattern `{}`", &path)
})?;
- res.map(|p| {
+ let res = res.map(|p| {
p.chain_err(|| {
- format!("unable to match path to pattern `{}`", &path)
+ format_err!("unable to match path to pattern `{}`", &path)
})
- }).collect()
+ }).collect::<Result<Vec<_>, _>>()?;
+ Ok(res)
}
}
#![cfg_attr(test, deny(warnings))]
#![recursion_limit="128"]
-#[macro_use] extern crate error_chain;
+#[macro_use] extern crate failure;
#[macro_use] extern crate log;
#[macro_use] extern crate scoped_tls;
#[macro_use] extern crate serde_derive;
extern crate core_foundation;
use std::fmt;
-use std::error::Error;
-use error_chain::ChainedError;
use serde::Deserialize;
use serde::ser;
use docopt::Docopt;
+use failure::Error;
use core::Shell;
use core::shell::Verbosity::Verbose;
-pub use util::{CargoError, CargoErrorKind, CargoResult, CliError, CliResult, Config};
+pub use util::{CargoError, CargoResult, CliError, CliResult, Config};
+pub use util::errors::Internal;
pub const CARGO_ENV: &'static str = "CARGO";
-macro_rules! bail {
- ($($fmt:tt)*) => (
- return Err(::util::errors::CargoError::from(format_args!($($fmt)*).to_string()))
- )
-}
-
pub mod core;
pub mod ops;
pub mod sources;
let flags = docopt.deserialize().map_err(|e| {
let code = if e.fatal() {1} else {0};
- CliError::new(e.to_string().into(), code)
+ CliError::new(e.into(), code)
})?;
exec(flags, config)
drop(writeln!(shell.err(), "{}", error))
}
- if !handle_cause(error, shell) || hide {
+ if !handle_cause(&error, shell) || hide {
drop(writeln!(shell.err(), "\nTo learn more, run the command again \
with --verbose."));
}
debug!("handle_error; err={:?}", &err);
let _ignored_result = shell.error(&err);
- handle_cause(err, shell);
+ handle_cause(&err, shell);
}
-fn handle_cause<E, EKind>(cargo_err: E, shell: &mut Shell) -> bool
- where E: ChainedError<ErrorKind=EKind> + 'static
-{
+fn handle_cause(cargo_err: &Error, shell: &mut Shell) -> bool {
fn print(error: String, shell: &mut Shell) {
drop(writeln!(shell.err(), "\nCaused by:"));
drop(writeln!(shell.err(), " {}", error));
}
- //Error inspection in non-verbose mode requires inspecting the
- //error kind to avoid printing Internal errors. The downcasting
- //machinery requires &(Error + 'static), but the iterator (and
- //underlying `cause`) return &Error. Because the borrows are
- //constrained to this handling method, and because the original
- //error object is constrained to be 'static, we're casting away
- //the borrow's actual lifetime for purposes of downcasting and
- //inspecting the error chain
- unsafe fn extend_lifetime(r: &Error) -> &(Error + 'static) {
- std::mem::transmute::<&Error, &Error>(r)
- }
-
let verbose = shell.verbosity();
if verbose == Verbose {
- //The first error has already been printed to the shell
- //Print all remaining errors
- for err in cargo_err.iter().skip(1) {
+ // The first error has already been printed to the shell
+ // Print all remaining errors
+ for err in cargo_err.causes().skip(1) {
print(err.to_string(), shell);
}
} else {
- //The first error has already been printed to the shell
- //Print remaining errors until one marked as Internal appears
- for err in cargo_err.iter().skip(1) {
- let err = unsafe { extend_lifetime(err) };
- if let Some(&CargoError(CargoErrorKind::Internal(..), ..)) =
- err.downcast_ref::<CargoError>() {
+ // The first error has already been printed to the shell
+ // Print remaining errors until one marked as Internal appears
+ for err in cargo_err.causes().skip(1) {
+ if err.downcast_ref::<Internal>().is_some() {
return false;
}
let m = fs::metadata(path);
if m.as_ref().map(|s| s.is_dir()).unwrap_or(false) {
fs::remove_dir_all(path).chain_err(|| {
- "could not remove build directory"
+ format_err!("could not remove build directory")
})?;
} else if m.is_ok() {
fs::remove_file(path).chain_err(|| {
- "failed to remove build artifact"
+ format_err!("failed to remove build artifact")
})?;
}
Ok(())
use ops::{self, BuildOutput, Executor, DefaultExecutor};
use util::config::Config;
use util::{CargoResult, profile};
-use util::errors::{CargoResultExt, CargoError};
/// Contains information about how a package should be compiled.
#[derive(Debug)]
for member in ws.members() {
for warning in member.manifest().warnings().iter() {
if warning.is_critical {
- let err: CargoResult<_> = Err(CargoError::from(warning.message.to_owned()));
- return err.chain_err(|| {
- format!("failed to parse manifest at `{}`", member.manifest_path().display())
- })
+ let err = format_err!("{}", warning.message);
+ let cx = format_err!("failed to parse manifest at `{}`",
+ member.manifest_path().display());
+ return Err(err.context(cx).into())
} else {
options.config.shell().warn(&warning.message)?
}
let (packages, resolve_with_overrides) = resolve;
if specs.is_empty() {
- return Err(format!("manifest path `{}` contains no package: The manifest is virtual, \
- and the workspace has no members.", ws.current_manifest().display()).into());
- };
+ bail!("manifest path `{}` contains no package: The manifest is virtual, \
+ and the workspace has no members.",
+ ws.current_manifest().display())
+ }
let to_builds = specs.iter().map(|p| {
let pkgid = p.query(resolve_with_overrides.iter())?;
let (packages, resolve_with_overrides) = resolve;
if specs.is_empty() {
- return Err(format!("manifest path `{}` contains no package: The manifest is virtual, \
- and the workspace has no members.", ws.current_manifest().display()).into());
+ bail!("manifest path `{}` contains no package: The manifest is virtual, \
+ and the workspace has no members.",
+ ws.current_manifest().display())
};
let pkgs = specs.iter().map(|p| {
use sources::{GitSource, PathSource, SourceConfigMap};
use util::{Config, internal};
use util::{Filesystem, FileLock};
-use util::errors::{CargoError, CargoResult, CargoResultExt};
+use util::errors::{CargoResult, CargoResultExt};
#[derive(Deserialize, Serialize)]
#[serde(untagged)]
summary.push(format!("Failed to install {} (see error(s) above).", failed.join(", ")));
}
if !succeeded.is_empty() || !failed.is_empty() {
- opts.config.shell().status("\nSummary:", summary.join(" "))?;
+ opts.config.shell().status("Summary", summary.join(" "))?;
}
(!succeeded.is_empty(), !failed.is_empty())
krate, vers, config, is_first_install,
&mut |git| git.read_packages())?
} else if source_id.is_path() {
- let path = source_id.url().to_file_path()
- .map_err(|()| CargoError::from("path sources must have a valid path"))?;
+ let path = source_id.url().to_file_path().map_err(|()| {
+ format_err!("path sources must have a valid path")
+ })?;
let mut src = PathSource::new(&path, source_id, config);
src.update().chain_err(|| {
- format!("`{}` is not a crate root; specify a crate to \
- install from crates.io, or use --path or --git to \
- specify an alternate source", path.display())
+ format_err!("`{}` is not a crate root; specify a crate to \
+ install from crates.io, or use --path or --git to \
+ specify an alternate source", path.display())
})?;
select_pkg(PathSource::new(&path, source_id, config),
krate, vers, config, is_first_install,
} else {
select_pkg(map.load(source_id)?,
krate, vers, config, is_first_install,
- &mut |_| Err("must specify a crate to install from \
- crates.io, or use --path or --git to \
- specify alternate source".into()))?
+ &mut |_| {
+ bail!("must specify a crate to install from \
+ crates.io, or use --path or --git to \
+ specify alternate source")
+ })?
};
let mut td_opt = None;
td.into_path();
}
- CargoError::from(format!("failed to compile `{}`, intermediate artifacts can be \
- found at `{}`", pkg, ws.target_dir().display()))
+ format_err!("failed to compile `{}`, intermediate artifacts can be \
+ found at `{}`", pkg, ws.target_dir().display())
})?;
let binaries: Vec<(&str, &Path)> = compile.binaries.iter().map(|bin| {
let name = bin.file_name().unwrap();
continue
}
fs::copy(src, &dst).chain_err(|| {
- format!("failed to copy `{}` to `{}`", src.display(),
- dst.display())
+ format_err!("failed to copy `{}` to `{}`", src.display(),
+ dst.display())
})?;
}
let dst = dst.join(bin);
config.shell().status("Installing", dst.display())?;
fs::rename(&src, &dst).chain_err(|| {
- format!("failed to move `{}` to `{}`", src.display(),
- dst.display())
+ format_err!("failed to move `{}` to `{}`", src.display(),
+ dst.display())
})?;
installed.bins.push(dst);
}
let dst = dst.join(bin);
config.shell().status("Replacing", dst.display())?;
fs::rename(&src, &dst).chain_err(|| {
- format!("failed to move `{}` to `{}`", src.display(),
- dst.display())
+ format_err!("failed to move `{}` to `{}`", src.display(),
+ dst.display())
})?;
replaced_names.push(bin);
}
// version range, otherwise parse it as a specific version
let first = v.chars()
.nth(0)
- .ok_or("no version provided for the `--vers` flag")?;
+ .ok_or(format_err!("no version provided for the `--vers` flag"))?;
match first {
'<' | '>' | '=' | '^' | '~' => match v.parse::<VersionReq>() {
Ok(v) => Some(v.to_string()),
Err(_) => {
- let msg = format!("the `--vers` provided, `{}`, is \
- not a valid semver version requirement\n\n
- Please have a look at \
- http://doc.crates.io/specifying-dependencies.html \
- for the correct format", v);
- return Err(msg.into());
+ bail!("the `--vers` provided, `{}`, is \
+ not a valid semver version requirement\n\n
+ Please have a look at \
+ http://doc.crates.io/specifying-dependencies.html \
+ for the correct format", v)
}
},
_ => match v.parse::<Version>() {
Ok(v) => Some(format!("={}", v)),
Err(_) => {
- let mut msg = format!("the `--vers` provided, `{}`, is \
- not a valid semver version\n\n\
- historically Cargo treated this \
- as a semver version requirement \
- accidentally\nand will continue \
- to do so, but this behavior \
- will be removed eventually", v);
+ let mut msg = format!("\
+ the `--vers` provided, `{}`, is \
+ not a valid semver version\n\n\
+ historically Cargo treated this \
+ as a semver version requirement \
+ accidentally\nand will continue \
+ to do so, but this behavior \
+ will be removed eventually", v
+ );
// If it is not a valid version but it is a valid version
// requirement, add a note to the warning
None => {
let vers_info = vers.map(|v| format!(" with version `{}`", v))
.unwrap_or_default();
- Err(format!("could not find `{}` in {}{}", name,
- source.source_id(), vers_info).into())
+ Err(format_err!("could not find `{}` in {}{}", name,
+ source.source_id(), vers_info))
}
}
}
(Some(i1), Some(i2)) => {
let mut v = vec![i1, i2];
v.extend(i);
- Err(f(v).into())
+ Err(format_err!("{}", f(v)))
}
(Some(i), None) => Ok(Some(i)),
(None, _) => Ok(None)
}
}
msg.push_str("Add --force to overwrite");
- Err(msg.into())
+ Err(format_err!("{}", msg))
}
fn find_duplicates(dst: &Path,
}
fn read_crate_list(file: &FileLock) -> CargoResult<CrateListingV1> {
- (|| -> CargoResult<_> {
+ let listing = (|| -> CargoResult<_> {
let mut contents = String::new();
file.file().read_to_string(&mut contents)?;
let listing = toml::from_str(&contents).chain_err(|| {
}
}
})().chain_err(|| {
- format!("failed to parse crate metadata at `{}`",
- file.path().to_string_lossy())
- })
+ format_err!("failed to parse crate metadata at `{}`",
+ file.path().to_string_lossy())
+ })?;
+ Ok(listing)
}
fn write_crate_list(file: &FileLock, listing: CrateListingV1) -> CargoResult<()> {
file.write_all(data.as_bytes())?;
Ok(())
})().chain_err(|| {
- format!("failed to write crate metadata at `{}`",
- file.path().to_string_lossy())
- })
+ format_err!("failed to write crate metadata at `{}`",
+ file.path().to_string_lossy())
+ })?;
+ Ok(())
}
pub fn install_list(dst: Option<&str>, config: &Config) -> CargoResult<()> {
}
if !succeeded.is_empty() || !failed.is_empty() {
- config.shell().status("\nSummary:", summary.join(" "))?;
+ config.shell().status("Summary", summary.join(" "))?;
}
!failed.is_empty()
use ops::is_bad_artifact_name;
use util::{GitRepo, HgRepo, PijulRepo, FossilRepo, internal};
use util::{Config, paths};
-use util::errors::{CargoError, CargoResult, CargoResultExt};
+use util::errors::{CargoResult, CargoResultExt};
use toml;
}
let dir_name = path.file_name().and_then(|s| s.to_str()).ok_or_else(|| {
- CargoError::from(format!("cannot create a project with a non-unicode name: {:?}",
- path.file_name().unwrap()))
+ format_err!("cannot create a project with a non-unicode name: {:?}",
+ path.file_name().unwrap())
})?;
if opts.bin {
duplicates_checker.insert(i.target_name.as_ref(), i);
} else {
if let Some(plp) = previous_lib_relpath {
- return Err(format!("cannot have a project with \
- multiple libraries, \
- found both `{}` and `{}`",
- plp, i.relative_path).into());
+ bail!("cannot have a project with \
+ multiple libraries, \
+ found both `{}` and `{}`",
+ plp, i.relative_path)
}
previous_lib_relpath = Some(&i.relative_path);
}
};
mk(config, &mkopts).chain_err(|| {
- format!("Failed to create project `{}` at `{}`",
- name, path.display())
- })
+ format_err!("Failed to create project `{}` at `{}`",
+ name, path.display())
+ })?;
+ Ok(())
}
pub fn init(opts: &NewOptions, config: &Config) -> CargoResult<()> {
};
mk(config, &mkopts).chain_err(|| {
- format!("Failed to create project `{}` at `{}`",
- name, path.display())
- })
+ format_err!("Failed to create project `{}` at `{}`",
+ name, path.display())
+ })?;
+ Ok(())
}
fn strip_rust_affixes(name: &str) -> &str {
config.shell().status("Packaging", pkg.package_id().to_string())?;
dst.file().set_len(0)?;
tar(ws, &src, dst.file(), &filename).chain_err(|| {
- "failed to prepare local package for uploading"
+ format_err!("failed to prepare local package for uploading")
})?;
if opts.verify {
dst.seek(SeekFrom::Start(0))?;
let relative = util::without_prefix(file, root).unwrap();
check_filename(relative)?;
let relative = relative.to_str().ok_or_else(|| {
- format!("non-utf8 path in source directory: {}",
- relative.display())
+ format_err!("non-utf8 path in source directory: {}",
+ relative.display())
})?;
config.shell().verbose(|shell| {
shell.status("Archiving", &relative)
use core::{Package, SourceId, PackageId, EitherManifest};
use util::{self, Config};
-use util::errors::{CargoResult, CargoResultExt, CargoError};
+use util::errors::{CargoResult, CargoError};
use util::important_paths::find_project_manifest_exact;
use util::toml::read_manifest;
if all_packages.is_empty() {
match errors.pop() {
Some(err) => Err(err),
- None => Err(format!("Could not find Cargo.toml in `{}`", path.display()).into()),
+ None => Err(format_err!("Could not find Cargo.toml in `{}`", path.display())),
}
} else {
Ok(all_packages.into_iter().map(|(_, v)| v).collect())
return Ok(())
}
Err(e) => {
- return Err(e).chain_err(|| {
- format!("failed to read directory `{}`", path.display())
- })
+ let cx = format!("failed to read directory `{}`", path.display());
+ let e = CargoError::from(e);
+ return Err(e.context(cx).into())
}
};
for dir in dirs {
use std::path::Path;
use ops::{self, Packages};
-use util::{self, CargoResult, CargoError, ProcessError};
-use util::errors::CargoErrorKind;
+use util::{self, CargoResult, ProcessError};
use core::Workspace;
pub fn run(ws: &Workspace,
1 => ws.members()
.find(|pkg| pkg.name() == xs[0])
.ok_or_else(||
- CargoError::from(
- format!("package `{}` is not a member of the workspace", xs[0]))
+ format_err!("package `{}` is not a member of the workspace", xs[0])
)?,
_ => unreachable!("cargo run supports single package only"),
}
match result {
Ok(()) => Ok(None),
- Err(CargoError(CargoErrorKind::ProcessErrorKind(e), ..)) => Ok(Some(e)),
- Err(e) => Err(e)
+ Err(e) => {
+ let err = e.downcast::<ProcessError>()?;
+ Ok(Some(err))
+ }
}
}
use core::PackageId;
use util::{Freshness, Cfg};
-use util::errors::{CargoResult, CargoResultExt, CargoError};
+use util::errors::{CargoResult, CargoResultExt};
use util::{self, internal, profile, paths};
use util::machine_message;
&mut |err_line| { state.stderr(err_line); Ok(()) },
true,
).map_err(|e| {
- CargoError::from(
- format!("failed to run custom build command for `{}`\n{}",
- pkg_name, e.description()))
+ format_err!("failed to run custom build command for `{}`\n{}",
+ pkg_name, e)
})?;
};
info!("fingerprint error for {}: {}", unit.pkg, ce);
- for cause in ce.iter().skip(1) {
+ for cause in ce.causes().skip(1) {
info!(" cause: {}", cause);
}
}
self.emit_warnings(Some(msg), key, cx)?;
if self.active > 0 {
- error = Some("build failed".into());
+ error = Some(format_err!("build failed"));
handle_error(e, &mut *cx.config.shell());
cx.config.shell().warn(
"build failed, waiting for other \
jobs to finish...")?;
- }
- else {
+ } else {
error = Some(e);
}
}
// the target triple as a Path and then just use the file stem as the
// component for the directory name.
if let Some(triple) = triple {
- path.push(Path::new(triple).file_stem().ok_or_else(|| "target was empty")?);
+ path.push(Path::new(triple).file_stem().ok_or_else(|| {
+ format_err!("target was empty")
+ })?);
}
path.push(dest);
Layout::at(ws.config(), path)
use core::shell::ColorChoice;
use util::{self, ProcessBuilder, machine_message};
use util::{Config, internal, profile, join_paths};
-use util::errors::{CargoResult, CargoResultExt};
+use util::errors::{CargoResult, CargoResultExt, Internal};
use util::Freshness;
use self::job::{Job, Work};
format!("Could not compile `{}`.", name)
})?;
} else {
- exec.exec(rustc, &package_id, &target).map_err(|e| e.into_internal()).chain_err(|| {
- format!("Could not compile `{}`.", name)
- })?;
+ exec.exec(rustc, &package_id, &target)
+ .map_err(Internal::new)
+ .chain_err(|| {
+ format!("Could not compile `{}`.", name)
+ })?;
}
if do_rename && real_name != crate_name {
}
}
state.running(&rustdoc);
- rustdoc.exec().chain_err(|| format!("Could not document `{}`.", name))
+ rustdoc.exec().chain_err(|| format!("Could not document `{}`.", name))?;
+ Ok(())
}))
}
use ops::{self, Compilation};
use util::{self, CargoTestError, Test, ProcessError};
-use util::errors::{CargoResult, CargoErrorKind, CargoError};
+use util::errors::CargoResult;
use core::Workspace;
pub struct TestOptions<'a> {
let result = cmd.exec();
match result {
- Err(CargoError(CargoErrorKind::ProcessErrorKind(e), .. )) => {
+ Err(e) => {
+ let e = e.downcast::<ProcessError>()?;
errors.push((kind.clone(), test.clone(), e));
if !options.no_fail_fast {
break;
}
}
- Err(e) => {
- //This is an unexpected Cargo error rather than a test failure
- return Err(e)
- }
Ok(()) => {}
}
}
config.shell().verbose(|shell| {
shell.status("Running", p.to_string())
})?;
- if let Err(CargoError(CargoErrorKind::ProcessErrorKind(e), .. )) = p.exec() {
+ if let Err(e) = p.exec() {
+ let e = e.downcast::<ProcessError>()?;
errors.push(e);
if !options.no_fail_fast {
return Ok((Test::Doc, errors));
format!("failed to read file: {}", f.path().display())
})?;
- (|| -> CargoResult<Option<Resolve>> {
+ let resolve = (|| -> CargoResult<Option<Resolve>> {
let resolve : toml::Value = cargo_toml::parse(&s, f.path(), ws.config())?;
let v: resolver::EncodableResolve = resolve.try_into()?;
Ok(Some(v.into_resolve(ws)?))
})().chain_err(|| {
format!("failed to parse lock file at: {}", f.path().display())
- })
+ })?;
+ Ok(resolve)
}
pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()> {
}).chain_err(|| {
format!("failed to write {}",
ws.root().join("Cargo.lock").display())
- })
+ })?;
+ Ok(())
}
fn are_equal_lockfiles(mut orig: String, current: &str, ws: &Workspace) -> bool {
use util::config::{self, Config};
use util::paths;
use util::ToUrl;
-use util::errors::{CargoError, CargoResult, CargoResultExt};
+use util::errors::{CargoResult, CargoResultExt};
use util::important_paths::find_root_manifest_for_wd;
pub struct RegistryConfig {
if let Some(ref v) = opts.to_add {
let v = v.iter().map(|s| &s[..]).collect::<Vec<_>>();
let msg = registry.add_owners(&name, &v).map_err(|e| {
- CargoError::from(format!("failed to invite owners to crate {}: {}", name, e))
+ format_err!("failed to invite owners to crate {}: {}", name, e)
})?;
config.shell().status("Owner", msg)?;
let v = v.iter().map(|s| &s[..]).collect::<Vec<_>>();
config.shell().status("Owner", format!("removing {:?} from crate {}",
v, name))?;
- registry.remove_owners(&name, &v).map_err(|e| {
- CargoError::from(format!("failed to remove owners from crate {}: {}", name, e))
+ registry.remove_owners(&name, &v).chain_err(|| {
+ format!("failed to remove owners from crate {}", name)
})?;
}
if opts.list {
- let owners = registry.list_owners(&name).map_err(|e| {
- CargoError::from(format!("failed to list owners of crate {}: {}", name, e))
+ let owners = registry.list_owners(&name).chain_err(|| {
+ format!("failed to list owners of crate {}", name)
})?;
for owner in owners.iter() {
print!("{}", owner.login);
if undo {
config.shell().status("Unyank", format!("{}:{}", name, version))?;
- registry.unyank(&name, &version).map_err(|e| {
- CargoError::from(format!("failed to undo a yank: {}", e))
+ registry.unyank(&name, &version).chain_err(|| {
+ "failed to undo a yank"
})?;
} else {
config.shell().status("Yank", format!("{}:{}", name, version))?;
- registry.yank(&name, &version).map_err(|e| {
- CargoError::from(format!("failed to yank: {}", e))
+ registry.yank(&name, &version).chain_err(|| {
+ "failed to yank"
})?;
}
}
let (mut registry, _) = registry(config, None, index, reg)?;
- let (crates, total_crates) = registry.search(query, limit).map_err(|e| {
- CargoError::from(format!("failed to retrieve search results from the registry: {}", e))
+ let (crates, total_crates) = registry.search(query, limit).chain_err(|| {
+ "failed to retrieve search results from the registry"
})?;
let names = crates.iter()
use sources::ReplacedSource;
use util::{Config, ToUrl};
use util::config::ConfigValue;
-use util::errors::{CargoError, CargoResult, CargoResultExt};
+use util::errors::{CargoResult, CargoResultExt};
#[derive(Clone)]
pub struct SourceConfigMap<'cfg> {
let mut srcs = srcs.into_iter();
let src = srcs.next().ok_or_else(|| {
- CargoError::from(format!("no source URL specified for `source.{}`, need \
- either `registry` or `local-registry` defined",
- name))
+ format_err!("no source URL specified for `source.{}`, need \
+ either `registry` or `local-registry` defined",
+ name)
})?;
if srcs.next().is_some() {
- return Err(format!("more than one source URL specified for \
- `source.{}`", name).into())
+ bail!("more than one source URL specified for `source.{}`", name)
}
let mut replace_with = None;
fn url(cfg: &ConfigValue, key: &str) -> CargoResult<Url> {
let (url, path) = cfg.string(key)?;
- url.to_url().chain_err(|| {
+ let url = url.to_url().chain_err(|| {
format!("configuration key `{}` specified an invalid \
URL (in {})", key, path.display())
- })
+ })?;
+ Ok(url)
}
}
}
fn download(&mut self, id: &PackageId) -> CargoResult<Package> {
self.packages.get(id).map(|p| &p.0).cloned().ok_or_else(|| {
- format!("failed to find package with id: {}", id).into()
+ format_err!("failed to find package with id: {}", id)
})
}
use core::GitReference;
use core::{Package, PackageId, Summary, Registry, Dependency};
use util::Config;
-use util::errors::{CargoError, CargoResult};
+use util::errors::{CargoResult, Internal};
use util::hex::short_hash;
use sources::PathSource;
use sources::git::utils::{GitRemote, GitRevision};
pub fn canonicalize_url(url: &Url) -> CargoResult<Url> {
let mut url = url.clone();
- // cannot-be-a-base-urls are not supported
+ // cannot-be-a-base-urls are not supported
// eg. github.com:rust-lang-nursery/rustfmt.git
if url.cannot_be_a_base() {
- return Err(format!("invalid url `{}`: cannot-be-a-base-URLs are not supported", url).into());
+ bail!("invalid url `{}`: cannot-be-a-base-URLs are not supported", url)
}
// Strip a trailing slash
trace!("updating git source `{:?}`", self.remote);
let repo = self.remote.checkout(&db_path, self.config)?;
- let rev = repo.rev_for(&self.reference).map_err(CargoError::into_internal)?;
+ let rev = repo.rev_for(&self.reference).map_err(Internal::new)?;
(repo, rev)
} else {
(self.remote.db_at(&db_path)?, actual_rev.unwrap())
use core::GitReference;
use util::{ToUrl, internal, Config, network, Progress};
-use util::errors::{CargoResult, CargoResultExt, CargoError};
+use util::errors::{CargoResult, CargoResultExt, CargoError, Internal};
#[derive(PartialEq, Clone, Debug)]
pub struct GitRevision(git2::Oid);
(|| {
let b = self.repo.find_branch(s, git2::BranchType::Local)?;
b.get().target().ok_or_else(|| {
- CargoError::from(format!("branch `{}` did not have a target", s))
+ format_err!("branch `{}` did not have a target", s)
})
})().chain_err(|| {
format!("failed to find branch `{}`", s)
for mut child in repo.submodules()? {
update_submodule(repo, &mut child, cargo_config)
- .map_err(CargoError::into_internal)
+ .map_err(Internal::new)
.chain_err(|| {
format!("failed to update submodule `{}`",
child.name().unwrap_or(""))
// In the case of an authentication failure (where we tried something) then
// we try to give a more helpful error message about precisely what we
// tried.
- res.map_err(CargoError::from).map_err(|e| e.into_internal()).chain_err(|| {
+ let res = res.map_err(Internal::new).chain_err(|| {
let mut msg = "failed to authenticate when downloading \
repository".to_string();
if !ssh_agent_attempts.is_empty() {
}
}
msg
- })
+ })?;
+ Ok(res)
}
fn reset(repo: &git2::Repository,
use core::{Package, PackageId, Summary, SourceId, Source, Dependency, Registry};
use ops;
-use util::{self, CargoError, CargoResult, internal};
+use util::{self, CargoResult, internal};
use util::Config;
pub struct PathSource<'cfg> {
p
};
Pattern::new(pattern).map_err(|e| {
- CargoError::from(format!("could not parse glob pattern `{}`: {}", p, e))
+ format_err!("could not parse glob pattern `{}`: {}", p, e)
})
};
) {
Match::None => Ok(true),
Match::Ignore(_) => Ok(false),
- Match::Whitelist(pattern) => Err(CargoError::from(format!(
+ Match::Whitelist(pattern) => Err(format_err!(
"exclude rules cannot start with `!`: {}",
pattern.original()
- ))),
+ )),
}
} else {
match ignore_include.matched_path_or_any_parents(
) {
Match::None => Ok(false),
Match::Ignore(_) => Ok(true),
- Match::Whitelist(pattern) => Err(CargoError::from(format!(
+ Match::Whitelist(pattern) => Err(format_err!(
"include rules cannot start with `!`: {}",
pattern.original()
- ))),
+ )),
}
}
};
warn!(" found submodule {}", file_path.display());
let rel = util::without_prefix(&file_path, root).unwrap();
let rel = rel.to_str().ok_or_else(|| {
- CargoError::from(format!("invalid utf-8 filename: {}", rel.display()))
+ format_err!("invalid utf-8 filename: {}", rel.display())
})?;
// Git submodules are currently only named through `/` path
// separators, explicitly not `\` which windows uses. Who knew?
use core::{SourceId, Summary, PackageId};
use sources::registry::{RegistryPackage, INDEX_LOCK};
use sources::registry::RegistryData;
-use util::{CargoError, CargoResult, internal, Filesystem, Config};
+use util::{CargoResult, internal, Filesystem, Config};
pub struct RegistryIndex<'cfg> {
source_id: SourceId,
let err = load.load(&root, Path::new(&path), &mut |contents| {
hit_closure = true;
let contents = str::from_utf8(contents).map_err(|_| {
- CargoError::from("registry index file was not valid utf-8")
+ format_err!("registry index file was not valid utf-8")
})?;
ret.reserve(contents.lines().count());
let lines = contents.lines()
// crates.io should also block uploads with these sorts of tarballs,
// but be extra sure by adding a check here as well.
if !entry_path.starts_with(prefix) {
- return Err(format!("invalid tarball downloaded, contains \
- a file at {:?} which isn't under {:?}",
- entry_path, prefix).into())
+ bail!("invalid tarball downloaded, contains \
+ a file at {:?} which isn't under {:?}",
+ entry_path, prefix)
}
// Once that's verified, unpack the entry as usual.
use util::network;
use util::{FileLock, Filesystem, LazyCell};
use util::{Config, Sha256, ToUrl, Progress};
-use util::errors::{CargoErrorKind, CargoResult, CargoResultExt};
+use util::errors::{CargoResult, CargoResultExt, HttpNot200};
pub struct RemoteRegistry<'cfg> {
index_path: Filesystem,
let code = handle.response_code()?;
if code != 200 && code != 0 {
let url = handle.effective_url()?.unwrap_or(&url);
- Err(CargoErrorKind::HttpNot200(code, url.to_string()).into())
+ Err(HttpNot200 { code, url: url.to_string() }.into())
} else {
Ok(())
}
}).chain_err(|| {
format!("failed to query replaced source {}",
self.to_replace)
- })
+ })?;
+ Ok(())
}
fn supports_checksums(&self) -> bool {
self.inner.update().chain_err(|| {
format!("failed to update replaced source {}",
self.to_replace)
- })
+ })?;
+ Ok(())
}
fn download(&mut self, id: &PackageId) -> CargoResult<Package> {
return Some(Ok(Token::String(&self.orig[start+1..end])))
}
}
- return Some(Err("unterminated string in cfg".into()))
+ return Some(Err(format_err!("unterminated string in cfg")))
}
Some((start, ch)) if is_ident_start(ch) => {
while let Some(&(end, ch)) = self.s.peek() {
return Some(Ok(Token::Ident(&self.orig[start..])))
}
Some((_, ch)) => {
- return Some(Err(format!("unexpected character in \
+ return Some(Err(format_err!("unexpected character in \
cfg `{}`, expected parens, \
a comma, an identifier, or \
- a string", ch).into()))
+ a string", ch)))
}
None => return None
}
"couldn't get the current directory of the process"
})?;
let homedir = homedir(&cwd).ok_or_else(|| {
- "Cargo couldn't find your home directory. \
- This probably means that $HOME was not set."
+ format_err!("Cargo couldn't find your home directory. \
+ This probably means that $HOME was not set.")
})?;
Ok(Config::new(shell, cwd, homedir))
}
// The method varies per operating system and might fail; in particular,
// it depends on /proc being mounted on Linux, and some environments
// (like containers or chroots) may not have that available.
- env::current_exe()
- .and_then(|path| path.canonicalize())
- .map_err(CargoError::from)
+ let exe = env::current_exe()?.canonicalize()?;
+ Ok(exe)
}
fn from_argv() -> CargoResult<PathBuf> {
// - an absolute path (e.g. `/usr/local/bin/cargo`).
// In either case, Path::canonicalize will return the full absolute path
// to the target if it exists
- env::args_os()
- .next()
- .ok_or(CargoError::from("no argv[0]"))
+ let argv0 = env::args_os()
.map(PathBuf::from)
- .and_then(|argv0| {
- if argv0.components().count() == 1 {
- probe_path(argv0)
- } else {
- argv0.canonicalize().map_err(CargoError::from)
- }
- })
+ .next()
+ .ok_or(format_err!("no argv[0]"))?;
+ if argv0.components().count() == 1 {
+ probe_path(argv0)
+ } else {
+ Ok(argv0.canonicalize()?)
+ }
}
fn probe_path(argv0: PathBuf) -> CargoResult<PathBuf> {
- let paths = env::var_os("PATH").ok_or(CargoError::from("no PATH"))?;
+ let paths = env::var_os("PATH").ok_or(format_err!("no PATH"))?;
for path in env::split_paths(&paths) {
let candidate = PathBuf::from(path).join(&argv0);
if candidate.is_file() {
// PATH may have a component like "." in it, so we still need to
// canonicalize.
- return candidate.canonicalize().map_err(CargoError::from);
+ return Ok(candidate.canonicalize()?)
}
}
- Err(CargoError::from("no cargo executable candidate found in PATH"))
+ bail!("no cargo executable candidate found in PATH")
}
- from_current_exe()
+ let exe = from_current_exe()
.or_else(|_| from_argv())
- .chain_err(|| "couldn't get the path to cargo executable")
+ .chain_err(|| "couldn't get the path to cargo executable")?;
+ Ok(exe)
}).map(AsRef::as_ref)
}
pub fn set_values(&self, values: HashMap<String, ConfigValue>) -> CargoResult<()> {
if self.values.borrow().is_some() {
- return Err("Config values already found".into());
+ bail!("config values already found")
}
match self.values.fill(values) {
Ok(()) => Ok(()),
- Err(_) => Err("Could not fill values".into()),
+ Err(_) => bail!("could not fill values"),
}
}
pub fn expected<T>(&self, ty: &str, key: &str, val: CV) -> CargoResult<T> {
val.expected(ty, key).map_err(|e| {
- format!("invalid configuration for key `{}`\n{}", key, e).into()
+ format_err!("invalid configuration for key `{}`\n{}", key, e)
})
}
pub fn get_registry_index(&self, registry: &str) -> CargoResult<Url> {
Ok(match self.get_string(&format!("registries.{}.index", registry))? {
Some(index) => index.val.to_url()?,
- None => return Err(CargoError::from(format!("No index found for registry: `{}`", registry)).into()),
+ None => bail!("No index found for registry: `{}`", registry),
})
}
Ok(CV::List(val.into_iter().map(|toml| {
match toml {
toml::Value::String(val) => Ok((val, path.to_path_buf())),
- v => Err(format!("expected string but found {} \
- in list", v.type_str()).into()),
+ v => bail!("expected string but found {} in list",
+ v.type_str()),
}
}).collect::<CargoResult<_>>()?, path.to_path_buf()))
}
}
pub fn expected<T>(&self, wanted: &str, key: &str) -> CargoResult<T> {
- Err(format!("expected a {}, but found a {} for `{}` in {}",
- wanted, self.desc(), key,
- self.definition_path().display()).into())
+ bail!("expected a {}, but found a {} for `{}` in {}",
+ wanted, self.desc(), key,
+ self.definition_path().display())
}
}
// in our history to be sure we pick up that standard location for
// information.
let home = homedir(pwd).ok_or_else(|| {
- CargoError::from("Cargo couldn't find your home directory. \
- This probably means that $HOME was not set.")
+ format_err!("Cargo couldn't find your home directory. \
+ This probably means that $HOME was not set.")
})?;
let config = home.join("config");
if !stash.contains(&config) && fs::metadata(&config).is_ok() {
#![allow(unknown_lints)]
-use std::error::Error;
use std::fmt;
-use std::io;
-use std::num;
use std::process::{Output, ExitStatus};
use std::str;
-use std::string;
use core::TargetKind;
+use failure::{Context, Error, Fail};
-use curl;
-use git2;
-use semver;
-use serde_json;
-use toml;
-use registry;
-use ignore;
-
-error_chain! {
- types {
- CargoError, CargoErrorKind, CargoResultExt, CargoResult;
- }
+pub use failure::Error as CargoError;
+pub type CargoResult<T> = Result<T, Error>;
- links {
- CrateRegistry(registry::Error, registry::ErrorKind);
- }
+pub trait CargoResultExt<T, E> {
+ fn chain_err<F, D>(self, f: F) -> Result<T, Context<D>>
+ where F: FnOnce() -> D,
+ D: fmt::Display + Send + Sync + 'static;
+}
- foreign_links {
- ParseSemver(semver::ReqParseError);
- Semver(semver::SemVerError);
- Ignore(ignore::Error);
- Io(io::Error);
- SerdeJson(serde_json::Error);
- TomlSer(toml::ser::Error);
- TomlDe(toml::de::Error);
- ParseInt(num::ParseIntError);
- ParseBool(str::ParseBoolError);
- Parse(string::ParseError);
- Git(git2::Error);
- Curl(curl::Error);
+impl<T, E> CargoResultExt<T, E> for Result<T, E>
+ where E: Into<Error>,
+{
+ fn chain_err<F, D>(self, f: F) -> Result<T, Context<D>>
+ where F: FnOnce() -> D,
+ D: fmt::Display + Send + Sync + 'static,
+ {
+ self.map_err(|failure| {
+ let context = f();
+ failure.into().context(context)
+ })
}
+}
- errors {
- Internal(err: Box<CargoErrorKind>) {
- description(err.description())
- display("{}", *err)
- }
- ProcessErrorKind(proc_err: ProcessError) {
- description(&proc_err.desc)
- display("{}", &proc_err.desc)
- }
- CargoTestErrorKind(test_err: CargoTestError) {
- description(&test_err.desc)
- display("{}", &test_err.desc)
- }
- HttpNot200(code: u32, url: String) {
- description("failed to get a 200 response")
- display("failed to get 200 response from `{}`, got {}", url, code)
- }
+#[derive(Debug, Fail)]
+#[fail(display = "failed to get 200 response from `{}`, got {}", url, code)]
+pub struct HttpNot200 {
+ pub code: u32,
+ pub url: String,
+}
+
+pub struct Internal {
+ inner: Error,
+}
+
+impl Internal {
+ pub fn new(inner: Error) -> Internal {
+ Internal { inner }
}
}
-impl CargoError {
- pub fn into_internal(self) -> Self {
- CargoError(CargoErrorKind::Internal(Box::new(self.0)), self.1)
+impl Fail for Internal {
+ fn cause(&self) -> Option<&Fail> {
+ self.inner.cause().cause()
}
+}
- fn is_human(&self) -> bool {
- match self.0 {
- CargoErrorKind::Msg(_) |
- CargoErrorKind::TomlSer(_) |
- CargoErrorKind::TomlDe(_) |
- CargoErrorKind::Curl(_) |
- CargoErrorKind::HttpNot200(..) |
- CargoErrorKind::ProcessErrorKind(_) |
- CargoErrorKind::CrateRegistry(_) => true,
- CargoErrorKind::ParseSemver(_) |
- CargoErrorKind::Semver(_) |
- CargoErrorKind::Ignore(_) |
- CargoErrorKind::Io(_) |
- CargoErrorKind::SerdeJson(_) |
- CargoErrorKind::ParseInt(_) |
- CargoErrorKind::ParseBool(_) |
- CargoErrorKind::Parse(_) |
- CargoErrorKind::Git(_) |
- CargoErrorKind::Internal(_) |
- CargoErrorKind::CargoTestErrorKind(_) |
- CargoErrorKind::__Nonexhaustive { .. } => false
- }
+impl fmt::Debug for Internal {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.inner.fmt(f)
}
}
+impl fmt::Display for Internal {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.inner.fmt(f)
+ }
+}
// =============================================================================
// Process errors
-#[derive(Debug)]
+#[derive(Debug, Fail)]
+#[fail(display = "{}", desc)]
pub struct ProcessError {
pub desc: String,
pub exit: Option<ExitStatus>,
// Cargo test errors.
/// Error when testcases fail
-#[derive(Debug)]
+#[derive(Debug, Fail)]
+#[fail(display = "{}", desc)]
pub struct CargoTestError {
pub test: Test,
pub desc: String,
pub exit_code: i32
}
-impl Error for CliError {
- fn description(&self) -> &str {
- self.error.as_ref().map(|e| e.description())
- .unwrap_or("unknown cli error")
- }
-
- fn cause(&self) -> Option<&Error> {
- self.error.as_ref().and_then(|e| e.cause())
- }
-}
-
-impl fmt::Display for CliError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- if let Some(ref error) = self.error {
- error.fmt(f)
- } else {
- self.description().fmt(f)
- }
- }
-}
-
impl CliError {
pub fn new(error: CargoError, code: i32) -> CliError {
- let human = &error.is_human();
- CliError { error: Some(error), exit_code: code, unknown: !human }
+ let unknown = error.downcast_ref::<Internal>().is_some();
+ CliError { error: Some(error), exit_code: code, unknown }
}
pub fn code(code: i32) -> CliError {
}
fn _internal(error: &fmt::Display) -> CargoError {
- CargoError::from_kind(error.to_string().into()).into_internal()
+ Internal::new(format_err!("{}", error)).into()
}
use std::fs::{self, File, OpenOptions};
-use std::io::*;
+use std::io::{Seek, Read, Write, SeekFrom};
use std::io;
use std::path::{Path, PathBuf, Display};
use libc;
use util::Config;
-use util::errors::{CargoResult, CargoResultExt};
+use util::errors::{CargoResult, CargoResultExt, CargoError};
pub struct FileLock {
f: Option<File>,
Err(e) => {
if e.raw_os_error() != lock_contended_error().raw_os_error() {
- return Err(e).chain_err(|| {
- format!("failed to lock file: {}", path.display())
- })
+ let e = CargoError::from(e);
+ let cx = format!("failed to lock file: {}", path.display());
+ return Err(e.context(cx).into())
}
}
}
let msg = format!("waiting for file lock on {}", msg);
config.shell().status_with_color("Blocking", &msg, Cyan)?;
- return block().chain_err(|| {
+ block().chain_err(|| {
format!("failed to lock file: {}", path.display())
- });
+ })?;
+ return Ok(());
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
fn is_on_nfs_mount(path: &Path) -> bool {
pub fn find_project_manifest_exact(pwd: &Path, file: &str) -> CargoResult<PathBuf> {
let manifest = pwd.join(file);
- if fs::metadata(&manifest).is_ok() {
+ if manifest.exists() {
Ok(manifest)
} else {
- Err(format!("Could not find `{}` in `{}`",
- file, pwd.display()).into())
+ bail!("Could not find `{}` in `{}`", file, pwd.display())
}
}
pub use self::cfg::{Cfg, CfgExpr};
pub use self::config::{Config, ConfigValue, homedir};
pub use self::dependency_queue::{DependencyQueue, Fresh, Dirty, Freshness};
-pub use self::errors::{CargoResult, CargoResultExt, CargoError, CargoErrorKind, Test, CliResult};
+pub use self::errors::{CargoResult, CargoResultExt, CargoError, Test, CliResult};
pub use self::errors::{CliError, ProcessError, CargoTestError};
pub use self::errors::{process_error, internal};
pub use self::flock::{FileLock, Filesystem};
-use std;
-use std::error::Error;
-
-use error_chain::ChainedError;
-use util::Config;
-use util::errors::{CargoError, CargoErrorKind, CargoResult};
+use curl;
use git2;
-fn maybe_spurious<E, EKind>(err: &E) -> bool
- where E: ChainedError<ErrorKind=EKind> + 'static {
- //Error inspection in non-verbose mode requires inspecting the
- //error kind to avoid printing Internal errors. The downcasting
- //machinery requires &(Error + 'static), but the iterator (and
- //underlying `cause`) return &Error. Because the borrows are
- //constrained to this handling method, and because the original
- //error object is constrained to be 'static, we're casting away
- //the borrow's actual lifetime for purposes of downcasting and
- //inspecting the error chain
- unsafe fn extend_lifetime(r: &Error) -> &(Error + 'static) {
- std::mem::transmute::<&Error, &Error>(r)
- }
+use failure::Error;
+
+use util::Config;
+use util::errors::{CargoResult, HttpNot200};
- for e in err.iter() {
- let e = unsafe { extend_lifetime(e) };
- if let Some(cargo_err) = e.downcast_ref::<CargoError>() {
- match cargo_err.kind() {
- &CargoErrorKind::Git(ref git_err) => {
- match git_err.class() {
- git2::ErrorClass::Net |
- git2::ErrorClass::Os => return true,
- _ => ()
- }
- }
- &CargoErrorKind::Curl(ref curl_err)
- if curl_err.is_couldnt_connect() ||
- curl_err.is_couldnt_resolve_proxy() ||
- curl_err.is_couldnt_resolve_host() ||
- curl_err.is_operation_timedout() ||
- curl_err.is_recv_error() => {
- return true
- }
- &CargoErrorKind::HttpNot200(code, ref _url) if 500 <= code && code < 600 => {
- return true
- }
+fn maybe_spurious(err: &Error) -> bool {
+ for e in err.causes() {
+ if let Some(git_err) = e.downcast_ref::<git2::Error>() {
+ match git_err.class() {
+ git2::ErrorClass::Net |
+ git2::ErrorClass::Os => return true,
_ => ()
}
}
+ if let Some(curl_err) = e.downcast_ref::<curl::Error>() {
+ if curl_err.is_couldnt_connect() ||
+ curl_err.is_couldnt_resolve_proxy() ||
+ curl_err.is_couldnt_resolve_host() ||
+ curl_err.is_operation_timedout() ||
+ curl_err.is_recv_error() {
+ return true
+ }
+ }
+ if let Some(not_200) = e.downcast_ref::<HttpNot200>() {
+ if 500 <= not_200.code && not_200.code < 600 {
+ return true
+ }
+ }
}
false
}
#[test]
fn with_retry_repeats_the_call_then_works() {
//Error HTTP codes (5xx) are considered maybe_spurious and will prompt retry
- let error1 = CargoErrorKind::HttpNot200(501, "Uri".to_string()).into();
- let error2 = CargoErrorKind::HttpNot200(502, "Uri".to_string()).into();
+ let error1 = HttpNot200 { code: 501, url: "Uri".to_string() }.into();
+ let error2 = HttpNot200 { code: 502, url: "Uri".to_string() }.into();
let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
let config = Config::default().unwrap();
let result = with_retry(&config, || results.pop().unwrap());
#[test]
fn with_retry_finds_nested_spurious_errors() {
+ use util::CargoError;
+
//Error HTTP codes (5xx) are considered maybe_spurious and will prompt retry
//String error messages are not considered spurious
- let error1 : CargoError = CargoErrorKind::HttpNot200(501, "Uri".to_string()).into();
- let error1 = CargoError::with_chain(error1, "A non-spurious wrapping err");
- let error2 = CargoError::from_kind(CargoErrorKind::HttpNot200(502, "Uri".to_string()));
- let error2 = CargoError::with_chain(error2, "A second chained error");
+ let error1 = CargoError::from(HttpNot200 { code: 501, url: "Uri".to_string() });
+ let error1 = CargoError::from(error1.context("A non-spurious wrapping err"));
+ let error2 = CargoError::from(HttpNot200 { code: 502, url: "Uri".to_string() });
+ let error2 = CargoError::from(error2.context("A second chained error"));
let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
let config = Config::default().unwrap();
let result = with_retry(&config, || results.pop().unwrap());
use std::path::{Path, PathBuf, Component};
use util::{internal, CargoResult};
-use util::errors::CargoResultExt;
+use util::errors::{CargoResultExt, Internal, CargoError};
pub fn join_paths<T: AsRef<OsStr>>(paths: &[T], env: &str) -> CargoResult<OsString> {
- env::join_paths(paths.iter()).or_else(|e| {
- let paths = paths.iter().map(Path::new).collect::<Vec<_>>();
- Err(internal(format!("failed to join path array: {:?}", paths))).chain_err(|| {
- format!("failed to join search paths together: {}\n\
- Does ${} have an unterminated quote character?",
- e, env)
- })
- })
+ let err = match env::join_paths(paths.iter()) {
+ Ok(paths) => return Ok(paths),
+ Err(e) => e,
+ };
+ let paths = paths.iter().map(Path::new).collect::<Vec<_>>();
+ let err = CargoError::from(err);
+ let explain = Internal::new(format_err!("failed to join path array: {:?}", paths));
+ let err = CargoError::from(err.context(explain));
+ let more_explain = format!("failed to join search paths together\n\
+ Does ${} have an unterminated quote character?",
+ env);
+ return Err(err.context(more_explain).into())
}
pub fn dylib_path_envvar() -> &'static str {
}
pub fn read_bytes(path: &Path) -> CargoResult<Vec<u8>> {
- (|| -> CargoResult<_> {
+ let res = (|| -> CargoResult<_> {
let mut ret = Vec::new();
let mut f = File::open(path)?;
if let Ok(m) = f.metadata() {
Ok(ret)
})().chain_err(|| {
format!("failed to read `{}`", path.display())
- })
+ })?;
+ Ok(res)
}
pub fn write(path: &Path, contents: &[u8]) -> CargoResult<()> {
Ok(())
})().chain_err(|| {
format!("failed to write `{}`", path.display())
- })
+ })?;
+ Ok(())
}
pub fn append(path: &Path, contents: &[u8]) -> CargoResult<()> {
Ok(())
})().chain_err(|| {
internal(format!("failed to write `{}`", path.display()))
- })
+ })?;
+ Ok(())
}
#[cfg(unix)]
pub fn path2bytes(path: &Path) -> CargoResult<&[u8]> {
match path.as_os_str().to_str() {
Some(s) => Ok(s.as_bytes()),
- None => Err(format!("invalid non-unicode path: {}",
- path.display()).into())
+ None => Err(format_err!("invalid non-unicode path: {}",
+ path.display())),
}
}
use std::str;
match str::from_utf8(bytes) {
Ok(s) => Ok(PathBuf::from(s)),
- Err(..) => Err("invalid non-unicode path".into()),
+ Err(..) => Err(format_err!("invalid non-unicode path")),
}
}
use shell_escape::escape;
use util::{CargoResult, CargoResultExt, CargoError, process_error, read2};
-use util::errors::CargoErrorKind;
/// A builder object for an external process, similar to `std::process::Command`.
#[derive(Clone, Debug)]
pub fn exec(&self) -> CargoResult<()> {
let mut command = self.build_command();
let exit = command.status().chain_err(|| {
- CargoErrorKind::ProcessErrorKind(
- process_error(&format!("could not execute process `{}`",
- self.debug_string()), None, None))
+ process_error(&format!("could not execute process `{}`",
+ self.debug_string()), None, None)
})?;
if exit.success() {
Ok(())
} else {
- Err(CargoErrorKind::ProcessErrorKind(process_error(
+ Err(process_error(
&format!("process didn't exit successfully: `{}`", self.debug_string()),
- Some(&exit), None)).into())
+ Some(&exit), None).into())
}
}
let mut command = self.build_command();
let error = command.exec();
- Err(CargoError::with_chain(error,
- CargoErrorKind::ProcessErrorKind(process_error(
- &format!("could not execute process `{}`", self.debug_string()), None, None))))
+ Err(CargoError::from(error).context(
+ process_error(
+ &format!("could not execute process `{}`", self.debug_string()),
+ None,
+ None,
+ ),
+ ).into())
}
/// On unix, executes the process using the unix syscall `execvp`, which will block this
let mut command = self.build_command();
let output = command.output().chain_err(|| {
- CargoErrorKind::ProcessErrorKind(
- process_error(
- &format!("could not execute process `{}`", self.debug_string()),
- None, None))
+ process_error(
+ &format!("could not execute process `{}`", self.debug_string()),
+ None,
+ None)
})?;
if output.status.success() {
Ok(output)
} else {
- Err(CargoErrorKind::ProcessErrorKind(process_error(
+ Err(process_error(
&format!("process didn't exit successfully: `{}`", self.debug_string()),
- Some(&output.status), Some(&output))).into())
+ Some(&output.status), Some(&output)).into())
}
}
})?;
child.wait()
})().chain_err(|| {
- CargoErrorKind::ProcessErrorKind(
- process_error(&format!("could not execute process `{}`",
- self.debug_string()),
- None, None))
+ process_error(
+ &format!("could not execute process `{}`",
+ self.debug_string()),
+ None,
+ None)
})?;
let output = Output {
stdout: stdout,
None
};
if !output.status.success() {
- return Err(CargoErrorKind::ProcessErrorKind(process_error(
+ return Err(process_error(
&format!("process didn't exit successfully: `{}`", self.debug_string()),
- Some(&output.status), to_print)).into())
+ Some(&output.status), to_print).into())
} else if let Some(e) = callback_error {
- return Err(CargoError::with_chain(e,
- CargoErrorKind::ProcessErrorKind(process_error(
- &format!("failed to parse process output: `{}`", self.debug_string()),
- Some(&output.status), to_print))))
+ let cx = process_error(
+ &format!("failed to parse process output: `{}`", self.debug_string()),
+ Some(&output.status),
+ to_print,
+ );
+ return Err(CargoError::from(e).context(cx).into())
}
}
use semver::Version;
+use util::errors::CargoResult;
pub trait ToSemver {
- fn to_semver(self) -> Result<Version, String>;
+ fn to_semver(self) -> CargoResult<Version>;
}
impl ToSemver for Version {
- fn to_semver(self) -> Result<Version, String> { Ok(self) }
+ fn to_semver(self) -> CargoResult<Version> { Ok(self) }
}
impl<'a> ToSemver for &'a str {
- fn to_semver(self) -> Result<Version, String> {
+ fn to_semver(self) -> CargoResult<Version> {
match Version::parse(self) {
Ok(v) => Ok(v),
- Err(..) => Err(format!("cannot parse '{}' as a semver", self)),
+ Err(..) => Err(format_err!("cannot parse '{}' as a semver", self)),
}
}
}
impl<'a> ToSemver for &'a String {
- fn to_semver(self) -> Result<Version, String> {
+ fn to_semver(self) -> CargoResult<Version> {
(**self).to_semver()
}
}
impl<'a> ToSemver for &'a Version {
- fn to_semver(self) -> Result<Version, String> {
+ fn to_semver(self) -> CargoResult<Version> {
Ok(self.clone())
}
}
impl<'a> ToUrl for &'a str {
fn to_url(self) -> CargoResult<Url> {
Url::parse(self).map_err(|s| {
- format!("invalid url `{}`: {}", self, s).into()
+ format_err!("invalid url `{}`: {}", self, s)
})
}
}
impl<'a> ToUrl for &'a Path {
fn to_url(self) -> CargoResult<Url> {
Url::from_file_path(self).map_err(|()| {
- format!("invalid path url `{}`", self.display()).into()
+ format_err!("invalid path url `{}`", self.display())
})
}
}
trace!("read_manifest; path={}; source-id={}", path.display(), source_id);
let contents = paths::read(path)?;
- do_read_manifest(&contents, path, source_id, config).chain_err(|| {
+ let ret = do_read_manifest(&contents, path, source_id, config).chain_err(|| {
format!("failed to parse manifest at `{}`", path.display())
- })
+ })?;
+ Ok(ret)
}
fn do_read_manifest(contents: &str,
return Ok(ret)
}
- Err(first_error).chain_err(|| {
- "could not parse input as TOML"
- })
+ let first_error = CargoError::from(first_error);
+ Err(first_error.context("could not parse input as TOML").into())
}
type TomlLibTarget = TomlTarget;
let project = me.project.as_ref().or_else(|| me.package.as_ref());
let project = project.ok_or_else(|| {
- CargoError::from("no `package` section found.")
+ format_err!("no `package` section found")
})?;
let package_name = project.name.trim();
if package_name.is_empty() {
- bail!("package name cannot be an empty string.")
+ bail!("package name cannot be an empty string")
}
let pkgid = project.to_package_id(source_id)?;
let mut dep = replacement.to_dependency(spec.name(), cx, None)?;
{
let version = spec.version().ok_or_else(|| {
- CargoError::from(format!("replacements must specify a version \
- to replace, but `{}` does not",
- spec))
+ format_err!("replacements must specify a version \
+ to replace, but `{}` does not",
+ spec)
})?;
dep.set_version_req(VersionReq::exact(version));
}
[dependencies]
curl = "0.4"
-error-chain = "0.11.0"
+failure = "0.1.1"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
extern crate curl;
extern crate url;
#[macro_use]
-extern crate error_chain;
+extern crate failure;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::prelude::*;
-use std::io::{self, Cursor};
+use std::io::Cursor;
use curl::easy::{Easy, List};
-
use url::percent_encoding::{percent_encode, QUERY_ENCODE_SET};
-error_chain! {
- foreign_links {
- Curl(curl::Error);
- Io(io::Error);
- Json(serde_json::Error);
- }
-
- errors {
- NotOkResponse(code: u32, headers: Vec<String>, body: Vec<u8>){
- description("failed to get a 200 OK response")
- display("failed to get a 200 OK response, got {}
-headers:
- {}
-body:
-{}", code, headers.join("\n ", ), String::from_utf8_lossy(body))
- }
- NonUtf8Body {
- description("response body was not utf-8")
- display("response body was not utf-8")
- }
- Api(errs: Vec<String>) {
- display("api errors: {}", errs.join(", "))
- }
- Unauthorized {
- display("unauthorized API access")
- }
- TokenMissing{
- display("no upload token found, please run `cargo login`")
- }
- NotFound {
- display("cannot find crate")
- }
- }
- }
+pub type Result<T> = std::result::Result<T, failure::Error>;
pub struct Registry {
host: String,
let token = match self.token.as_ref() {
Some(s) => s,
- None => return Err(Error::from_kind(ErrorKind::TokenMissing)),
+ None => bail!("no upload token found, please run `cargo login`"),
};
self.handle.put(true)?;
self.handle.url(&url)?;
if authorized == Auth::Authorized {
let token = match self.token.as_ref() {
Some(s) => s,
- None => return Err(Error::from_kind(ErrorKind::TokenMissing)),
+ None => bail!("no upload token found, please run `cargo login`"),
};
headers.append(&format!("Authorization: {}", token))?;
}
match handle.response_code()? {
0 => {} // file upload url sometimes
200 => {}
- 403 => return Err(Error::from_kind(ErrorKind::Unauthorized)),
- 404 => return Err(Error::from_kind(ErrorKind::NotFound)),
- code => return Err(Error::from_kind(ErrorKind::NotOkResponse(code, headers, body))),
+ 403 => bail!("received 403 unauthorized response code"),
+ 404 => bail!("received 404 not found response code"),
+ code => {
+ bail!("failed to get a 200 OK response, got {}\n\
+ headers:\n\
+ \t{}\n\
+ body:\n\
+ {}",
+ code,
+ headers.join("\n\t"),
+ String::from_utf8_lossy(&body))
+ }
}
let body = match String::from_utf8(body) {
Ok(body) => body,
- Err(..) => return Err(Error::from_kind(ErrorKind::NonUtf8Body)),
+ Err(..) => bail!("response body was not valid utf-8"),
};
match serde_json::from_str::<ApiErrorList>(&body) {
Ok(errors) => {
- return Err(Error::from_kind(ErrorKind::Api(errors
- .errors
- .into_iter()
- .map(|s| s.detail)
- .collect())))
+ let errors = errors.errors.into_iter().map(|s| s.detail);
+ bail!("api errors: {}", errors.collect::<Vec<_>>().join(", "))
}
Err(..) => {}
}
[ERROR] failed to parse manifest at `[..]`
Caused by:
- package name cannot be an empty string.
+ package name cannot be an empty string
"))
}
use std::env;
-use std::error::Error;
use std::ffi::OsStr;
use std::fmt;
use std::fs;
use url::Url;
use hamcrest as ham;
use cargo::util::ProcessBuilder;
-use cargo::util::{CargoError, CargoErrorKind, ProcessError};
+use cargo::util::{ProcessError};
use support::paths::CargoPathExt;
let mut matches = 0;
- while let Some(..) = {
+ while let Some(..) = {
if self.diff_lines(a.clone(), e.clone(), true).is_empty() {
matches += 1;
}
a.next()
} {}
-
+
ham::expect(matches == number,
format!("expected to find {} occurences:\n\
{}\n\n\
match res {
Ok(out) => self.match_output(&out),
- Err(CargoError(CargoErrorKind::ProcessErrorKind(
- ProcessError { output: Some(ref out), .. }), ..)) => {
- self.match_output(out)
- }
Err(e) => {
+ let err = e.downcast_ref::<ProcessError>();
+ if let Some(&ProcessError { output: Some(ref out), .. }) = err {
+ return self.match_output(out)
+ }
let mut s = format!("could not exec process {}: {}", process, e);
- match e.cause() {
- Some(cause) => s.push_str(&format!("\ncaused by: {}",
- cause.description())),
- None => {}
+ for cause in e.causes() {
+ s.push_str(&format!("\ncaused by: {}", cause));
}
Err(s)
}
("[INSTALLING]", " Installing"),
("[REPLACING]", " Replacing"),
("[UNPACKING]", " Unpacking"),
+ ("[SUMMARY]", " Summary"),
("[EXE]", if cfg!(windows) {".exe"} else {""}),
("[/]", if cfg!(windows) {"\\"} else {"/"}),
];
use cargotest::support::{project, execs, path2url};
use cargotest::support::registry::Package;
use hamcrest::{assert_that, existing_file, existing_dir, is_not};
-use cargo::util::{CargoError, CargoErrorKind};
+use cargo::util::ProcessError;
#[test]
fn simple() {
.build();
let error = p.cargo("doc").exec_with_output().err().unwrap();
- if let CargoError(CargoErrorKind::ProcessErrorKind(perr), ..) = error {
+ if let Ok(perr) = error.downcast::<ProcessError>() {
let output = perr.output.unwrap();
let stderr = str::from_utf8(&output.stderr).unwrap();
[FINISHED] release [optimized] target(s) in [..]
[INSTALLING] {home}[..]bin[..]bar[..]
error: could not find `baz` in registry `[..]`
-
-Summary: Successfully installed foo, bar! Failed to install baz (see error(s) above).
+[SUMMARY] Successfully installed foo, bar! Failed to install baz (see error(s) above).
warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
error: some crates failed to install
",
execs().with_status(0).with_stderr(&format!("\
[REMOVING] {home}[..]bin[..]foo[..]
[REMOVING] {home}[..]bin[..]bar[..]
-
-Summary: Successfully uninstalled foo, bar!
+[SUMMARY] Successfully uninstalled foo, bar!
",
home = cargo_home().display())));
assert_that(cargo_process("install").arg("foo").arg("--version").arg("0.1.1").arg("--vers").arg("0.1.2"),
execs().with_status(101).with_stderr_contains("\
-error: Invalid arguments.
+error: invalid arguments
"));
}
execs().with_status(101).with_stderr(&format!("\
[REMOVING] {home}[..]bin[..]foo[..]
error: package id specification `bar` matched no packages
-
-Summary: Successfully uninstalled foo! Failed to uninstall bar (see error(s) above).
+[SUMMARY] Successfully uninstalled foo! Failed to uninstall bar (see error(s) above).
error: some packages failed to uninstall
",
home = cargo_home().display())));