use std::vec::Vec;
use core::{Source, SourceId, Summary, Dependency, PackageId, Package};
-use util::{CargoResult,Config};
+use util::{CargoResult, ChainError, Config, human};
pub trait Registry {
fn query(&mut self, name: &Dependency) -> CargoResult<Vec<Summary>>;
fn load(&mut self, namespace: &SourceId,
override: bool) -> CargoResult<()> {
- let mut source = namespace.load(&try!(Config::new()));
- let dst = if override {&mut self.overrides} else {&mut self.summaries};
- // Ensure the source has fetched all necessary remote data.
- try!(source.update());
+ (|| {
+ let mut source = namespace.load(&try!(Config::new()));
+ let dst = if override {&mut self.overrides} else {&mut self.summaries};
- // Get the summaries
- for summary in (try!(source.list())).iter() {
- assert!(!dst.contains(summary), "duplicate summaries");
- dst.push(summary.clone());
- // self.summaries.push(summary.clone());
- }
+ // Ensure the source has fetched all necessary remote data.
+ try!(source.update());
- // Save off the source
- self.sources.push(source);
+ // Get the summaries
+ for summary in (try!(source.list())).iter() {
+ assert!(!dst.contains(summary), "duplicate summaries");
+ dst.push(summary.clone());
+ // self.summaries.push(summary.clone());
+ }
- // Track that the source has been searched
- self.searched.push(namespace.clone());
+ // Save off the source
+ self.sources.push(source);
- Ok(())
+ // Track that the source has been searched
+ self.searched.push(namespace.clone());
+
+ Ok(())
+ }).chain_error(|| human(format!("Unable to update {}", namespace)))
}
}
impl Registry for PackageRegistry {
fn query(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
- let overrides = try!(self.overrides.query(dep));
+ let overrides = try!(self.overrides.query(dep)); // this can never fail in practice
if overrides.is_empty() {
// Ensure the requested namespace is loaded
+use std::fmt;
+use std::fmt::{Show, Formatter};
+
use url;
use url::Url;
+
use core::{Summary,Package,PackageId};
use sources::{PathSource,GitSource};
use util::{Config,CargoResult};
RegistryKind
}
-#[deriving(Show,Clone,PartialEq)]
+#[deriving(Clone,PartialEq)]
pub struct SourceId {
pub kind: SourceKind,
pub url: Url
}
+impl Show for SourceId {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ match *self {
+ SourceId { kind: PathKind, ref url } => {
+ try!(write!(f, "{}", url))
+ },
+ SourceId { kind: GitKind(ref reference), ref url } => {
+ try!(write!(f, "{}", url));
+ if reference.as_slice() != "master" {
+ try!(write!(f, " (ref={})", reference));
+ }
+ },
+ SourceId { kind: RegistryKind, .. } => {
+ // TODO: Central registry vs. alternates
+ try!(write!(f, "the package registry"));
+ }
+ }
+
+ Ok(())
+ }
+}
+
impl SourceId {
pub fn new(kind: SourceKind, url: Url) -> SourceId {
SourceId { kind: kind, url: url }
macro_rules! cargo_try (
($expr:expr) => ({
use util::CargoError;
- try!($expr.map_err(|err| err.to_error()))
+ match $expr.map_err(|err| err.to_error()) {
+ Ok(val) => val,
+ Err(err) => return Err(err)
+ }
})
)
use std::collections::HashMap;
use serialize::{Encodable,Encoder};
use toml;
-use util::{CargoResult, ChainError, Require, internal, human};
+use util::{CargoResult, CargoError, ChainError, Require, internal, human};
pub struct Config {
home_path: Path
use std::io::process::{Command,ProcessOutput,ProcessExit,ExitStatus,ExitSignal};
use std::io::IoError;
use std::fmt;
-use std::fmt::{Show, Formatter};
+use std::fmt::{Show, Formatter, FormatError};
use std::str;
use TomlError = toml::Error;
impl Show for Box<CargoError> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- try!(write!(f, "{}", self.description()));
+ cargo_try!(write!(f, "{}", self.description()));
Ok(())
}
}
fn chain_error<E: CargoError>(self, callback: || -> E) -> CargoResult<T> ;
}
+impl<'a, T> ChainError<T> for ||:'a -> CargoResult<T> {
+ fn chain_error<E: CargoError>(self, callback: || -> E) -> CargoResult<T> {
+ self().map_err(|err| callback().with_cause(err))
+ }
+}
+
impl<T, E: CargoError> BoxError<T> for Result<T, E> {
fn box_error(self) -> CargoResult<T> {
self.map_err(|err| err.box_error())
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().with_cause(err)
- })
+ self.map_err(|err| callback().with_cause(err))
}
}
from_error!(TomlError)
+impl CargoError for FormatError {
+ fn description(&self) -> String {
+ "formatting failed".to_str()
+ }
+}
+
+from_error!(FormatError)
+
pub struct ProcessError {
pub msg: String,
pub command: String,
Some(ExitStatus(i)) | Some(ExitSignal(i)) => i.to_str(),
None => "never executed".to_str()
};
- try!(write!(f, "{} (status={})", self.msg, exit));
+ cargo_try!(write!(f, "{} (status={})", self.msg, exit));
match self.output {
Some(ref out) => {
match str::from_utf8(out.output.as_slice()) {
Some(s) if s.trim().len() > 0 => {
- try!(write!(f, "\n--- stdout\n{}", s));
+ cargo_try!(write!(f, "\n--- stdout\n{}", s));
}
Some(..) | None => {}
}
match str::from_utf8(out.error.as_slice()) {
Some(s) if s.trim().len() > 0 => {
- try!(write!(f, "\n--- stderr\n{}", s));
+ cargo_try!(write!(f, "\n--- stderr\n{}", s));
}
Some(..) | None => {}
}
pub exit_code: uint
}
+impl CargoError for CliError {
+ fn description(&self) -> String {
+ self.error.to_str()
+ }
+}
+
+from_error!(CliError)
+
impl CliError {
pub fn new<S: Str>(error: S, code: uint) -> CliError {
let error = human(error.as_slice().to_str());
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::{CliError, ProcessError};
+pub use self::errors::{CliError, FromError, ProcessError};
pub use self::errors::{process_error, internal_error, internal, human};
pub use self::paths::realpath;
Ok(ref stat) if stat.kind != io::TypeSymlink => break,
Ok(..) => {
followed += 1;
- let path = try!(fs::readlink(&result));
+ let path = cargo_try!(fs::readlink(&result));
result.pop();
result.push(path);
}
impl Show for ProcessBuilder {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- try!(write!(f, "`{}", self.program));
+ cargo_try!(write!(f, "`{}", self.program));
if self.args.len() > 0 {
- try!(write!(f, " {}", self.args.connect(" ")));
+ cargo_try!(write!(f, " {}", self.args.connect(" ")));
}
write!(f, "`")
let msg = || format!("Could not execute process `{}`",
self.debug_string());
- let exit = try!(command.status().map_err(|_| {
+ let exit = cargo_try!(command.status().map_err(|_| {
process_error(msg(), &command, None, None)
}));
let msg = || format!("Could not execute process `{}`",
self.debug_string());
- let output = try!(command.output().map_err(|_| {
+ let output = cargo_try!(command.output().map_err(|_| {
process_error(msg(), &command, None, None)
}));
pub fn to_manifest(contents: &[u8],
source_id: &SourceId) -> CargoResult<(Manifest, Vec<Path>)> {
- let root = try!(toml::parse_from_bytes(contents).map_err(|_| {
+ let root = cargo_try!(toml::parse_from_bytes(contents).map_err(|_| {
human("Cargo.toml is not valid Toml")
}));
- let toml = try!(toml_to_manifest(root).map_err(|_| {
+ let toml = cargo_try!(toml_to_manifest(root).map_err(|_| {
human("Cargo.toml is not a valid manifest")
}));
let deps = match deps {
Some(deps) => {
- let table = try!(deps.get_table().require(|| {
+ let table = cargo_try!(deps.get_table().require(|| {
human("dependencies must be a table")
})).clone();
let mut details = HashMap::<String, String>::new();
for (k, v) in table.iter() {
- let v = try!(v.get_str().require(|| {
+ let v = cargo_try!(v.get_str().require(|| {
human("dependency values must be string")
}));
details.insert(k.clone(), v.clone());
}
- let version = try!(details.find_equiv(&"version")
+ let version = cargo_try!(details.find_equiv(&"version")
.require(|| {
human("dependencies must include a version")
})).clone();
}
};
- deps.push(try!(Dependency::parse(n.as_slice(),
+ deps.push(cargo_try!(Dependency::parse(n.as_slice(),
version.as_slice(),
&source_id)))
}